Para o desenvolvimento e compilação do MEGAchat , usamos principalmente o CMake como ferramenta de configuração de projeto multiplataforma. Também usamos VCPKG para gerenciar as dependências necessárias para construir MEGAchat na maioria das plataformas: Windows, MacOS e Linux.
Para obter detalhes sobre as ferramentas de construção necessárias para cada sistema operacional, revise o capítulo Ferramentas de construção no repositório MEGA SDK.
Mais informações para a compilação WebRTC Android em WebRTC para Android
MEGAchat requer algumas dependências para funcionar. A maioria deles é baixada e construída automaticamente usando VCPKG durante a fase de configuração.
Para Linux, algumas bibliotecas extras são necessárias no sistema para que o VCPKG possa construir as dependências. Para distribuições baseadas em Debian, você pode instalar as bibliotecas necessárias usando o seguinte comando:
sudo apt install python3-pkg-resources libglib2.0-dev libgtk-3-dev libasound2-dev libpulse-dev
Os nomes dos pacotes podem variar para diferentes distribuições Linux, mas devem ser compilados com sucesso com pacotes que fornecem as mesmas bibliotecas.
Você pode dar uma olhada no conjunto completo de dependências no arquivo vcpkg.json na raiz do repositório.
MEGAchat também precisa da biblioteca MEGA SDK. Há instruções posteriormente neste documento sobre como usá-lo com MEGAchat . O projeto MEGA SDK é carregado automaticamente pelo MEGAchat CMake, então você só precisa cloná-lo no caminho esperado.
Existe apenas uma dependência extra opcional que deve ser instalada no sistema: O Qt Framework. É necessário apenas construir o aplicativo de exemplo Qt, mas não é necessário para os testes, exemplo CLI ou a própria biblioteca.
Em primeiro lugar, prepare um diretório de sua preferência para trabalhar com MEGAchat . O mega
será usado como diretório do espaço de trabalho nos exemplos deste documento.
mkdir mega
cd mega
Após preparar o diretório, clone o repositório MEGAchat para obter o código-fonte MEGAchat .
git clone https://github.com/meganz/MEGAchat
Como MEGAchat requer o MEGA SDK para funcionar, clone o MEGA SDK no caminho esperado.
git clone https://github.com/meganz/sdk MEGAchat/third-party/mega
Por fim, clone o repositório VCPKG próximo à pasta MEGAchat . Se você já estiver usando o VCPKG e tiver um clone local do repositório, poderá pular esta etapa e usar o VCPKG existente em seu sistema.
git clone https://github.com/microsoft/vcpkg
As instruções a seguir são para configurar o projeto a partir da interface de linha de comando (CLI), mas cmake-gui ou qualquer editor ou IDE compatível com CMake deve ser adequado se os mesmos parâmetros do CMake estiverem configurados.
MEGAchat é configurado como qualquer outro projeto CMake normal. O único parâmetro sempre necessário é o diretório VCPKG para gerenciar as dependências de terceiros. A dependência do MEGA SDK é construída como parte da construção MEGAchat .
Para configurar MEGAchat , no espaço de trabalho (diretório mega
), execute o CMake:
cmake -DVCPKG_ROOT=vcpkg -DCMAKE_BUILD_TYPE=Debug -S MEGAchat -B build_dir
Nota 1 : O -DCMAKE_BUILD_TYPE=<Debug|Release>
pode não ser necessário para geradores multiconfig, como o Visual Studio.
Nota 2 Se o Qt Framework estiver instalado em seu sistema, mas o CMake não conseguir detectá-lo, você poderá adicionar -DCMAKE_PREFIX_PATH=</path/to/qt/install/dir>
para que o CMake possa localizá-lo. Se o Qt não estiver instalado e você preferir não instalá-lo, você pode desabilitar o aplicativo de exemplo Qt configurando -DENABLE_CHATLIB_QTAPP=OFF
. A biblioteca, o exemplo CLI e os testes ainda serão construídos.
No comando cmake acima, caminhos relativos foram usados para simplificar. Se você deseja alterar a localização do VCPKG, MEGAchat ou do diretório de construção, basta fornecer um caminho relativo ou absoluto válido para qualquer um deles.
Durante a configuração do projeto, o VCPKG construirá e configurará as bibliotecas necessárias para a plataforma. Pode demorar um pouco na primeira execução, mas assim que as bibliotecas forem construídas, o VCPKG irá recuperá-las do cache binário.
MEGAchat pode ser configurado com diferentes opções, algumas das quais podem ser encontradas no arquivo chatlib_options.cmake. As opções para gerenciar os exemplos e testes estão no CMakeLists.txt.
Depois que MEGAchat estiver configurado, basta construir o projeto completo:
cmake --build build_dir
Você pode especificar --target=<target>
como CHATlib
ou megaclc
, ou simplesmente deixar o comando como está para construir todos os tagets. Além disso, -j <N>
ou --parallel <N>
podem ser adicionados para gerenciar a simultaneidade e acelerar a construção.
Assim que a compilação for concluída, os binários estarão disponíveis no build_dir
, que foi especificado no comando de configuração do CMake.
Para abstrair a complexidade do código, MEGAchat fornece uma camada intermediária que permite criar rapidamente novos aplicativos.
A documentação está disponível em src/ MEGAchat api.h
O modelo de threading MEGAchat é semelhante ao modelo de threading javascript - tudo é executado no thread principal (GUI), o bloqueio nunca é permitido e eventos externos (rede, temporizadores, etc., eventos webrtc, etc.) acionam retornos de chamada no thread principal. Para que isso funcione, MEGAchat deve ser capaz de interagir com o loop de eventos do aplicativo - geralmente é o loop de eventos/mensagens da estrutura GUI no caso de um aplicativo GUI, ou um loop de mensagens personalizado no caso de um aplicativo de console. Como esse loop de mensagens é muito específico da plataforma, é responsabilidade do desenvolvedor do aplicativo implementar a interface entre ele e MEGAchat . Isto pode parecer mais complicado do que realmente é – a interface consiste em duas partes. Uma parte é a implementação da função megaPostMessageToGui(void*)
, que envia um ponteiro opaco void*
para o loop de mensagens do aplicativo. Esta função normalmente é chamada por threads diferentes do thread principal, mas também pode ser chamada pelo próprio thread da GUI. A outra parte é o código no loop de mensagens do aplicativo que reconhece esse tipo de mensagem e as repassa ao MEGAchat , chamando megaProcessMessage(void*)
com o mesmo ponteiro - desta vez no contexto do thread principal (GUI). Tudo isso é implementado em /src/base/gcm.h
e /src/base/gcm.hpp
. Esses arquivos contêm documentação detalhada. Um exemplo de implementação disso no Windows é: megaPostMessageToGui(void*)
faria um PostMessage()
com um tipo de mensagem do usuário, e o void*
como o lParam ou wParam da mensagem, e na instrução switch
de processamento de eventos, haverá uma entrada para esse tipo de mensagem, obtendo o ponteiro void*
convertendo o lParam ou wParam da mensagem e passando-o para megaProcessMessage(void*)
.
MEGAchat depende do libuv, rodando em seu próprio thread dedicado, para monitorar vários soquetes para eventos de E/S brutos e para implementar temporizadores. Ele também depende da funcionalidade de E/S de nível superior do libuv, como resolução DNS e soquetes SSL. Uma camada fina sobre o libuv, chamada 'services' ( /src/base/?services*.*
) é implementada sobre o libuv e o GCM para ter APIs C++ 11 assíncronas simples, semelhantes a javascript, para temporizadores ( src/base/timer.h
), resolução DNS ( /src/base/services-dns.hpp
), cliente http ( /src/base/services-http.hpp
). Esta camada foi originalmente projetada para ter um componente de nível inferior com interface C simples (arquivos cservices*.cpp/h
), para que os serviços possam ser usados por várias DLLs construídas com compiladores diferentes e um C somente de cabeçalho de alto nível. Camada ++11 que é o frontend e contém a API pública - esses são os arquivos .hpp.
Todas as bibliotecas de rede no MEGAchat (libcurl) usam libuv para operação de rede e temporizadores (as bibliotecas C usam libuv diretamente, o código C++ usa a camada C++ 11, ou seja, timers.hpp
). É altamente recomendável que o usuário do SDK também faça o mesmo, embora seja possível, por exemplo, ter um thread de trabalho dedicado bloqueando um soquete e postando eventos no thread da GUI por meio do GCM.
O padrão de uso é o seguinte: um retorno de chamada é registrado para um determinado evento (evento de E/S de soquete, temporizador, etc.), e esse retorno de chamada é chamado pelo thread libuv quando o evento ocorre. Se o evento puder se propagar fora da biblioteca cujo retorno de chamada é chamado, e especialmente para a GUI, então, em algum momento, o processamento do evento deverá ser empacotado para o thread da GUI, usando o mecanismo GCM. No entanto, se o evento for interno e nunca se propagar fora da biblioteca, ele poderá ser tratado diretamente no contexto do thread libuv (desde que nunca o bloqueie). Isso economiza o custo de desempenho de empacotamento para o thread da GUI e é recomendado se o evento ocorrer em alta frequência, por exemplo, um evento de bloco de dados de entrada que só precisa dos dados anexados a um buffer. Quando a transferência for concluída, um evento de conclusão poderá ser organizado no thread da GUI uma vez por transferência, combinando as vantagens de ambas as abordagens.
MEGAchat possui um recurso de registro avançado que suporta registro de arquivos e console com cores, rotação de arquivos de registro, vários canais de registro, cada um com nível de registro individual. Os níveis de log são configurados em tempo de execução (na inicialização) e não em tempo de compilação (ou seja, não desabilitando macros de log). Isso permite que um aplicativo criado para lançamento habilite o registro de depuração completo para qualquer canal. Os canais de log são definidos e configurados por padrão em src/base/loggerChannelConfig.h. O arquivo contém documentação detalhada. Por conveniência, macros de registro dedicadas para cada canal são geralmente definidas no código que o utiliza - consulte as macros XXX_LOG_DEBUG/WARN/ERROR em karereCommon.h para obter exemplos. O usuário do SDK pode criar canais de log adicionais, se necessário. Um canal de log da GUI já está definido. A configuração do canal de log pode ser substituída em tempo de execução pela variável de ambiente KRLOG. Seu formato é o seguinte:
KRLOG=<chan name>=<log level>,<chan name2>=<log level2>...
Os níveis de log são 'off', 'error', 'warn', 'info', 'verbose', 'debug', 'debugv'.
Existe um nome de canal especial - 'todos'. Definir o nível de log deste canal define os níveis de log de todos os canais. Isto permite, por exemplo, silenciar facilmente todos os canais, exceto um (ou alguns), ao:
KRLOG=all=warn,mychannel=debug,myotherchannel=info
O mesmo canal pode ser configurado várias vezes e apenas a última configuração terá efeito, o que torna possível o truque acima.
MEGAchat requer que a função karere::getAppDir()
seja definida pelo aplicativo em tempo de compilação, para saber onde criar o arquivo de log e iniciar o registro o mais cedo possível, antes que main()
seja inserido. Se MEGAchat for construído como uma biblioteca estática, isso não será um problema. No caso de biblioteca dinâmica, esta função deve ser um símbolo fraco, para que o próprio MEGAchat possa compilar sem a implementação da função, e a implementação seja vinculada quando a biblioteca compartilhada MEGAchat for carregada na inicialização do aplicativo. Símbolos fracos não são realmente portáveis entre compiladores e isso pode ser um problema. No entanto, eles são suportados pelo gcc e pelo clang. Se nenhum símbolo fraco for suportado, karer e deve ser construído como biblioteca estática.
base/promise.h
e exemplo de uso, por exemplo, em /src/test-promise.cpp
setTimeout()
e setInterval()
em /src/base/timers.hpp
marshallCall()
organiza chamadas lambda de um thread de trabalho para o thread da GUI. Exemplos de uso podem ser vistos, por exemplo, em /src/webrtcAdapter.h
e em muitos lugares diferentes. Esse mecanismo não deve ser necessário diretamente em código de alto nível executado no thread da GUI./src/chatClient.h;.cpp
megaPostMessageToGui()
, como iniciar os 'serviços' e como instanciar o cliente MEGAchat . Também mostra como implementar o método getAppDir()
, que é um símbolo fraco necessário à biblioteca MEGAchat para criar o arquivo de log e iniciar o registro o mais cedo possível, antes que main()
seja inserido.src/rtcModile/IRtcModule.h
e cabeçalhos relacionadosmegaPostMessageToGui()
, mas pode ter qualquer nome, desde que a assinatura seja extern "C" void(void*)
. Esta função é o coração do mecanismo de passagem de mensagens (chamado Gui Call Marshaller, ou GCM) do qual MEGAchat depende. Você deve passar um ponteiro para esta função para services_init()
.