Для разработки и компиляции MEGAchat мы в основном используем CMake как инструмент кроссплатформенной настройки проекта. Мы также используем VCPKG для управления необходимыми зависимостями для сборки MEGAchat на большинстве платформ: Windows, MacOS и Linux.
Подробную информацию о необходимых инструментах сборки для каждой операционной системы см. в главе «Инструменты сборки» в репозитории MEGA SDK.
Дополнительная информация о компиляции WebRTC для Android в WebRTC для Android.
Для работы MEGAchat требуются некоторые зависимости. Большинство из них автоматически загружаются и собираются с помощью VCPKG на этапе настройки.
Для Linux в системе необходимы некоторые дополнительные библиотеки, чтобы VCPKG мог создавать зависимости. Для дистрибутивов на основе Debian вы можете установить необходимые библиотеки с помощью следующей команды:
sudo apt install python3-pkg-resources libglib2.0-dev libgtk-3-dev libasound2-dev libpulse-dev
Имена пакетов могут различаться в разных дистрибутивах Linux, но сборка должна осуществляться успешно с пакетами, предоставляющими одни и те же библиотеки.
Полный набор зависимостей можно просмотреть в файле vcpkg.json в корне репозитория.
MEGAchat также необходима библиотека MEGA SDK. Далее в этом документе приведены инструкции о том, как использовать его с MEGAchat . Проект MEGA SDK автоматически загружается MEGAchat CMake, поэтому вам нужно просто клонировать его по ожидаемому пути.
В системе следует установить только одну дополнительную необязательную зависимость: Qt Framework. Необходимо только собрать пример приложения Qt, но это не требуется для тестов, примера CLI или самой библиотеки.
Прежде всего подготовьте выбранный вами каталог для работы с MEGAchat . В примерах этого документа mega
будет использоваться в качестве каталога рабочей области.
mkdir mega
cd mega
После подготовки каталога клонируйте репозиторий MEGAchat , чтобы получить исходный код MEGAchat .
git clone https://github.com/meganz/MEGAchat
Поскольку для работы MEGAchat требуется MEGA SDK, клонируйте MEGA SDK по ожидаемому пути.
git clone https://github.com/meganz/sdk MEGAchat/third-party/mega
Наконец, клонируйте репозиторий VCPKG рядом с папкой MEGAchat . Если вы уже используете VCPKG и у вас есть локальный клон репозитория, вы можете пропустить этот шаг и использовать существующий VCPKG в своей системе.
git clone https://github.com/microsoft/vcpkg
Следующие инструкции предназначены для настройки проекта из интерфейса командной строки (CLI), но cmake-gui или любой редактор или IDE, совместимый с CMake, должны подойти, если настроены те же параметры CMake.
MEGAchat настраивается как любой другой обычный проект CMake. Единственный параметр, который всегда необходим, — это каталог VCPKG для управления сторонними зависимостями. Зависимость MEGA SDK создается как часть сборки MEGAchat .
Чтобы настроить MEGAchat , из рабочей области ( mega
) запустите CMake:
cmake -DVCPKG_ROOT=vcpkg -DCMAKE_BUILD_TYPE=Debug -S MEGAchat -B build_dir
Примечание 1. Параметр -DCMAKE_BUILD_TYPE=<Debug|Release>
может не потребоваться для генераторов мультиконфигурации, таких как Visual Studio.
Примечание 2. Если в вашей системе установлен Qt Framework, но CMake не может его обнаружить, вы можете добавить -DCMAKE_PREFIX_PATH=</path/to/qt/install/dir>
чтобы CMake мог его найти. Если Qt не установлен и вы предпочитаете не устанавливать его, вы можете отключить пример приложения Qt, установив -DENABLE_CHATLIB_QTAPP=OFF
. Библиотека, пример CLI и тесты все равно будут собраны.
В приведенной выше команде cmake для простоты использовались относительные пути. Если вы хотите изменить местоположение VCPKG, MEGAchat или каталога сборки, просто укажите действительный относительный или абсолютный путь для любого из них.
В ходе настройки проекта VCPKG соберет и настроит необходимые библиотеки для платформы. При первом запуске это может занять некоторое время, но как только библиотеки будут построены, VCPKG извлечет их из двоичного кэша.
MEGAchat можно настроить с помощью различных параметров, некоторые из которых можно найти в файлеchatlib_options.cmake. Параметры управления примерами и тестами находятся в файле CMakeLists.txt.
После настройки MEGAchat просто создайте полный проект:
cmake --build build_dir
Вы можете указать --target=<target>
например CHATlib
или megaclc
, или просто оставить команду как есть, чтобы построить все теги. Кроме того, можно добавить -j <N>
или --parallel <N>
для управления параллелизмом и ускорения сборки.
После завершения сборки двоичные файлы будут доступны в build_dir
, который был указан в команде конфигурации CMake.
Чтобы абстрагироваться от сложности кода, MEGAchat предоставляет промежуточный уровень, позволяющий быстро создавать новые приложения.
Документация доступна по адресу src/ MEGAchat api.h
Модель потоков MEGAchat аналогична модели потоков javascript — все выполняется в основном потоке (GUI), блокировка никогда не допускается, а внешние события (сеть, таймеры и т. д., события webrtc и т. д.) запускают обратные вызовы в основном потоке. Чтобы это работало, MEGAchat должен иметь возможность взаимодействовать с циклом событий приложения — обычно это цикл событий/сообщений инфраструктуры графического пользовательского интерфейса в случае приложения с графическим интерфейсом или собственный цикл сообщений в случае консольного приложения. Поскольку этот цикл сообщений очень зависит от платформы, разработчик приложения несет ответственность за реализацию интерфейса между ним и MEGAchat . Это может показаться сложнее, чем есть на самом деле — интерфейс состоит из двух частей. Одна часть — это реализация функции megaPostMessageToGui(void*)
, которая отправляет непрозрачный указатель void*
в цикл сообщений приложения. Эта функция обычно вызывается потоками, отличными от основного потока, но также может быть вызвана самим потоком графического интерфейса. Другая часть — это код в цикле сообщений приложения, который распознает этот тип сообщений и передает их обратно в MEGAchat , вызывая megaProcessMessage(void*)
с тем же указателем — на этот раз в контексте основного (GUI) потока. Все это реализовано в /src/base/gcm.h
и /src/base/gcm.hpp
. Эти файлы содержат подробную документацию. Пример реализации этого в Windows: megaPostMessageToGui(void*)
выполнит PostMessage()
с типом пользовательского сообщения, а void*
— в качестве lParam или wParam сообщения, а в операторе switch
обработки событий будет запись для этого типа сообщения, получение указателя void*
путем приведения lParam или wParam сообщения и передачи его в megaProcessMessage(void*)
.
MEGAchat использует libuv, работающую в собственном выделенном потоке, для мониторинга нескольких сокетов на предмет необработанных событий ввода-вывода и реализации таймеров. Он также опирается на функциональные возможности ввода-вывода более высокого уровня libuv, такие как разрешение DNS и сокеты SSL. Тонкий слой поверх libuv, называемый 'services' ( /src/base/?services*.*
), реализован поверх libuv и GCM, чтобы иметь простые, подобные javascript асинхронные API-интерфейсы C++11 для таймеров. ( src/base/timer.h
), разрешение DNS ( /src/base/services-dns.hpp
), http-клиент ( /src/base/services-http.hpp
). Первоначально этот уровень был разработан для того, чтобы иметь компонент нижнего уровня с простым интерфейсом C (файлы cservices*.cpp/h
), чтобы службы могли использоваться несколькими DLL, созданными с помощью разных компиляторов, и высокоуровневый C, содержащий только заголовок. Уровень ++11, который является внешним интерфейсом и содержит общедоступный API — это файлы .hpp.
Все сетевые библиотеки в MEGAchat (libcurl) используют libuv для сетевых операций и таймеров (библиотеки C напрямую используют libuv, код C++ использует уровень C++11, т.е. timers.hpp
). Настоятельно рекомендуется, чтобы пользователь SDK также делал то же самое, хотя можно, например, заблокировать выделенный рабочий поток в сокете и отправлять события в поток графического интерфейса через GCM.
Схема использования следующая: обратный вызов регистрируется для определенного события (событие ввода-вывода сокета, таймер и т. д.), и этот обратный вызов вызывается потоком libuv при возникновении события. Если событие может распространиться за пределы библиотеки, обратный вызов которой вызывается, и особенно в графический интерфейс, то в какой-то момент обработка событий должна быть передана в поток графического интерфейса с использованием механизма GCM. Однако если событие является внутренним и никогда не распространяется за пределы библиотеки, то его можно обработать непосредственно в контексте потока libuv (при условии, что он никогда его не блокирует). Это экономит затраты на производительность, связанные с маршалингом его в поток графического пользовательского интерфейса, и рекомендуется, если событие происходит с высокой частотой, например, событие входящего фрагмента данных, для которого требуется только добавление данных в буфер. Когда передача завершена, событие завершения может быть маршалировано в потоке графического интерфейса один раз за передачу, что сочетает в себе преимущества обоих подходов.
MEGAchat имеет расширенную функцию ведения журналов, которая поддерживает ведение файловых и консольных журналов с цветом, ротацией файлов журналов, несколькими каналами журналов, каждый из которых имеет индивидуальный уровень журнала. Уровни журнала настраиваются во время выполнения (при запуске), а не во время компиляции (т. е. без отключения макросов журнала). Это позволяет приложению, созданному в рамках выпуска, включать полное ведение журнала отладки для любых каналов. Каналы журналов определяются и настраиваются по умолчанию в src/base/loggerChannelConfig.h. В файле содержится подробная документация. Для удобства специальные макросы журналирования для каждого канала обычно определяются в коде, который его использует — примеры см. в макросах XXX_LOG_DEBUG/WARN/ERROR в karereCommon.h. Пользователь SDK может при необходимости создавать дополнительные каналы журналов. Канал журнала графического интерфейса уже определен. Конфигурацию канала журнала можно переопределить во время выполнения с помощью переменной среды KRLOG. Его формат следующий:
KRLOG=<chan name>=<log level>,<chan name2>=<log level2>...
Уровни журнала: «выключено», «ошибка», «предупреждение», «информация», «подробный», «отладка», «отладка».
Есть одно специальное название канала – «все». Установка уровня журнала этого канала устанавливает уровни журнала всех каналов. Это позволяет, например, легко отключить все каналы, кроме одного (или нескольких), следующим образом:
KRLOG=all=warn,mychannel=debug,myotherchannel=info
Один и тот же канал можно настроить несколько раз, и только последняя настройка будет эффективна, что делает возможным описанный выше трюк.
MEGAchat требует, чтобы функция karere::getAppDir()
была определена приложением во время компиляции, чтобы знать, где создавать файл журнала, и начинать регистрацию как можно раньше, до того, как будет введена main()
. Если MEGAchat собран как статическая библиотека, это не проблема. В случае динамической библиотеки эта функция должна быть слабым символом, чтобы сам MEGAchat мог скомпилироваться без реализации функции, а реализация должна быть связана при загрузке общей библиотеки MEGAchat при запуске приложения. Слабые символы на самом деле не переносятся между компиляторами, и это может быть проблемой. Однако они поддерживаются как gcc, так и clang. Если слабые символы не поддерживаются, karer необходимо собрать как статическую библиотеку.
base/promise.h
и пример использования, например, в /src/test-promise.cpp
setTimeout()
и setInterval()
в /src/base/timers.hpp
marshallCall()
сортирует лямбда-вызовы из рабочего потока в поток графического интерфейса. Примеры использования можно увидеть, например, в /src/webrtcAdapter.h
и во многих других местах. Этот механизм не должен быть непосредственно необходим в высокоуровневом коде, который выполняется в потоке графического интерфейса./src/chatClient.h;.cpp
megaPostMessageToGui()
, как запустить «службы» и как создать экземпляр клиента MEGAchat . Также показано, как реализовать метод getAppDir()
, который является слабым символом, необходимым библиотеке MEGAchat для создания файла журнала и начала регистрации как можно раньше, до того, как будет введена main()
.src/rtcModile/IRtcModule.h
и связанных заголовках.megaPostMessageToGui()
, но она может иметь любое имя при условии, что подпись — extern "C" void(void*)
. Эта функция является основой механизма передачи сообщений (называемого Gui Call Marshaller или GCM), на который опирается MEGAchat . Вы должны передать указатель на эту функцию в services_init()
.