MacroSIP
EnglishРусский中文

Сборка

MacroSIP собирается одним SwiftPM и Xcode Command Line Tools. Проекта Xcode нет, Homebrew не участвует: OpenSSL и Opus компилируются из зафиксированных исходных архивов вместе с PJSIP. Подробности — в scripts/README-build.md, scripts/build-pjsip.sh, scripts/make-app.sh и ADR 0012.

Требования

Шаг 1: scripts/build-pjsip.sh

scripts/build-pjsip.sh            # first run about 5 minutes on an 8-core M-series Mac, then seconds
scripts/build-pjsip.sh --clean    # remove every output except the downloads and rebuild
JOBS=4 scripts/build-pjsip.sh     # limit parallelism
KEEP_BUILD=1 scripts/build-pjsip.sh   # keep the source trees under third_party/build

Скрипт собирает для arm64 (нативно) и x86_64 (--host=x86_64-apple-darwin) с -mmacosx-version-min=14.0:

Компонент Версия Параметры
OpenSSL 3.5.9 (LTS) no-shared no-module no-tests, только build_libs и install_dev; darwin64-arm64-cc / darwin64-x86_64-cc
Opus 1.6.1 --disable-shared --enable-static --disable-doc --disable-extra-programs
pjproject 2.17 third_party/pjsip/config_site.h устанавливается до configure; --disable-shared --disable-pjsua2 --disable-video --disable-darwin-ssl --disable-speex-aec, без L16, AMR, SILK, bcg729 (G.729) и Lyra; --with-ssl и --with-opus указывают на third_party/deps/<arch>

Каждый архив сверяется с SHA-256, зафиксированным в начале скрипта. --disable-darwin-ssl важен: иначе configure предпочёл бы устаревший SecureTransport вместо OpenSSL. Скрипт проверяет журнал configure (OpenSSL и Opus найдены, кодеки G.722.1, GSM, iLBC и Speex не отключены), проверяет архитектуру и minos каждого архива и pjsua и завершается с ошибкой, если pjsua линкует что-либо из /opt/homebrew.

config_site.h включает IPv6, SRTP (SDES, без DTLS), эхоподавитель WebRTC, TLS, кэширование заголовка авторизации, PJSUA_MAX_CALLS 8 и кодеки Opus, G.711, G.722, G.722.1, GSM, iLBC и Speex (G.722.1, GSM, iLBC и Speex остаются выключенными в движке, пока пользователь их не включит; как добавить кодек, см. Участие). Видео выключено.

Результаты по архитектурам объединяются через lipo. Заголовки, различающиеся между архитектурами (pj/compat/m_auto.h, os_auto.h, куда configure записывает имя машины), становятся одним файлом с ветками #if defined(__aarch64__) / #elif defined(__x86_64__). Имена библиотек теряют суффикс host-triple (libpj-aarch64-apple-darwin27.2.0.a становится libpj.a), так что оба среза называются одинаково и флаги линковки переживают обновления macOS.

Структура вывода в third_party/ (всё игнорируется git, кроме pjsip/config_site.h):

Путь Содержимое
downloads/ проверенные архивы, сохраняются при --clean
deps/<arch>/{include,lib} OpenSSL и Opus для одной архитектуры
deps/universal/lib libssl.a, libcrypto.a, libopus.a, линкуются из Package.swift
pjsip/arch/<arch>/ заголовки, библиотеки PJSIP и pjsua для одной архитектуры
pjsip/include/, pjsip/lib/ объединённые заголовки и универсальные архивы
pjsip/bin/pjsua универсальный CLI pjsua, второй телефон в самопроверке
pjsip/LINKFLAGS, pjsip/CFLAGS флаги, нужные потребителю; pjsipLibraries в Package.swift повторяет LINKFLAGS
build/, build-logs/<arch>/ деревья исходников (удаляются, если не задан KEEP_BUILD=1) и полные журналы configure/make

Кэширование. Каждый компонент записывает штамп со своим рецептом (версии, контрольные суммы, флаги, SHA-256 файла config_site.h, штампы, с которыми он собирался). Запуск пропускает каждый компонент с совпадающим штампом и пересобирает остальные из свежераспакованного дерева. После правки config_site.h перезапустите скрипт: PJSIP пересобирается для обеих архитектур (2–5 минут), а OpenSSL и Opus остаются. CI кэширует third_party/pjsip и third_party/deps с ключом по скрипту и config_site.h, так что при попадании в кэш шаг ничего не делает. Чтобы обновить компонент, измените его версию и контрольную сумму в скрипте и перезапустите.

Шаг 2: swift build

swift build                         # debug, native architecture
swift build -c release              # release, native architecture
swift build --arch arm64 --arch x86_64 -c release   # universal (what make-app.sh release runs)
.build/release/pjsip-smoke          # prints PJSIP version, codecs and audio devices; exits 0

Package.swift линкует архивы абсолютными флагами -L/-l (Context.packageDirectory), добавляет -lc++, потому что libwebrtc содержит C++, и даёт каждому Swift-таргету, импортирующему CPJSUA, путь к заголовкам через swiftSettings: pjsipSwiftSettings (-Xcc -I). Таргет приложения получает rpath @executable_path/../Frameworks для Sparkle. Универсальные сборки кладут продукты в .build/out/Products/<Config>, а не в .build/<config>; путь можно узнать через swift build ... --show-bin-path. SwiftPM не отслеживает предсобранные архивы, поэтому после пересборки PJSIP выполните rm -rf .build, если изменение как будто не применяется.

Шаг 3: scripts/make-app.sh

scripts/make-app.sh                 # release: universal dist/MacroSIP.app (default)
scripts/make-app.sh debug           # debug: native only, faster; the only build that accepts demo options
ARCHS=arm64 scripts/make-app.sh     # single-architecture release

Скрипт выполняет swift build --product MacroSIPApp (универсально для release, нативно для debug), проверяет срезы через lipo и собирает dist/MacroSIP.app: бинарник, Sparkle.framework в Contents/Frameworks, строки en.lproj и ru.lproj и InfoPlist.strings в Contents/Resources, packaging/AppIcon.icns и сгенерированный Info.plist с bundle id com.hsmm.macrosip, URL-схемами sip/sips/tel, ключами Sparkle (SUFeedURL, SUPublicEDKey, ежедневная проверка) и версией. CFBundleShortVersionString — ближайший тег git (git describe --tags --abbrev=0; до первого тега — Product.version), CFBundleVersion — число коммитов. Скрипт убирает все rpath, кроме /usr/lib/swift и @executable_path/../Frameworks, и завершается с ошибкой, если бинарнику нужна другая библиотека через @rpath.

Подпись ad hoc (-) с hardened runtime, изнутри наружу, как описано в документации Sparkle: службы XPC, Autoupdate, Updater.app, фреймворк, затем приложение с packaging/Entitlements.plist; codesign --verify --deep --strict должен проходить. Entitlements дают доступ к микрофону и Контактам и отключают проверку библиотек, без чего подпись ad hoc не может загрузить встроенный фреймворк (ADR 0013).

Debug-приложение принимает --mock-engine, --demo-state, --data-dir, --snapshot и --appearance (см. Тесты); release-приложение их игнорирует и запускает настоящее приложение на настоящих данных, включая запрос к связке ключей. Все сборки принимают --log-level 0-6 (или MACROSIP_LOG_LEVEL) для подробности PJSIP.

Другие скрипты

Скрипт Что делает
scripts/make-dmg.sh [debug|release] запускает make-app.sh, кладёт приложение рядом с символической ссылкой на Applications и пишет dist/MacroSIP-<version>.dmg (HFS+, UDZO, том «MacroSIP»), печатает его SHA-256
swift scripts/make-icon.swift рисует иконку (первоисточник packaging/AppIcon.svg: клавиатура набора, нажатые клавиши которой образуют букву M на зелёном градиенте) средствами CoreGraphics в iconset и запускает iconutil, чтобы получить packaging/AppIcon.icns; перезапускайте после изменения рисунка
scripts/make-appcast.sh, scripts/publish-appcast.sh, scripts/update-cask.sh инструменты выпуска, см. Релизы
scripts/test.sh, scripts/selftest-call.sh, scripts/check-strings.sh см. Тесты

Универсальная сборка (ADR 0012)

Одно приложение и один DMG обслуживают Apple Silicon и Intel. Release-сборки приложения универсальные, debug-сборки нативные. Opus и OpenSSL линкуются как статические архивы из third_party/deps/universal/lib, никогда через .linkedLibrary или из Homebrew, так что у приложения нет зависимостей от dylib вне системы (архивы Homebrew были бы только arm64 и собраны под macOS хоста). Срез Intel проверяется на Apple Silicon командой SELFTEST_ARCH=x86_64 scripts/selftest-call.sh под Rosetta 2. Поддержка Intel закончится, когда её прекратят инструменты Apple или Intel-раннеры GitHub.

Типичные проблемы

Симптом Причина и решение
Apple Silicon (arm64) host required build-pjsip.sh кросс-компилирует x86_64 и работает только на arm64. На Mac с Intel возьмите универсальные библиотеки из артефакта CI (задание Intel в CI делает именно это).
SHA-256 mismatch for ... повреждённая или переопубликованная загрузка; удалите файл в third_party/downloads/, чтобы скачать его снова, и проверьте зафиксированную контрольную сумму, если upstream изменил архив
configure did not enable OpenSSL / Opus configure не увидел third_party/deps/<arch>; смотрите third_party/build-logs/<arch>/pjsip-configure.log
plugin for module SwiftUIMacros not found @State нужен плагин макросов Xcode; используйте обёртку @Local из Views/Components/Local.swift
swift test не находит макрос Testing запускайте scripts/test.sh, который передаёт путь к плагину
после пересборки приложение всё ещё выполняет старый код PJSIP SwiftPM не видит, что архивы изменились: rm -rf .build
Sparkle.framework not found в make-app.sh сначала выполните swift package resolve или swift build
бинарнику нужны библиотеки @rpath, кроме Sparkle новая зависимость подключена динамически; ADR 0012 требует статических архивов
PJSUA_INVALID_ID не компилируется в Swift это константа C-перечисления: используйте PJSUA_INVALID_ID.rawValue
pjsua x86_64 под Rosetta не отвечает сразу запуск Rosetta занимает несколько секунд; selftest-call.sh опрашивает до ~15 с

См. также Устройство, Установка об установке собранного DMG и Решение-проблем о проблемах во время работы.

Другие страницы: Главная · Home (English)