تم إنشاؤها بواسطة GH-MD-TOC
Sobjectizer هو واحد من عدد قليل من المنصات المتقاطعة ويفتح "أطر الممثل" لـ C ++. لكن SoBjectizer لا يدعم نموذج الممثل فحسب ، بل يقوم أيضًا بنشر طراز Subscribe وقنوات تشبه CSP. الهدف من Sobjectizer هو تبسيط كبير لتطوير التطبيقات المتزامنة والمتعددة مؤشرات الترابط في C ++.
يسمح SoBjectizer بإنشاء تطبيق متزامن كمجموعة من الكائنات التي تتفاعل مع بعضها البعض من خلال الرسائل غير المتزامنة. يتولى إرسال الرسائل ويوفر سياق عمل لمعالجة الرسائل. ويسمح بضبط هذه الأشياء من خلال توفير مختلف المرسلين الجاهدين للاستخدام.
نضج . يعتمد Sobjectizer على الأفكار التي تم طرحها في 1995-2000. ويجري تطوير Sobjectizer نفسه منذ عام 2002. تم تطوير Sobjectizer-5 باستمرار منذ عام 2010.
استقرار . منذ البداية ، تم استخدام SoBjectizer للتطبيقات المهمة للأعمال ، ولا يزال بعضها يستخدم في الإنتاج. إن كسر التغييرات في SoBjectizer نادرة ونقترب معهم بعناية فائقة.
منصة العرض . يعمل Sobjectizer على Windows و Linux و FreeBSD و MacOS و Android.
سهل الاستخدام . يوفر Sobjectizer سهلة الفهم وسهلة الاستخدام مع الكثير من الأمثلة في توزيع Sobjectizer والكثير من المعلومات في ويكي المشروع.
حر . يتم توزيع Sobjectizer بموجب ترخيص BSD-3-Cause ، بحيث يمكن استخدامه في تطوير برامج تجارية خاصة مجانًا.
غالبًا ما تتم مقارنة SoBjectizer بأدوات مثل لبنات إنشاء Thinding Intel ، وتدفق المهام ، و HPX ، وشبهها. هذه المقارنة ليست عديمة الفائدة.
تهدف جميع هذه الأدوات إلى استخدام المهام من منطقة الحوسبة المتوازية: فهي تسمح بتقليل الوقت الحسابي عن طريق استخدام العديد من نوى وحدة المعالجة المركزية. على سبيل المثال ، يمكنك إعادة توحيد ملف الفيديو الخاص بك من تنسيق إلى آخر في غضون ساعة واحدة على قلب وحدة المعالجة المركزية ، من خلاله يستغرق 15 دقيقة فقط على أربعة نوى. هذا هو الهدف الرئيسي للحوسبة المتوازية.
يهدف Sobjectizer إلى منطقة مختلفة قليلاً: الحوسبة المتزامنة. الهدف الرئيسي من SoBjectizer هو تبسيط القيام بالعديد من المهام المختلفة في وقت واحد. في بعض الأحيان لا توجد حاجة لاستخدام أكثر من مجرد وحدة المعالجة المركزية واحدة لذلك. ولكن إذا كان هناك العديد من نوى وحدة المعالجة المركزية ، فإن Sobjectizer يجعل معالجة تلك المهام والتفاعل بينهما أسهل بكثير.
الجزء الصعب هو حقيقة أن الحوسبة المتوازية والمتزامنة تستخدم نفس آليات التزامن والكرات البدائية (مثل الخيوط ، الطفرة ، الذرة ، وما إلى ذلك) تحت الغطاء. ولكن من وجهة نظر الرؤية عالية المستوى ، يتم استخدام الحوسبة المتزامنة والمتزامنة لمهام مختلفة للغاية.
كأمثلة للتطبيقات التي تم أو يمكن تنفيذها على رأس Sobjectizer ، يمكننا سرد الوكيل المتعدد مؤشرات الترابط ، ونظام التحكم التلقائي ، ومساعد MQ ، وخادم قاعدة البيانات ، وما إلى ذلك.
هذا مثال كلاسيكي "مرحبًا ، العالم" معبر عنه باستخدام وكلاء Sobjectizer:
# include < so_5/all.hpp >
class hello_actor final : public so_5:: agent_t {
public:
using so_5:: agent_t :: agent_t ;
void so_evt_start () override {
std::cout << " Hello, World! " << std::endl;
// Finish work of example.
so_deregister_agent_coop_normally ();
}
};
int main () {
// Launch SObjectizer.
so_5::launch ([](so_5:: environment_t & env) {
// Add a hello_actor instance in a new cooperation.
env. register_agent_as_coop ( env. make_agent <hello_actor>() );
});
return 0 ;
}دعونا نلقي نظرة على مثال أكثر إثارة للاهتمام مع اثنين من الوكلاء وتبادل الرسائل بينهما. إنه مثال مشهور آخر لأطر الممثلين ، "Ping-Pong":
# include < so_5/all.hpp >
struct ping {
int counter_;
};
struct pong {
int counter_;
};
class pinger final : public so_5:: agent_t {
so_5:: mbox_t ponger_;
void on_pong ( mhood_t <pong> cmd) {
if (cmd-> counter_ > 0 )
so_5::send<ping>(ponger_, cmd-> counter_ - 1 );
else
so_deregister_agent_coop_normally ();
}
public:
pinger ( context_t ctx) : so_5:: agent_t { std::move (ctx)} {}
void set_ponger ( const so_5:: mbox_t mbox) { ponger_ = mbox; }
void so_define_agent () override {
so_subscribe_self (). event ( &pinger::on_pong );
}
void so_evt_start () override {
so_5::send<ping>(ponger_, 1000 );
}
};
class ponger final : public so_5:: agent_t {
const so_5:: mbox_t pinger_;
int pings_received_{};
public:
ponger ( context_t ctx, so_5:: mbox_t pinger)
: so_5:: agent_t { std::move (ctx)}
, pinger_{ std::move (pinger)}
{}
void so_define_agent () override {
so_subscribe_self (). event (
[ this ]( mhood_t <ping> cmd) {
++pings_received_;
so_5::send<pong>(pinger_, cmd-> counter_ );
});
}
void so_evt_finish () override {
std::cout << " pings received: " << pings_received_ << std::endl;
}
};
int main () {
so_5::launch ([](so_5:: environment_t & env) {
env. introduce_coop ([](so_5:: coop_t & coop) {
auto pinger_actor = coop. make_agent <pinger>();
auto ponger_actor = coop. make_agent <ponger>(
pinger_actor-> so_direct_mbox ());
pinger_actor-> set_ponger (ponger_actor-> so_direct_mbox ());
});
});
return 0 ;
}جميع الوكلاء في الكود أعلاه يعملون على نفس مؤشر ترابط العمل. كيفية ربطهم بمواضيع عمل مختلفة؟
إنه بسيط للغاية. فقط استخدم مرسلًا مناسبًا:
int main () {
so_5::launch ([](so_5:: environment_t & env) {
env. introduce_coop (
so_5::disp::active_obj::make_dispatcher (env). binder (),
[](so_5:: coop_t & coop) {
auto pinger_actor = coop. make_agent <pinger>();
auto ponger_actor = coop. make_agent <ponger>(
pinger_actor-> so_direct_mbox ());
pinger_actor-> set_ponger (ponger_actor-> so_direct_mbox ());
});
});
return 0 ;
}يدعم Sobjectizer النموذج/النموذج الفرعي عبر مربعات الرسائل متعددة المنتجات/متعددة المستهلكين. سيتم استلام رسالة تم إرسالها إلى مربع الرسائل هذا من قبل جميع المشتركين من نوع الرسالة:
# include < so_5/all.hpp >
using namespace std ::literals ;
struct acquired_value {
std::chrono::steady_clock::time_point acquired_at_;
int value_;
};
class producer final : public so_5:: agent_t {
const so_5:: mbox_t board_;
so_5:: timer_id_t timer_;
int counter_{};
struct acquisition_time final : public so_5:: signal_t {};
void on_timer ( mhood_t <acquisition_time>) {
// Publish the next value for all consumers.
so_5::send<acquired_value>(
board_, std::chrono::steady_clock::now (), ++counter_);
}
public:
producer ( context_t ctx, so_5:: mbox_t board)
: so_5:: agent_t { std::move (ctx)}
, board_{ std::move (board)}
{}
void so_define_agent () override {
so_subscribe_self (). event (&producer::on_timer);
}
void so_evt_start () override {
// Agent will periodically recive acquisition_time signal
// without initial delay and with period of 750ms.
timer_ = so_5::send_periodic<acquisition_time>(* this , 0ms, 750ms);
}
};
class consumer final : public so_5:: agent_t {
const so_5:: mbox_t board_;
const std::string name_;
void on_value ( mhood_t <acquired_value> cmd) {
std::cout << name_ << " : " << cmd-> value_ << std::endl;
}
public:
consumer ( context_t ctx, so_5:: mbox_t board, std::string name)
: so_5:: agent_t { std::move (ctx)}
, board_{ std::move (board)}
, name_{ std::move (name)}
{}
void so_define_agent () override {
so_subscribe (board_). event (&consumer::on_value);
}
};
int main () {
so_5::launch ([](so_5:: environment_t & env) {
auto board = env. create_mbox ();
env. introduce_coop ([board](so_5:: coop_t & coop) {
coop. make_agent <producer>(board);
coop. make_agent <consumer>(board, " first " s);
coop. make_agent <consumer>(board, " second " s);
});
std::this_thread::sleep_for ( std::chrono::seconds ( 4 ));
env. stop ();
});
return 0 ;
}جميع الوكلاء في Sobjectizer هي آلات الحالة المحدودة. يتم دعم جميع وظائف آلات الدول المحدودة الهرمية تقريبًا (HSM): وراثي الحالات والمعالجات ، وميراث ON_ENTER/ON_EXIT ، ومهلة الدولة ، وتاريخ الحالة العميقة والضحلة ، باستثناء الحالات المتعامدة.
دعونا نرى كيف يمكن للوكيل الذي ينفذ أن يبدو Statechart التالي:

هذا مثال بسيط للغاية يوضح وكيل لـ Statechart الموضح أعلاه:
# include < so_5/all.hpp >
using namespace std ::literals ;
class blinking_led final : public so_5:: agent_t {
state_t off{ this }, blinking{ this },
blink_on{ initial_substate_of{ blinking } },
blink_off{ substate_of{ blinking } };
public :
struct turn_on_off : public so_5 :: signal_t {};
blinking_led ( context_t ctx) : so_5:: agent_t { std::move (ctx)} {
this >>= off;
off. just_switch_to <turn_on_off>(blinking);
blinking. just_switch_to <turn_on_off>(off);
blink_on
. on_enter ([]{ std::cout << " ON " << std::endl; })
. on_exit ([]{ std::cout << " off " << std::endl; })
. time_limit (1250ms, blink_off);
blink_off
. time_limit (750ms, blink_on);
}
};
int main ()
{
so_5::launch ([](so_5:: environment_t & env) {
so_5:: mbox_t m;
env. introduce_coop ([&](so_5:: coop_t & coop) {
auto led = coop. make_agent < blinking_led >();
m = led-> so_direct_mbox ();
});
const auto pause = []( auto duration) {
std::this_thread::sleep_for (duration);
};
std::cout << " Turn blinking on for 10s " << std::endl;
so_5::send<blinking_led::turn_on_off>(m);
pause (10s);
std::cout << " Turn blinking off for 5s " << std::endl;
so_5::send<blinking_led::turn_on_off>(m);
pause (5s);
std::cout << " Turn blinking on for 5s " << std::endl;
so_5::send<blinking_led::turn_on_off>(m);
pause (5s);
std::cout << " Stopping... " << std::endl;
env. stop ();
} );
return 0 ;
}يسمح Sobjectizer بكتابة تطبيقات متزامنة حتى بدون وكلاء في الداخل. يمكن استخدام الخيوط العادية والقنوات التي تشبه CSP فقط.
هذا هو تطبيق ping-pong بشكل واضح (يرجى ملاحظة أن Main () ليس آمنًا للاستثناء):
# include < so_5/all.hpp >
struct ping {
int counter_;
};
struct pong {
int counter_;
};
void pinger_proc (so_5:: mchain_t self_ch, so_5:: mchain_t ping_ch) {
so_5::send<ping>(ping_ch, 1000 );
// Read all message until channel will be closed.
so_5::receive ( so_5::from (self_ch). handle_all (),
[&](so_5:: mhood_t <pong> cmd) {
if (cmd-> counter_ > 0 )
so_5::send<ping>(ping_ch, cmd-> counter_ - 1 );
else {
// Channels have to be closed to break `receive` calls.
so_5::close_drop_content (so_5::exceptions_enabled, self_ch);
so_5::close_drop_content (so_5::exceptions_enabled, ping_ch);
}
});
}
void ponger_proc (so_5:: mchain_t self_ch, so_5:: mchain_t pong_ch) {
int pings_received{};
// Read all message until channel will be closed.
so_5::receive ( so_5::from (self_ch). handle_all (),
[&](so_5:: mhood_t <ping> cmd) {
++pings_received;
so_5::send<pong>(pong_ch, cmd-> counter_ );
});
std::cout << " pings received: " << pings_received << std::endl;
}
int main () {
so_5:: wrapped_env_t sobj;
auto pinger_ch = so_5::create_mchain (sobj);
auto ponger_ch = so_5::create_mchain (sobj);
std::thread pinger{pinger_proc, pinger_ch, ponger_ch};
std::thread ponger{ponger_proc, ponger_ch, pinger_ch};
ponger. join ();
pinger. join ();
return 0 ;
}يوفر SoBjectizer وظيفة SELECT () تشبه عبارة SELECT الخاصة بـ Golang. تتيح هذه الوظيفة انتظار الرسائل الواردة من عدة سلاسل للرسائل. كما يسمح بانتظار استعداد سلاسل الرسائل لقبول رسالة صادرة جديدة. لذلك حدد () يسمح بإجراء المكالمات غير المحظورة () مع التعامل مع الرسائل الواردة بينما تكون سلسلة الرسائل المستهدفة ممتلئة.
يوجد مثال حساب فيبوناتشي يستخدم SELECT () كآلية الضغط الخلفي (سينتظر مؤشر ترابط منتج الأرقام إذا لم يقرأ مؤشر ترابط قارئ الأرقام الرقم السابق بعد). لاحظ أيضًا أن الوظيفة الرئيسية () في هذا المثال آمنة من الاستثناء.
# include < so_5/all.hpp >
# include < chrono >
using namespace std ;
using namespace std ::chrono_literals ;
using namespace so_5 ;
struct quit {};
void fibonacci ( mchain_t values_ch, mchain_t quit_ch )
{
int x = 0 , y = 1 ;
mchain_select_result_t r;
do
{
r = select (
from_all (). handle_n ( 1 ),
// Sends a new message of type 'int' with value 'x' inside
// when values_ch is ready for a new outgoing message.
send_case ( values_ch, message_holder_t < int >:: make (x),
[&x, &y] { // This block of code will be called after the send().
auto old_x = x;
x = y; y = old_x + y;
} ),
// Receive a 'quit' message from quit_ch if it is here.
receive_case ( quit_ch, [](quit){} ) );
}
// Continue the loop while we send something and receive nothing.
while ( r. was_sent () && !r. was_handled () );
}
int main ()
{
wrapped_env_t sobj;
thread fibonacci_thr;
auto thr_joiner = auto_join ( fibonacci_thr );
// The chain for Fibonacci number will have limited capacity.
auto values_ch = create_mchain ( sobj, 1s, 1 ,
mchain_props:: memory_usage_t ::preallocated,
mchain_props:: overflow_reaction_t ::abort_app );
auto quit_ch = create_mchain ( sobj );
auto ch_closer = auto_close_drop_content ( values_ch, quit_ch );
fibonacci_thr = thread{ fibonacci, values_ch, quit_ch };
// Read the first 10 numbers from values_ch.
receive ( from ( values_ch ). handle_n ( 10 ),
// And show every number to the standard output.
[]( int v ) { cout << v << endl; } );
send< quit >( quit_ch );
}يمكن العثور على مزيد من المعلومات حول Sobjectizer في القسم المقابل من ويكي للمشروع.
هناك مشروع مصاحب منفصل So5Extra يحتوي على الكثير من الأشياء المفيدة المختلفة مثل المرسلات المستندة إلى ASIO ، وأنواع إضافية من MOBONDs ، و TIMER القابلة للإلغاء ، والطلبات المتزامنة ، والمزيد.
على سبيل المثال ، هناك كيف يبدو التفاعل المتزامن (باستخدام so_5::extra::sync Stuff):
# include < so_5_extra/sync/pub.hpp >
# include < so_5/all.hpp >
// Short alias for convenience.
namespace sync_ns = so_5::extra::sync;
using namespace std ::chrono_literals ;
// The type of service provider.
class service_provider_t final : public so_5:: agent_t
{
public :
using so_5:: agent_t :: agent_t ;
void so_define_agent () override
{
so_subscribe_self (). event (
[]( sync_ns:: request_mhood_t < int , std::string> cmd ) {
// Transform the incoming value, convert the result
// to string and send the resulting string back.
cmd-> make_reply ( std::to_string (cmd-> request () * 2 ) );
} );
}
};
// The type of service consumer.
class consumer_t final : public so_5:: agent_t
{
// Message box of the service provider.
const so_5:: mbox_t m_service;
public :
consumer_t ( context_t ctx, so_5:: mbox_t service )
: so_5:: agent_t { std::move (ctx) }
, m_service{ std::move (service) }
{}
void so_evt_start () override
{
// Issue a request and wait for the result no more than 500ms.
auto result = sync_ns::request_reply< int , std::string>(
// The destination for the request.
m_service,
// Max waiting time.
500ms,
// Request's value.
4 );
std::cout << " The result: " << result << std::endl;
so_deregister_agent_coop_normally ();
}
};
int main ()
{
so_5::launch ( [](so_5:: environment_t & env) {
env. introduce_coop (
// Every agent should work on its own thread.
so_5::disp::active_obj::make_dispatcher ( env ). binder (),
[](so_5:: coop_t & coop) {
auto service_mbox = coop. make_agent < service_provider_t >()
-> so_direct_mbox ();
coop. make_agent < consumer_t >( service_mbox );
} );
} );
}يهدف Sobjectizer نفسه إلى أن يكون مشروعًا صغيرًا نسبيًا دون تبعيات خارجية. SO5EXTRA ليس لديه هذا القيد. هذا هو السبب في تنفيذ المرسلات المستندة إلى ASIO والبنية التحتية للبيئة في So5Extra ، وليس في Sobjectizer.
خاصية مهمة أخرى من Sobjectizer هي الاستقرار. نحن نحاول الحفاظ على Sobjectizer مستقرًا قدر الإمكان ، ولكن هناك حاجة لتجربة بعض الميزات الجديدة ، حتى لو لم نعرف بعد مدى نجاحها وطلبها. يعد So5Extra مكانًا جيدًا لتجربة ميزات جديدة ، ويمكن نقل بعضها إلى Sobjectizer مع مرور الوقت.
لذلك إذا لم تجد ميزة مفيدة في Sobjectizer ، فلنحاول النظر إلى So5Extra. ربما هو موجود بالفعل.
Sobjectizer هو إطار إرسال الرسائل في العملية. لا تدعم التطبيقات الموزعة خارج الصندوق. ولكن يمكن استخدام الأدوات والمكتبات الخارجية في هذه الحالة. يرجى إلقاء نظرة على تجربة Mosquitto_Transport: https://github.com/stiffstream/mosquitto_transport
يمكن التحقق من SoBjectizer من جيثب. يمكن تنزيل المحفوظات التي تحتوي على رمز مصدر Sobjectizer من GitHub أو من SourceForge.
هناك طريقتان لبناء Sobjectizer. أول واحد باستخدام أداة MXX_RU. الثاني باستخدام Cmake.
ملحوظة. منذ V.5.5.15.2 هناك دعم من منصة Android. بناء لنظام Android ممكن عن طريق CMake فقط. انظر القسم المقابل أدناه.
يمكن أيضًا تثبيت Sobjectizer واستخدامها عبر مديري التبعية VCPKG و Conan . انظر الأقسام المناسبة أدناه.
يتطلب 5.8 فرع من Sobjectizer C ++ 17.
إذا كنت بحاجة إلى دعم لـ C ++ 14 أو C ++ 11 ، فحاول النظر إلى الإصدارات القديمة من Sobjectizer على SourceForge. أو اتصل بـ STIPTSTREAM لمناقشة نقل SOBJESIZER-5.8 إلى معايير C ++ الأقدم.
ملحوظة. هذه طريقة قياسية لبناء Sobjectizer. يتم استخدام هذه الطريقة في عملية تطوير Sobjectizer.
لبناء Sobjectizer ، من الضروري استخدام لغة Ruby وأداة MXX_RU. قم بتثبيت Ruby ثم قم بتثبيت MXX_RU عبر أمر Rubygems:
gem install Mxx_ruإذا تم تثبيت MXX_RU بالفعل ، فيرجى التحديث إلى الإصدار 1.6.14.6 على الأقل:
gem update Mxx_ruيمكن الحصول على Sobjectizer من مستودع GIT على Github:
git clone https://github.com/stiffstream/sobjectizerلبناء Sobjectizer:
cd sobjectizer/dev
ruby build.rbسيتم بناء مكتبة ثابتة ومشتركة لـ Sobjectizer. سيتم وضع المكتبات في دليل الهدف/الإصدار الفرعي.
إذا كنت ترغب في بناء مكتبة مشتركة فقط:
cd sobjectizer/dev
ruby so_5/prj.rbأو إذا كنت ترغب في بناء مكتبة ثابتة فقط:
cd sobjectizer/dev
ruby so_5/prj_s.rbلبناء Sobjectizer مع جميع الاختبارات والعينات:
cd sobjectizer/dev
ruby build_all.rbيرجى ملاحظة أنه تحت FreeBSD قد يكون من الضروري تحديد متغير بيئة LD_Library_Path. ويمكن أن يكون تسلسل أوامر البناء الفعلي تحت FreeBSD كما يلي:
cd sobjectizer/dev
export LD_LIBRARY_PATH=target/release
ruby build_all.rbلبناء وثائق HTML-Format لـ SoBjectizer ، يعد أداة doxygen ضرورية. إذا تم تثبيته ثم:
cd sobjectizer/doxygen
doxygenسيتم وضع ملفات HTML التي تم إنشاؤها في Sobjectizer/DEV/DOC/HTML.
ملحوظة. إذا لم تحدد MXX_RU_CPP_TOOLSET بواسطة نفسك ، فسيحاول MXX_RU اكتشاف مجموعة أدوات C ++ تلقائيًا. إذا كنت ترغب في استخدام برنامج التحويل البرمجي C ++ الذي لا يكون افتراضيًا في نظامك ، فيرجى تحديد متغير بيئة MXX_RU_CPP_TOOLSET يدويًا. يمكن أن تبدو مثل:
export MXX_RU_CPP_TOOLSET= " clang_linux compiler_name=clang++-6 linker_name=clang++-6 "مزيد من المعلومات حول ضبط MXX_RU لاحتياجاتك يمكنك العثور عليها في الوثائق المقابلة.
لبناء Sobjectizer عبر cmake ، من الضروري الحصول على cmake وبعض المعرفة بكيفية استخدامه. الإجراء التالي هو مجرد مظاهرة. لمزيد من المعلومات التفصيلية حول نظام بناء cmake لـ sobjectizer ، انظر Dev/cmake/cmakequickhowto.txt
للحصول على وإنشاء SOBJESIZER تحت Linux/FreeBSD في تشغيل سطر الأوامر:
git clone https://github.com/stiffstream/sobjectizer
cd sobjectizer
mkdir cmake_build
cd cmake_build
cmake -DCMAKE_INSTALL_PREFIX=target -DCMAKE_BUILD_TYPE=Release ../dev
cmake --build . --config Release
cmake --build . --config Release --target installستؤدي هذه الأوامر إلى إنشاء جميع Makefile اللازمة ، ثم بناء SoBjectizer. إذا كان من الضروري إنشاء أمثلة واختبارات أيضًا ، فاستخدم
cmake -DBUILD_ALL=ON -DCMAKE_INSTALL_PREFIX=target ../devعندما "قم بتثبيت" منتهية ".
يدعم نظام إنشاء CMake حاليًا هذه الخيارات:
SOBJECTIZER_BUILD_STATIC . تمكين بناء sobjectizer كمكتبة ثابتة [افتراضي: ON]SOBJECTIZER_BUILD_SHARED . تمكين بناء sobjectizer كمكتبة مشتركة [افتراضي: ON]BUILD_ALL . قم بتمكين أمثلة البناء والاختبارات [الافتراضي: OFF]BUILD_EXAMPLES . تمكين بناء أمثلة [افتراضي: OFF]BUILD_TESTS . تمكين اختبارات البناء [الافتراضي: OFF] يرجى ملاحظة أنه إذا تم تشغيل BUILD_ALL أو BUILD_EXAMPLES أو BUILD_TESTS ، فيجب تشغيل كل من SOBJECTIZER_BUILD_STATIC و SOBJECTIZER_BUILD_SHARED . وهذا يعني أنه إذا تم إيقاف تشغيل SOBJECTIZER_BUILD_STATIC أو SOBJECTIZER_BUILD_SHARED ، فيجب إيقاف تشغيل BUILD_ALL / BUILD_EXAMPLES / BUILD_TESTS .
لبناء Sobjectizer تحت Windows بواسطة MS Visual Studio 2013 من سطر الأوامر:
git clone https://github.com/stiffstream/sobjectizer
cd sobjectizer
mkdir cmake_build
cd cmake_build
cmake -DCMAKE_INSTALL_PREFIX=target -DCMAKE_BUILD_TYPE=Release -G " Visual Studio 15 2017 " ../dev
cmake --build . --config Release
cmake --build . --config Release --target install إذا كان من الضروري إنشاء أمثلة أيضًا ، فاستخدم BUILD_ALL في Cmake Invocation:
cmake -DCMAKE_INSTALL_PREFIX=target -DCMAKE_BUILD_TYPE=Release -DBUILD_ALL=ON -G " Visual Studio 15 2017 " ../dev نظرًا لأن V.5.5.24 يوفر SoBjectizer ملفات sobjectizer-config.cmake. يتم تثبيت هذه الملفات تلقائيًا في المجلد الفرعي <target>/lib/cmake/sobjectizer . يسمح باستخدام SoBjectizer عبر أمر Find_Package الخاص بـ Cmake.
بناء لنظام Android ممكن من خلال Android NDK أو Crystax NDK الطازجة إلى حد ما.
تحتاج إلى تثبيت Android SDK و Android NDK في نظامك. وكذلك نسخة مناسبة من cmake. تحتاج أيضًا إلى تعيين متغيرات البيئة بشكل صحيح ANDROID_HOME و ANDROID_NDK . ثم يمكنك إصدار الأوامر التالية:
git clone https://github.com/stiffstream/sobjectizer
cd sobjectizer
mkdir cmake_build
cd cmake_build
cmake -DBUILD_ALL -DCMAKE_INSTALL_PREFIX=target -DCMAKE_BUILD_TYPE=Release
-DCMAKE_TOOLCHAIN_FILE= ${ANDROID_NDK} /build/cmake/android.toolchain.cmake
-G Ninja
-DANDROID_ABI=arm64-v8a
-DANDROID_NDK= ${ANDROID_NDK}
-DANDROID_NATIVE_API_LEVEL=23
-DANDROID_TOOLCHAIN=clang
../dev
cmake --build . --config=Release
cmake --build . --config=Release --target installتحتاج إلى Crystax NDK v.10.4.0 أو أعلى مثبت بالفعل في نظامك. يستخدم Cmake لبناء Sobjectizer:
git clone https://github.com/stiffstream/sobjectizer
cd sobjectizer
mkdir cmake_build
cd cmake_build
export NDK=/path/to/the/crystax-ndk
cmake -DBUILD_ALL -DCMAKE_INSTALL_PREFIX=result -DCMAKE_TOOLCHAIN_FILE= $NDK /cmake/toolchain.cmake -DANDROID_ABI=arm64-v8a ../dev
make
make test
make installلاستخدام SoBjectizer عبر VCPKG ، من الضروري القيام بالخطوات التالية.
قم بتثبيت حزمة sobjectizer :
vcpkg install sobjectizerأضف الأسطر التالية إلى ملف cmakelists.txt الخاص بك:
find_package (sobjectizer CONFIG REQUIRED)
target_link_libraries (your_target sobjectizer::SharedLib) # or sobjectizer::StaticLibملحوظة. منذ فبراير 2021 تتوفر إصدارات جديدة من Sobjectizer عبر Conan-Center فقط.
لاستخدام Sobjectizer عبر Conan ، من الضروري إضافة Sobjectizer إلى conanfile.txt من مشروعك:
[requires]
sobjectizer/5.8.0
قد يكون من الضروري أيضًا تحديد الخيار shared لـ Sobjectizer. على سبيل المثال ، لبناء Sobjectizer كمكتبة ثابتة:
[options]
sobjectizer:shared=False
تثبيت تبعيات لمشروعك:
conan install SOME_PATH --build=missing
...
include ( ${CMAKE_BINARY_DIR} /conanbuildinfo.cmake)
conan_basic_setup()
...
target_link_libraries (your_target ${CONAN_LIBS} )يتم توزيع Sobjectizer ضمن ترخيص BSD من 3 أبناء. للحصول على معلومات الترخيص ، يرجى الاطلاع على ملف الترخيص.