Creado por GH-MD-TOC
Sobjectizer es uno de los pocos "marcos de actores" multiplataforma y OpenSource para C ++. Pero Sobjectizer admite no solo el modelo de actor, sino también publicar el modelo de suscripción y los canales similares a CSP. El objetivo de Sobjectizer es la simplificación significativa del desarrollo de aplicaciones concurrentes y multiproceso en C ++.
Sobjectizer permite la creación de una aplicación concurrente como un conjunto de objetos de agente que interactúan entre sí a través de mensajes asíncronos. Maneja el envío de mensajes y proporciona un contexto de trabajo para el procesamiento de mensajes. Y permite sintonizar esas cosas suministrando varios despachadores listos para usar.
Madurez . Sobjectizer se basa en ideas que se han presentado en 1995-2000. Y se está desarrollando Sobjectizer en sí desde 2002. Sobjectizer-5 se evoluciona continuamente desde 2010.
Estabilidad . Desde el comienzo, se utilizó el soberjector para aplicaciones críticas de negocios, y algunos de ellos todavía se están utilizando en producción. Los cambios en el soberjector son raros y nos acercamos a ellos con mucho cuidado.
Platforma cruzada . Sobjectizer se ejecuta en Windows, Linux, FreeBSD, MacOS y Android.
Fácil de usar . Sobjectizer proporciona API fácil de entender y fácil de usar con muchos ejemplos en el distributivo del Sobjectizador y mucha información en el wiki del proyecto.
Gratis . Sobjectizer se distribuye bajo la licencia de cláusula BSD-3, por lo que se puede utilizar en el desarrollo de software comercial patentado de forma gratuita.
El Sobjectizer a menudo se compara con herramientas como bloques de construcción de enhebramiento Intel, flujo de tareas, HPX y similares a ellas. Tal comparación es simplemente inútil.
Todas esas herramientas están destinadas a ser utilizadas para resolver tareas del área informática paralela: permiten reducir el tiempo computacional utilizando varios núcleos de CPU. Por ejemplo, puede volver a codificar su archivo de video de un formato a otro dentro de una hora en un núcleo de CPU, ya que solo toma 15 minutos en cuatro núcleos. Ese es el objetivo principal de la computación paralela.
Sobjectizer está destinado a un área ligeramente diferente: informática concurrente. El objetivo principal de Sobjectizer es la simplificación de hacer muchas tareas diferentes a la vez. A veces no hay necesidad de usar más de un núcleo de CPU para eso. Pero si hay varios núcleos de CPU, entonces Sobjectizer facilita mucho el manejo de esas tareas y la interacción entre ellos.
La parte difícil es el hecho de que la computación paralela y concurrente usa los mismos mecanismos y primitivos de concurrencia (como hilos, mutexes, atomics, etc.) debajo del capó. Pero desde el punto de vista de alto nivel, se utilizan la informática paralela y concurrente para tareas muy diferentes.
Como ejemplos de aplicaciones que se implementaron o podían implementarse en la parte superior del Sobjectizer, podemos enumerar el servidor proxy multithreaded, el sistema de control automático, el corredor MQ, el servidor de bases de datos, etc.
Este es un ejemplo clásico "Hola, mundo" expresado mediante el uso de agentes de 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 ;
}Veamos un ejemplo más interesante con dos agentes e intercambio de mensajes entre ellos. Es otro ejemplo famoso para los marcos de actores, "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 ;
}Todos los agentes en el código anterior están trabajando en el mismo hilo de trabajo. ¿Cómo vincularlos a diferentes hilos de trabajo?
Es muy simple. Solo use un despachador apropiado:
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 admite Pub/Sub Model a través de cuadros de mensajes de múltiples productores/multi-consumo. Todos los suscriptores recibirán un mensaje enviado a ese cuadro de mensaje de ese tipo de mensaje:
# 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 ;
}Todos los agentes en Sobjectizer son máquinas de estado finito. Se respaldan casi todas las funcionalidades de las máquinas jerárquicas de estado finito (HSM): la herencia de los estados y los manejadores, los manejadores ON_ENTER/ON_EXIT, los tiempos de espera del estado, la historia estatal profunda y poco profunda, excepto los estados ortogonales.
Veamos cómo puede verse un agente que implementa el siguiente statechart:

Este es un ejemplo muy simple que demuestra un agente para el statechart que se muestra arriba:
# 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 permite escribir aplicaciones concurrentes incluso sin agentes dentro. Solo se pueden usar hilos simples y canales tipo CSP.
Esta es la implementación simple de Ping-Pong (Tenga en cuenta que Main () no es Safe de excepción):
# 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 proporciona una función select () que es similar a la instrucción SELECT de Golang. Esta función permite esperar mensajes entrantes de varias cadenas de mensajes. También permite esperar la preparación de las cadenas de mensajes para aceptar un nuevo mensaje saliente. Entonces, select () permite realizar llamadas SEND () sin bloquear con el manejo de mensajes entrantes mientras la cadena de mensajes de destino está llena.
Hay un ejemplo de cálculo de Fibonacci que usa select () como el mecanismo de retroceso (el subproceso del productor de números esperará si el hilo del lector de números aún no lee el número anterior). Tenga en cuenta también que la función Main () en este ejemplo es a la vista de excepción.
# 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 );
}Se puede encontrar más información sobre Sobjectizer en la sección correspondiente de la wiki del proyecto.
Hay un proyecto complementario separado SO5EXTRA que contiene muchas cosas útiles como despachadores con sede en ASIO, tipos adicionales de mboxes, temporizador revocable, solicitudes sincrónicas y más.
Por ejemplo, existe cómo se ve la interacción sincrónica (usando cosas so_5::extra::sync )::
# 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 en sí está destinado a ser un proyecto relativamente pequeño sin dependencias externas. SO5EXTRA no tiene esta restricción. Es por eso que los despachadores y las infraestructuras ambientales basadas en ASIO se implementan en SO5EXTRA, no en el Sobjectizador.
Otra propiedad significativa de Sobjectizer es la estabilidad. Estamos tratando de mantener el Sobjetizador lo más estable posible, pero es necesario probar algunas características nuevas, incluso si aún no sabemos cuán exitosos y exigidos serán. SO5EXTRA es un buen lugar para experimentar con nuevas características, algunas de ellas podrían moverse al Sobjetador con el tiempo.
Entonces, si no encuentra una característica útil en el Sobjectizer, intentemos ver SO5EXTRA. Tal vez ya esté ahí.
Sobjectizer es un marco de envío de mensajes en proceso. No admite aplicaciones distribuidas solo fuera de caja. Pero las herramientas y bibliotecas externas se pueden usar en ese caso. Eche un vistazo a nuestro experimento Mosquitto_Transport: https://github.com/stiffstream/mosquitto_transport
Se puede verificar el Sobjectizer desde GitHub. Los archivos con el código fuente de Sobjectizer se pueden descargar desde GitHub o desde SourceForge.
Hay dos formas de construir el sobrenegador. El primero usando la herramienta MXX_RU. El segundo usando Cmake.
NOTA. Desde V.5.5.15.2 hay un soporte de la plataforma Android. Construir para Android es posible solo por CMake. Consulte la sección correspondiente a continuación.
Sobjectizer también se puede instalar y utilizar a través de los gerentes de dependencia VCPKG y Conan . Consulte las secciones apropiadas a continuación.
La rama de 5.8 del sobrenegador requiere C ++ 17.
Si necesita soporte para C ++ 14 o C ++ 11, intente buscar versiones más antiguas de Sobjectizer en SourceForge. O comuníquese con Stiffstream para discutir el portamiento de Sobjectizer-5.8 a los estándares más antiguos de C ++.
NOTA. Esta es una forma estándar para construir el sobrenegador. De esta manera se utiliza en el proceso de desarrollo de Sobjetizador.
Para construir Sobjectizer, es necesario usar el lenguaje Ruby y la herramienta MXX_RU. Instale Ruby y luego instale mxx_ru a través del comando Rubygems:
gem install Mxx_ruSi ya tiene instalado MXX_RU, actualice al menos a la versión 1.6.14.6:
gem update Mxx_ruSe puede obtener el sobrilizador del repositorio de Git en GitHub:
git clone https://github.com/stiffstream/sobjectizerPara construir Sobjectizador:
cd sobjectizer/dev
ruby build.rbSe construirá biblioteca estática y compartida para Sobjectizer. Las bibliotecas se colocarán en el subdirectorio de destino/liberación.
Si desea construir la biblioteca acaba de compartir:
cd sobjectizer/dev
ruby so_5/prj.rbO si quieres construir solo la biblioteca estática:
cd sobjectizer/dev
ruby so_5/prj_s.rbPara construir el soberjector con todas las pruebas y muestras:
cd sobjectizer/dev
ruby build_all.rbTenga en cuenta que en FreeBSD podría ser necesario definir la variable de entorno LD_Library_Path. Y la secuencia de comando de compilación real en FreeBSD podría ser la siguiente:
cd sobjectizer/dev
export LD_LIBRARY_PATH=target/release
ruby build_all.rbPara construir la documentación de formato HTML para Sobjectizer, la herramienta Doxygen es necesaria. Si está instalado, entonces:
cd sobjectizer/doxygen
doxygenLos archivos HTML generados se ubicarán en Sobjectizer/Dev/Doc/HTML.
NOTA. Si no especifica MXX_RU_CPP_TOOLSET de usted mismo, entonces MXX_RU intentará detectar su conjunto de herramientas C ++ automáticamente. Si desea usar el compilador C ++, que no es predeterminado en su sistema, defina MXX_RU_CPP_ToolSet Entorno Variable manualmente. Podría parecer:
export MXX_RU_CPP_TOOLSET= " clang_linux compiler_name=clang++-6 linker_name=clang++-6 "Más información sobre la sintonización MXX_RU para sus necesidades que puede encontrar en la documentación correspondiente.
Para construir Sobjectizer a través de CMake, es necesario tener CMake y algún conocimiento de cómo usarlo. La siguiente acción es solo una demostración. Para obtener información más detallada sobre el sistema de compilación Cmake para Sobjectizer, consulte Dev/Cmake/Cmakequickhowto.txt
Para obtener y construir Sobjectizer en Linux/FreeBSD en la línea de comando Ejecutar:
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 installEsos comandos crearán todo el archivo de making necesario, luego construirá Sobjectizer. Si es necesario crear ejemplos y pruebas también, use
cmake -DBUILD_ALL=ON -DCMAKE_INSTALL_PREFIX=target ../devCuando 'haga instalar' terminado './target' contendrá dos subcarpetas "./bin" con muestras y './lib' con Libso.5.xxso compartido
El sistema de compilación CMake actualmente admite estas opciones:
SOBJECTIZER_BUILD_STATIC . Habilitar el Sobjectizador de construcción como una biblioteca estática [predeterminado: ON]SOBJECTIZER_BUILD_SHARED . Habilitar el Sobjetador de construcción como una biblioteca compartida [predeterminado: ON]BUILD_ALL . Habilitar ejemplos y pruebas de construcción [predeterminado: apagado]BUILD_EXAMPLES . Habilitar ejemplos de construcción [predeterminado: apagado]BUILD_TESTS . Habilitar pruebas de construcción [predeterminado: apagado] Tenga en cuenta que si BUILD_ALL o BUILD_EXAMPLES o BUILD_TESTS se enciende, entonces se deben activar tanto SOBJECTIZER_BUILD_STATIC como SOBJECTIZER_BUILD_SHARED . Significa que si SOBJECTIZER_BUILD_STATIC o SOBJECTIZER_BUILD_SHARED se desactiva, entonces BUILD_ALL / BUILD_EXAMPLES / BUILD_TESTS todo debe desactivarse.
Para construir Sobjectizer en Windows por MS Visual Studio 2013 desde la línea de comandos:
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 Si es necesario crear ejemplos también, use BUILD_ALL en la invocación de cmake:
cmake -DCMAKE_INSTALL_PREFIX=target -DCMAKE_BUILD_TYPE=Release -DBUILD_ALL=ON -G " Visual Studio 15 2017 " ../dev Dado que V.5.5.24 Sobjectizer proporciona archivos Sobjectizer-Config.cmake. Estos archivos se instalan automáticamente en <target>/lib/cmake/sobjectizer . Permite usar Sobjectizer a través del comando Find_package de CMake.
La construcción para Android es posible a través de un NDK de Android bastante fresco o un NDK Crystax.
Necesita instalados Android SDK y Android NDK en su sistema. Así como una versión apropiada de Cmake. También ha necesitado configurar correctamente las variables de entorno ANDROID_HOME , ANDROID_NDK . Luego puede emitir los siguientes comandos:
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 installNecesita Crystax NDK V.10.4.0 o superior ya instalado en su sistema. CMake se usa para el sobrenegador de edificios:
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 installPara usar Sobjectizer a través de VCPKG, es necesario hacer los siguientes pasos.
Instalar el paquete sobjectizer :
vcpkg install sobjectizerAgregue las siguientes líneas a su archivo CMakelists.txt:
find_package (sobjectizer CONFIG REQUIRED)
target_link_libraries (your_target sobjectizer::SharedLib) # or sobjectizer::StaticLibNOTA. Desde febrero de 2021, nuevas versiones de Sobjectizer están disponibles solo con Conan-Center.
Para usar Sobjectizer a través de Conan, es necesario agregar Sobjectizer a conanfile.txt de su proyecto:
[requires]
sobjectizer/5.8.0
También puede ser necesario especificar la opción shared para Sobjectizer. Por ejemplo, para el Sobjectizador de compilación como una biblioteca estática:
[options]
sobjectizer:shared=False
Instalar dependencias para su proyecto:
conan install SOME_PATH --build=missing
...
include ( ${CMAKE_BINARY_DIR} /conanbuildinfo.cmake)
conan_basic_setup()
...
target_link_libraries (your_target ${CONAN_LIBS} )Sobjectizer se distribuye bajo la licencia BSD de 3 cláusulas. Para obtener información sobre la licencia, consulte el archivo de licencia.