Criado por gh-md-toc
O Sobjectizer é uma das poucas plataformas cruzadas e OpenSource "estruturas de ator" para C ++. Mas o Sobjectizer suporta não apenas o modelo de ator, mas também o modelo de inscrição de publicação e canais do tipo CSP. O objetivo do Sobjectizer é uma simplificação significativa do desenvolvimento de aplicações simultâneas e multithreads em C ++.
O Sobjectizer permite a criação de um aplicativo simultâneo como um conjunto de objetos de agente que interagem entre si por meio de mensagens assíncronas. Ele lida com a despacho de mensagens e fornece um contexto de trabalho para processamento de mensagens. E permite ajustar essas coisas fornecendo vários despachantes prontos para uso.
Maturidade . O Sobjectizer é baseado em idéias que foram apresentadas em 1995-2000. E o próprio Sobjectizer está sendo desenvolvido desde 2002. O Sobjectizer-5 é evoluído continuamente desde 2010.
Estabilidade . Desde o início, o Sobjectizer foi usado para aplicativos críticos de negócios, e alguns deles ainda estão sendo usados na produção. As mudanças de quebra no Sobjectizer são raras e nos aproximamos com muito cuidado.
Plataforma cruzada . O Sobjectizer é executado no Windows, Linux, FreeBSD, MacOS e Android.
Fácil de usar . O Sobjetize fornece API fácil de entender e fácil de usar, com muitos exemplos no distributivo do Sobjectizer e muitas informações no wiki do projeto.
Livre . O Sobjectizer é distribuído pela licença de cláusula BSD-3, para que possa ser usado no desenvolvimento de software comercial proprietário gratuitamente.
O Sobjectizer é frequentemente comparado com ferramentas como blocos de construção de encadeamento Intel, fluxo de tarefas, hpx e semelhantes a eles. Essa comparação é apenas inútil.
Todas essas ferramentas devem ser usadas para resolver tarefas da área de computação paralela: elas permitem reduzir o tempo computacional, utilizando vários núcleos da CPU. Por exemplo, você pode reencodificar seu arquivo de vídeo de um formato para outro dentro de uma hora em um núcleo da CPU, leva apenas 15 minutos em quatro núcleos. Esse é o principal objetivo da computação paralela.
O Sobjectizer destina -se a uma área ligeiramente diferente: computação simultânea. O principal objetivo do Sobjectizer é a simplificação de realizar muitas tarefas diferentes de uma só vez. Às vezes, não há necessidade de usar mais do que apenas um núcleo da CPU para isso. Mas se houver vários núcleos de CPU, o Sobjectizer facilita muito o manuseio dessas tarefas e a interação entre elas.
A parte complicada é o fato de que a computação paralela e simultânea usa os mesmos mecanismos de simultaneidade e primitivos (como threads, mutexes, atômicos e assim por diante) sob o capô. Mas, do ponto de vista de alto nível, a computação paralela e simultânea é usada para tarefas muito diferentes.
Como exemplos de aplicativos que foram ou poderiam ser implementados no topo do Sobjectizer, podemos listar o servidor proxy multithread, sistema de controle automático, corretor MQ, servidor de banco de dados e assim por diante.
Este é um exemplo clássico "Hello, World" expresso usando os agentes do Sobjetizer:
# 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 ;
}Vejamos o exemplo mais interessante com dois agentes e a troca de mensagens entre eles. É outro exemplo famoso para estruturas de atores, "pingue-pongue":
# 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 os agentes do código acima estão trabalhando no mesmo tópico de trabalho. Como ligá -los a diferentes tópicos de trabalho?
É muito simples. Basta usar um despachante apropriado:
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 ;
}O SoBjectizer suporta pub/sub-modelo via caixas de mensagens multiprodutor/multi-consumidor. Uma mensagem enviada para essa caixa de mensagem será recebida por todos os assinantes desse tipo de mensagem:
# 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 os agentes do Sobjectizer são máquinas de estado finito. Quase todas as funcionalidades das máquinas hierárquicas de estados finitos (HSM) são suportados: Estados Infantis e Manipuladores de Herança, On_Enter/On_exit Manipuladores, Tempo limite do Estado, História do Estado profunda e rasa, exceto estados ortogonais.
Vamos ver como um agente que implementa o seguinte Statechart pode parecer:

Este é um exemplo muito simples que demonstra um agente para o StatChart mostrado acima:
# 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 ;
}O Sobjectizer permite escrever aplicativos simultâneos, mesmo sem agentes internos. Somente threads simples e canais semelhantes a CSP podem ser usados.
Esta é a implementação de thread simples do exemplo de pingue-pongue (observe que Main () não é seguro de exceção):
# 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 ;
}O Sobjectizer fornece uma função select () semelhante à instrução SELECT de Golang. Esta função permite aguardar mensagens recebidas de várias cadeias de mensagens. Ele também permite aguardar a prontidão das cadeias de mensagens para aceitar uma nova mensagem de saída. Portanto, selecione () permite fazer chamadas de send () não bloqueando () com o manuseio de mensagens recebidas enquanto a cadeia de mensagens de destino está cheia.
Há um exemplo de cálculo de Fibonacci que usa o Select () como o mecanismo de pressão de back-pressão (o thread do produtor numérico aguardará se o thread do leitor de número ainda não ler o número anterior). Observe também que a função main () neste exemplo é segura por exceção.
# 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 );
}Mais informações sobre o Sobjectizer podem ser encontradas na seção correspondente do wiki do projeto.
Existe um projeto complementar separado SO5EXTRA que contém muitas coisas úteis, como os despachantes baseados na ASIO, tipos adicionais de MBOXES, timer revogável, solicitações síncronas e muito mais.
Por exemplo, há como a interação síncrona se parece (usando 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 );
} );
} );
}O próprio Sobjectizer pretende ser um projeto relativamente pequeno, sem dependências externas. SO5EXTRA não tem essa restrição. É por isso que os despachantes e infraestruturas ambientais baseados na ASIO são implementados no SO5EXTRA, não no Sobjectizer.
Outra propriedade significativa do Sobjectizer é a estabilidade. Estamos tentando manter o Sobjectizer o mais estável possível, mas é necessário experimentar alguns novos recursos, mesmo que ainda não saibamos o quão bem -sucedido e exigimos que eles serão. O SO5EXTRA é um bom lugar para experimentar novos recursos, alguns deles podem ser movidos para o Sobjectizer com o tempo.
Portanto, se você não encontrar um recurso útil no Sobjectizer, vamos tentar olhar para o So5Extra. Talvez já esteja lá.
O Sobjectizer é uma estrutura de envio de mensagens em processo. Ele não suporta aplicativos distribuídos apenas fora da caixa. Mas ferramentas e bibliotecas externas podem ser usadas nesse caso. Por favor, dê uma olhada em nosso experimento Mosquitto_transport: https://github.com/stiffstream/mosquitto_transport
O Sobjectizer pode ser verificado no Github. Os arquivos com o código -fonte do Sobjectizer podem ser baixados do GitHub ou do SourceForge.
Existem duas maneiras de construir o Sobjectizer. O primeiro usando a ferramenta MXX_RU. O segundo usando cmake.
OBSERVAÇÃO. Desde v.5.5.15.2 Há um suporte à plataforma Android. A construção do Android é possível apenas por cmake. Veja a seção correspondente abaixo.
O Sobjectizer também pode ser instalado e usado via gerentes de dependência VCPKG e Conan . Veja as seções apropriadas abaixo.
O 5.8 ramo do Sobjectizer requer C ++ 17.
Se você precisar de suporte para C ++ 14 ou C ++ 11, tente procurar versões mais antigas do Sobjectizer no SourceForge. Ou entre em contato com o StiffStream para discutir a porta do Sobjectizer-5.8 para os padrões C ++ mais antigos.
OBSERVAÇÃO. Esta é uma maneira padrão de criar o Sobjectizer. Dessa forma, é usado no processo de desenvolvimento do Sobjectizer.
Para construir o Sobjectizer, é necessário usar a linguagem Ruby e a ferramenta MXX_RU. Instale o ruby e depois instale o comando mxx_ru via rubygems:
gem install Mxx_ruSe você já possui mxx_ru instalado, atualize pelo menos a versão 1.6.14.6:
gem update Mxx_ruO Sobjectizer pode ser obtido do Repositório Git no GitHub:
git clone https://github.com/stiffstream/sobjectizerPara construir o Sobjectizer:
cd sobjectizer/dev
ruby build.rbBiblioteca estática e compartilhada para Sobjectizer será construída. As bibliotecas serão colocadas no subdiretório de destino/liberação.
Se você deseja construir apenas biblioteca compartilhada:
cd sobjectizer/dev
ruby so_5/prj.rbOu se você quiser construir apenas biblioteca estática:
cd sobjectizer/dev
ruby so_5/prj_s.rbPara construir o Sobjectizer com todos os testes e amostras:
cd sobjectizer/dev
ruby build_all.rbObserve que, em FreeBSD, pode ser necessário definir a variável de ambiente LD_LIBRARY_PATH. E a sequência de comando de construção real sob FreeBSD pode ser a seguinte:
cd sobjectizer/dev
export LD_LIBRARY_PATH=target/release
ruby build_all.rbPara criar documentação em formato HTML para o Sobjectizer, a ferramenta Doxygen é necessária. Se for instalado, então:
cd sobjectizer/doxygen
doxygenOs arquivos HTML gerados estarão localizados no Sobjectizer/dev/doc/html.
OBSERVAÇÃO. Se você não especificar MXX_RU_CPP_TOOLSET por si mesmo, o MXX_RU tentará detectar seu conjunto de ferramentas C ++ automaticamente. Se você deseja usar o compilador C ++, que não é padrão no seu sistema, defina MXX_RU_CPP_TOOLSET Ambiente variável manualmente. Pode parecer:
export MXX_RU_CPP_TOOLSET= " clang_linux compiler_name=clang++-6 linker_name=clang++-6 "Mais informações sobre o ajuste do MXX_RU para suas necessidades que você pode encontrar na documentação correspondente.
Para construir o Sobjectizer via cmake, é necessário ter cmake e algum conhecimento de como usá -lo. A ação a seguir é apenas uma demonstração. Para informações mais detalhadas sobre o sistema de construção cmake para Sobjectizer, consulte Dev/cmake/cmakequickhowto.txt
Para obter e construir o Sobjectizer em Linux/FreeBSD na linha de comando Run:
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 installEsses comandos criarão todo o makefile necessário e, em seguida, criarão o Sobjectizer. Se necessário criar exemplos e testes também, use
cmake -DBUILD_ALL=ON -DCMAKE_INSTALL_PREFIX=target ../devQuando 'Faça a instalação' terminada './target' conterá duas subpastas './bin' com amostras e './lib' com libso.5.xxso compartilhado
Atualmente, o Sistema de compilação do CMAKE suporta essas opções:
SOBJECTIZER_BUILD_STATIC . Habilite o edifício Sobjectizer como uma biblioteca estática [Padrão: ON]SOBJECTIZER_BUILD_SHARED . Habilitar o Building Sobjetizer como uma biblioteca compartilhada [padrão: ON]BUILD_ALL . Ativar exemplos e testes de construção [Padrão: Off]BUILD_EXAMPLES . Ativar exemplos de construção [Padrão: Off]BUILD_TESTS . Ativar testes de construção [Padrão: Off] Observe que, se BUILD_ALL ou BUILD_EXAMPLES ou BUILD_TESTS estiver ligado, então SOBJECTIZER_BUILD_STATIC e SOBJECTIZER_BUILD_SHARED devem ser ativados. Isso significa que se SOBJECTIZER_BUILD_STATIC ou SOBJECTIZER_BUILD_SHARED estiver desligado, BUILD_ALL / BUILD_EXAMPLES / BUILD_TESTS deve ser desligado.
Para construir o Sobjectizer no Windows pelo MS Visual Studio 2013 na linha de comando:
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 Se necessário para criar exemplos também, use BUILD_ALL na Invocação CMake:
cmake -DCMAKE_INSTALL_PREFIX=target -DCMAKE_BUILD_TYPE=Release -DBUILD_ALL=ON -G " Visual Studio 15 2017 " ../dev Desde V.5.5.24 O Sobjectizer fornece arquivos SoBjectizer--Fig.cmake. Esses arquivos são instalados automaticamente na subpasta <target>/lib/cmake/sobjectizer . Ele permite usar o Sobjectizer através do comando find_package do cmake.
A construção do Android é possível por meio de um NDK Android ou NDK bastante fresco.
Você precisa do Android SDK e do Android NDK instalados em seu sistema. Bem como uma versão apropriada do cmake. Você também precisa definir adequadamente as variáveis de ambiente ANDROID_HOME , ANDROID_NDK . Então você pode emitir os seguintes 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 installVocê precisa do Crystax NDK v.10.4.0 ou superior já instalado em seu sistema. Cmake é usado para construir 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 installPara usar o Sobjectizer via vcpkg, é necessário fazer as seguintes etapas.
Instale o pacote sobjectizer :
vcpkg install sobjectizerAdicione as seguintes linhas ao seu arquivo cmakelists.txt:
find_package (sobjectizer CONFIG REQUIRED)
target_link_libraries (your_target sobjectizer::SharedLib) # or sobjectizer::StaticLibOBSERVAÇÃO. Desde fevereiro de 2021, novas versões do Sobjectizer estão disponíveis apenas por Conan-Center.
Para usar o Sobjectizer via Conan, é necessário adicionar Sobjectizer ao conanfile.txt do seu projeto:
[requires]
sobjectizer/5.8.0
Também pode ser necessário especificar a opção shared para o Sobjectizer. Por exemplo, para Build Sobjetize como uma biblioteca estática:
[options]
sobjectizer:shared=False
Instale dependências para o seu projeto:
conan install SOME_PATH --build=missing
...
include ( ${CMAKE_BINARY_DIR} /conanbuildinfo.cmake)
conan_basic_setup()
...
target_link_libraries (your_target ${CONAN_LIBS} )O Sobjectizer é distribuído sob a licença BSD de 3 cláusulas. Para informações de licença, consulte o arquivo de licença.