mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-08 14:33:23 +00:00
build: make conan tvOS pipeline build
build: make tvOS awg prebuilt explicit docs: make Apple TV build manual portable
This commit is contained in:
340
apple-tv-build.md
Normal file
340
apple-tv-build.md
Normal file
@@ -0,0 +1,340 @@
|
||||
# AmneziaVPN Apple TV Build
|
||||
|
||||
This document describes how to build the current branch for Apple TV from the repository root.
|
||||
|
||||
The pipeline is:
|
||||
|
||||
1. Use a separately built static Qt 6.9.2 for `tvOS`.
|
||||
2. Let Conan build/provide C/C++ dependencies.
|
||||
3. Generate an Xcode project with `qt-cmake`.
|
||||
4. Build the `.app` and embedded Network Extension with `xcodebuild`.
|
||||
|
||||
Important:
|
||||
|
||||
- Run the project commands from the repository root.
|
||||
- This is a device build for `appletvos`, not a simulator build.
|
||||
- `xcodebuild build` produces `.app`.
|
||||
- `.ipa` is produced later via `archive` and `-exportArchive`.
|
||||
- The current tvOS Network Extension scope is WireGuard-only.
|
||||
- The temporary tvOS WireGuard bridge prebuilt is opt-in. The Conan recipe does not contain machine-specific fallback paths.
|
||||
- Do not initialize or update submodules just for this build. If a clean checkout has empty `client/3rd` folders, pass `AMNEZIA_THIRDPARTY_ROOT` to an already initialized read-only `client/3rd` tree.
|
||||
|
||||
## 1. Environment
|
||||
|
||||
Set these paths for your machine:
|
||||
|
||||
```bash
|
||||
export REPO_ROOT="$PWD"
|
||||
export QT_DESKTOP_PREFIX="$HOME/Qt/6.9.2/macos"
|
||||
export QT_TVOS_SRC="$HOME/Qt_tv/qt-6.9.2-tvos-src"
|
||||
export QT_TVOS_PREFIX="$HOME/Qt_tv/6.9.2/tvos-device"
|
||||
export BUILD_DIR="$REPO_ROOT/build-tvos-device-conan"
|
||||
```
|
||||
|
||||
If this checkout does not have initialized `client/3rd` sources, point CMake at an initialized tree:
|
||||
|
||||
```bash
|
||||
export AMNEZIA_THIRDPARTY_ROOT="/path/to/initialized/amnezia/client/3rd"
|
||||
```
|
||||
|
||||
If you are using a temporary prebuilt tvOS WireGuard bridge, point Conan at it explicitly:
|
||||
|
||||
```bash
|
||||
export AMNEZIA_TVOS_AWG_PREBUILT_DIR="/path/to/WireGuardKitGo-appletvos"
|
||||
export AMNEZIA_TVOS_AWG_VERSION_HEADER_DIR="/path/to/directory/with/wireguard-go-version.h"
|
||||
```
|
||||
|
||||
`AMNEZIA_TVOS_AWG_PREBUILT_DIR` must contain `libwg-go.a`.
|
||||
|
||||
`AMNEZIA_TVOS_AWG_VERSION_HEADER_DIR` is optional when `wireguard-go-version.h` lives in the same directory as `libwg-go.a`.
|
||||
|
||||
If the env vars are not set, the recipe uses the normal source build path. Rebuilding and publishing the tvOS WireGuard bridge through the registry is a separate task.
|
||||
|
||||
## 2. Required Local Tools
|
||||
|
||||
Conan must be available:
|
||||
|
||||
```bash
|
||||
uv tool install conan
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
conan --version
|
||||
```
|
||||
|
||||
Validated version:
|
||||
|
||||
```text
|
||||
Conan version 2.27.1
|
||||
```
|
||||
|
||||
The build uses Xcode's AppleTVOS SDK:
|
||||
|
||||
```bash
|
||||
xcrun --sdk appletvos --show-sdk-path
|
||||
```
|
||||
|
||||
## 3. Prepare Qt Sources
|
||||
|
||||
Do not edit the installed Qt sources in place. Copy them into a separate tvOS fork:
|
||||
|
||||
```bash
|
||||
mkdir -p "$HOME/Qt_tv"
|
||||
rsync -a "$HOME/Qt/6.9.2/Src/" "$QT_TVOS_SRC/"
|
||||
```
|
||||
|
||||
Recommended for reproducibility:
|
||||
|
||||
```bash
|
||||
cd "$QT_TVOS_SRC"
|
||||
git init
|
||||
git add .
|
||||
git commit -m "Qt 6.9.2 source snapshot"
|
||||
```
|
||||
|
||||
## 4. Apply the Qt tvOS Patchset
|
||||
|
||||
Apply the local Qt tvOS patchset to `$QT_TVOS_SRC`.
|
||||
|
||||
If you need to recreate the patchset from a fresh copy, compare these files against `$HOME/Qt/6.9.2/Src` and reapply the same changes:
|
||||
|
||||
- `qtbase/cmake/QtBaseGlobalTargets.cmake`
|
||||
- `qtbase/cmake/QtBaseHelpers.cmake`
|
||||
- `qtbase/cmake/QtBuildPathsHelpers.cmake`
|
||||
- `qtbase/cmake/QtMkspecHelpers.cmake`
|
||||
- `qtbase/cmake/QtConfig.cmake.in`
|
||||
- `qtbase/mkspecs/unsupported/macx-tvos-clang/qplatformdefs.h`
|
||||
- `qtbase/src/corelib/CMakeLists.txt`
|
||||
- `qtbase/src/corelib/platform/darwin/qdarwinpermissionplugin_location.mm`
|
||||
- `qtbase/src/gui/CMakeLists.txt`
|
||||
- `qtbase/src/widgets/CMakeLists.txt`
|
||||
- `qtbase/src/network/kernel/qnetworkproxy_darwin.cpp`
|
||||
- `qtbase/src/testlib/qtestcrashhandler.cpp`
|
||||
- `qtbase/src/plugins/platforms/ios/qiosapplicationdelegate.mm`
|
||||
- `qtbase/src/plugins/platforms/ios/qiosscreen.mm`
|
||||
- `qtbase/src/plugins/platforms/ios/qiostheme.mm`
|
||||
- `qtbase/src/plugins/platforms/ios/quiview.mm`
|
||||
- `qtbase/src/plugins/platforms/ios/qiosclipboard.mm`
|
||||
|
||||
Recommended after patching:
|
||||
|
||||
```bash
|
||||
git -C "$QT_TVOS_SRC" diff > "$HOME/Qt_tv/qt-6.9.2-tvos.patch"
|
||||
```
|
||||
|
||||
Do not use `QT_APPLE_SDK=appletvos`. The working path is `CMAKE_SYSTEM_NAME=tvOS` with `CMAKE_OSX_SYSROOT=appletvos`.
|
||||
|
||||
## 5. Build Qt 6.9.2 for Apple TV
|
||||
|
||||
Only the modules required by this project are built.
|
||||
|
||||
```bash
|
||||
mkdir -p /private/tmp/qt6.9.2-tvos-device-build
|
||||
cd /private/tmp/qt6.9.2-tvos-device-build
|
||||
|
||||
"$QT_TVOS_SRC/configure" \
|
||||
-release -static -appstore-compliant \
|
||||
-nomake tests -nomake examples \
|
||||
-submodules qtbase,qtdeclarative,qtshadertools,qtremoteobjects,qtsvg,qt5compat,qttools \
|
||||
-qt-host-path "$QT_DESKTOP_PREFIX" \
|
||||
-prefix "$QT_TVOS_PREFIX" \
|
||||
-- \
|
||||
-G Ninja \
|
||||
-DQT_QMAKE_TARGET_MKSPEC=macx-tvos-clang \
|
||||
-DCMAKE_SYSTEM_NAME=tvOS \
|
||||
-DCMAKE_OSX_SYSROOT=appletvos \
|
||||
-DCMAKE_OSX_ARCHITECTURES=arm64 \
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=17.0 \
|
||||
-DBUILD_SHARED_LIBS=OFF \
|
||||
-DQT_NO_APPLE_SDK_MAX_VERSION_CHECK=ON
|
||||
|
||||
cmake --build . --parallel 8
|
||||
cmake --install .
|
||||
```
|
||||
|
||||
Sanity checks:
|
||||
|
||||
```bash
|
||||
"$QT_TVOS_PREFIX/bin/qt-cmake" --version
|
||||
"$QT_TVOS_PREFIX/bin/qmake" -query QMAKE_XSPEC
|
||||
```
|
||||
|
||||
Expected `QMAKE_XSPEC`:
|
||||
|
||||
```text
|
||||
macx-tvos-clang
|
||||
```
|
||||
|
||||
Return to the repository root after building Qt:
|
||||
|
||||
```bash
|
||||
cd "$REPO_ROOT"
|
||||
```
|
||||
|
||||
## 6. Conan Dependency Behavior
|
||||
|
||||
For `CMAKE_SYSTEM_NAME=tvOS`, the project-level Conan graph is intentionally reduced:
|
||||
|
||||
- included: `awg-apple/2.0.1`
|
||||
- included: `libssh/0.11.3@amnezia`
|
||||
- included: `openssl/3.6.1` with `no_apps=True`
|
||||
- excluded: `openvpnadapter`
|
||||
- excluded: `hev-socks5-tunnel`
|
||||
|
||||
This keeps the current Apple TV target in the same practical scope as before: app plus WireGuard-only Network Extension.
|
||||
|
||||
`libssh` is built with `WITH_EXEC=OFF` on tvOS because tvOS does not provide `fork()` or `execv()`.
|
||||
|
||||
## 7. Configure the Project
|
||||
|
||||
From the repository root:
|
||||
|
||||
```bash
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
"$QT_TVOS_PREFIX/bin/qt-cmake" \
|
||||
-B"$BUILD_DIR" \
|
||||
-GXcode \
|
||||
-DQT_HOST_PATH="$QT_DESKTOP_PREFIX" \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DCMAKE_SYSTEM_NAME=tvOS \
|
||||
-DCMAKE_OSX_SYSROOT=appletvos
|
||||
```
|
||||
|
||||
If you need to provide an external initialized `client/3rd` tree:
|
||||
|
||||
```bash
|
||||
"$QT_TVOS_PREFIX/bin/qt-cmake" \
|
||||
-B"$BUILD_DIR" \
|
||||
-GXcode \
|
||||
-DQT_HOST_PATH="$QT_DESKTOP_PREFIX" \
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||
-DCMAKE_SYSTEM_NAME=tvOS \
|
||||
-DCMAKE_OSX_SYSROOT=appletvos \
|
||||
-DAMNEZIA_THIRDPARTY_ROOT="$AMNEZIA_THIRDPARTY_ROOT"
|
||||
```
|
||||
|
||||
Expected non-fatal configure warnings:
|
||||
|
||||
```text
|
||||
Warning: plug-in QIOSIntegrationPlugin is not known to the current Qt installation.
|
||||
Warning: plug-in QJpegPlugin is not known to the current Qt installation.
|
||||
...
|
||||
```
|
||||
|
||||
In this repo those warnings are tolerated because `client/cmake/ios.cmake` also links the static plugin targets explicitly when available.
|
||||
|
||||
## 8. Build the Apple TV App
|
||||
|
||||
```bash
|
||||
xcodebuild -quiet \
|
||||
-project "$BUILD_DIR/AmneziaVPN.xcodeproj" \
|
||||
-scheme AmneziaVPN \
|
||||
-configuration RelWithDebInfo \
|
||||
-sdk appletvos \
|
||||
CODE_SIGNING_ALLOWED=NO \
|
||||
build
|
||||
```
|
||||
|
||||
Outputs:
|
||||
|
||||
- `$BUILD_DIR/client/RelWithDebInfo-appletvos/AmneziaVPN.app`
|
||||
- `$BUILD_DIR/client/RelWithDebInfo-appletvos/AmneziaVPN.app/PlugIns/AmneziaVPNNetworkExtension.appex`
|
||||
|
||||
Verification:
|
||||
|
||||
```bash
|
||||
file "$BUILD_DIR/client/RelWithDebInfo-appletvos/AmneziaVPN.app/AmneziaVPN"
|
||||
file "$BUILD_DIR/client/RelWithDebInfo-appletvos/AmneziaVPN.app/PlugIns/AmneziaVPNNetworkExtension.appex/AmneziaVPNNetworkExtension"
|
||||
lipo -info "$BUILD_DIR/client/RelWithDebInfo-appletvos/AmneziaVPN.app/AmneziaVPN"
|
||||
lipo -info "$BUILD_DIR/client/RelWithDebInfo-appletvos/AmneziaVPN.app/PlugIns/AmneziaVPNNetworkExtension.appex/AmneziaVPNNetworkExtension"
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
```text
|
||||
Mach-O 64-bit executable arm64
|
||||
Non-fat file: ... is architecture: arm64
|
||||
```
|
||||
|
||||
Useful plist checks:
|
||||
|
||||
```bash
|
||||
plutil -p "$BUILD_DIR/client/RelWithDebInfo-appletvos/AmneziaVPN.app/Info.plist" | rg 'CFBundleIdentifier|DTPlatformName|UIDeviceFamily|MinimumOSVersion' -C 1
|
||||
plutil -p "$BUILD_DIR/client/RelWithDebInfo-appletvos/AmneziaVPN.app/PlugIns/AmneziaVPNNetworkExtension.appex/Info.plist" | rg 'CFBundleIdentifier|NSExtension|DTPlatformName|MinimumOSVersion' -C 1
|
||||
```
|
||||
|
||||
Expected:
|
||||
|
||||
- `DTPlatformName => appletvos`
|
||||
- `UIDeviceFamily => 3`
|
||||
- `MinimumOSVersion => 17.0`
|
||||
- extension point `com.apple.networkextension.packet-tunnel`
|
||||
|
||||
## 9. `.app` vs `.ipa`
|
||||
|
||||
This is the normal sequence:
|
||||
|
||||
1. `xcodebuild build` -> `.app`
|
||||
2. `xcodebuild archive` -> `.xcarchive`
|
||||
3. `xcodebuild -exportArchive` -> `.ipa`
|
||||
|
||||
So seeing `.app` after a successful `build` is correct.
|
||||
|
||||
## 10. Optional Archive and Export
|
||||
|
||||
The commands below are the next step for packaging, but signing and provisioning must be configured first.
|
||||
|
||||
Archive:
|
||||
|
||||
```bash
|
||||
xcodebuild \
|
||||
-project "$BUILD_DIR/AmneziaVPN.xcodeproj" \
|
||||
-scheme AmneziaVPN \
|
||||
-configuration RelWithDebInfo \
|
||||
-sdk appletvos \
|
||||
-archivePath "$BUILD_DIR/AmneziaVPN-tvos.xcarchive" \
|
||||
archive
|
||||
```
|
||||
|
||||
Export:
|
||||
|
||||
```bash
|
||||
xcodebuild -exportArchive \
|
||||
-archivePath "$BUILD_DIR/AmneziaVPN-tvos.xcarchive" \
|
||||
-exportPath "$BUILD_DIR/export-tvos" \
|
||||
-exportOptionsPlist /absolute/path/to/ExportOptions.plist
|
||||
```
|
||||
|
||||
The resulting `.ipa` should appear under:
|
||||
|
||||
```text
|
||||
$BUILD_DIR/export-tvos
|
||||
```
|
||||
|
||||
## 11. Known Non-Fatal Warnings
|
||||
|
||||
The validated `xcodebuild` still prints warnings that do not break the build:
|
||||
|
||||
- missing Swift search path under the active Xcode Metal toolchain
|
||||
- `SDKROOT[sdk=...]` target-level warnings generated by Xcode project export
|
||||
- Swift conditional compilation flag warnings such as `GROUP_ID="..."`
|
||||
- asset catalog warnings because the current icon set is still iOS-shaped, not a full tvOS Top Shelf asset set
|
||||
- Go/WireGuard umbrella-header warnings from the temporary local `libwg-go.a` bridge
|
||||
- deprecated libssh SCP API warnings in existing app code
|
||||
- `qt_import_plugins()` warnings shown during configure
|
||||
|
||||
If the static platform plugin is not linked correctly, the typical failure is:
|
||||
|
||||
- `_OBJC_CLASS_$_QIOSApplicationDelegate`
|
||||
- `_qt_main_wrapper`
|
||||
|
||||
Those are cleanup tasks, not blockers for the current build proof.
|
||||
|
||||
## 12. Fast Rebuild Checklist
|
||||
|
||||
If everything is already built once:
|
||||
|
||||
1. Reuse `$QT_TVOS_PREFIX`
|
||||
2. Reuse Conan cache under `$HOME/.conan2`
|
||||
3. Reuse or pass an initialized `AMNEZIA_THIRDPARTY_ROOT`
|
||||
4. Re-run `qt-cmake` into `$BUILD_DIR`
|
||||
5. Re-run `xcodebuild -quiet ... build`
|
||||
@@ -3,6 +3,9 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
|
||||
set(PROJECT AmneziaVPN)
|
||||
project(${PROJECT})
|
||||
|
||||
set(AMNEZIA_THIRDPARTY_ROOT "${CMAKE_CURRENT_LIST_DIR}/3rd" CACHE PATH "Path to Amnezia client/3rd sources")
|
||||
get_filename_component(AMNEZIA_THIRDPARTY_CLIENT_ROOT "${AMNEZIA_THIRDPARTY_ROOT}/.." ABSOLUTE)
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
set_property(GLOBAL PROPERTY AUTOGEN_TARGETS_FOLDER "Autogen")
|
||||
set_property(GLOBAL PROPERTY AUTOMOC_TARGETS_FOLDER "Autogen")
|
||||
@@ -108,6 +111,7 @@ include_directories(
|
||||
${CMAKE_CURRENT_LIST_DIR}/../ipc
|
||||
${CMAKE_CURRENT_LIST_DIR}/../common/logger
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
${AMNEZIA_THIRDPARTY_CLIENT_ROOT}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
@@ -209,26 +213,28 @@ else()
|
||||
qt_finalize_target(${PROJECT})
|
||||
endif()
|
||||
|
||||
install(TARGETS ${PROJECT}
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT AmneziaVPN
|
||||
)
|
||||
install(FILES $<TARGET_RUNTIME_DLLS:${PROJECT}>
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT AmneziaVPN
|
||||
)
|
||||
if(NOT IOS AND NOT CMAKE_SYSTEM_NAME STREQUAL "tvOS")
|
||||
install(TARGETS ${PROJECT}
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT AmneziaVPN
|
||||
)
|
||||
install(FILES $<TARGET_RUNTIME_DLLS:${PROJECT}>
|
||||
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
COMPONENT AmneziaVPN
|
||||
)
|
||||
|
||||
set(deploy_tool_options "")
|
||||
if(WIN32)
|
||||
set(deploy_tool_options "--force-openssl --force")
|
||||
set(deploy_tool_options "")
|
||||
if(WIN32)
|
||||
set(deploy_tool_options "--force-openssl --force")
|
||||
endif()
|
||||
|
||||
qt_generate_deploy_qml_app_script(
|
||||
TARGET ${PROJECT}
|
||||
OUTPUT_SCRIPT QT_DEPLOY_SCRIPT
|
||||
NO_UNSUPPORTED_PLATFORM_ERROR
|
||||
DEPLOY_TOOL_OPTIONS ${deploy_tool_options}
|
||||
)
|
||||
install(SCRIPT ${QT_DEPLOY_SCRIPT}
|
||||
COMPONENT AmneziaVPN
|
||||
)
|
||||
endif()
|
||||
|
||||
qt_generate_deploy_qml_app_script(
|
||||
TARGET ${PROJECT}
|
||||
OUTPUT_SCRIPT QT_DEPLOY_SCRIPT
|
||||
NO_UNSUPPORTED_PLATFORM_ERROR
|
||||
DEPLOY_TOOL_OPTIONS ${deploy_tool_options}
|
||||
)
|
||||
install(SCRIPT ${QT_DEPLOY_SCRIPT}
|
||||
COMPONENT AmneziaVPN
|
||||
)
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
set(CLIENT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/..)
|
||||
set(AMNEZIA_THIRDPARTY_ROOT "${CLIENT_ROOT_DIR}/3rd" CACHE PATH "Path to Amnezia client/3rd sources")
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/Modules;${CMAKE_MODULE_PATH}")
|
||||
|
||||
add_subdirectory(${CLIENT_ROOT_DIR}/3rd/SortFilterProxyModel)
|
||||
add_subdirectory(${AMNEZIA_THIRDPARTY_ROOT}/SortFilterProxyModel ${CMAKE_CURRENT_BINARY_DIR}/3rd/SortFilterProxyModel)
|
||||
set(LIBS ${LIBS} SortFilterProxyModel)
|
||||
include(${CLIENT_ROOT_DIR}/cmake/QSimpleCrypto.cmake)
|
||||
|
||||
include(${CLIENT_ROOT_DIR}/3rd/qrcodegen/qrcodegen.cmake)
|
||||
include(${AMNEZIA_THIRDPARTY_ROOT}/qrcodegen/qrcodegen.cmake)
|
||||
|
||||
add_compile_definitions(_WINSOCKAPI_)
|
||||
|
||||
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
|
||||
set(BUILD_WITH_QT6 ON)
|
||||
add_subdirectory(${CLIENT_ROOT_DIR}/3rd/qtkeychain EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(${AMNEZIA_THIRDPARTY_ROOT}/qtkeychain ${CMAKE_CURRENT_BINARY_DIR}/3rd/qtkeychain EXCLUDE_FROM_ALL)
|
||||
|
||||
if(ANDROID)
|
||||
# Use qtgamepad from amnezia-vpn/qtgamepad repository
|
||||
@@ -36,8 +37,8 @@ endif()
|
||||
set(LIBS ${LIBS} qt6keychain)
|
||||
|
||||
include_directories(
|
||||
${CLIENT_ROOT_DIR}/3rd/QSimpleCrypto/src/include
|
||||
${CLIENT_ROOT_DIR}/3rd/qtkeychain/qtkeychain
|
||||
${AMNEZIA_THIRDPARTY_ROOT}/QSimpleCrypto/src/include
|
||||
${AMNEZIA_THIRDPARTY_ROOT}/qtkeychain/qtkeychain
|
||||
${CMAKE_CURRENT_BINARY_DIR}/3rd/qtkeychain
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
set(CLIENT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/..)
|
||||
set(QSIMPLECRYPTO_DIR ${CLIENT_ROOT_DIR}/3rd/QSimpleCrypto/src)
|
||||
set(AMNEZIA_THIRDPARTY_ROOT "${CLIENT_ROOT_DIR}/3rd" CACHE PATH "Path to Amnezia client/3rd sources")
|
||||
set(QSIMPLECRYPTO_DIR ${AMNEZIA_THIRDPARTY_ROOT}/QSimpleCrypto/src)
|
||||
|
||||
include_directories(${QSIMPLECRYPTO_DIR})
|
||||
|
||||
|
||||
@@ -211,7 +211,8 @@ if(AMNEZIA_IOS_APPLETV)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(WG_APPLE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/amneziawg-apple/Sources)
|
||||
set(AMNEZIA_THIRDPARTY_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/3rd" CACHE PATH "Path to Amnezia client/3rd sources")
|
||||
set(WG_APPLE_SOURCE_DIR ${AMNEZIA_THIRDPARTY_ROOT}/amneziawg-apple/Sources)
|
||||
|
||||
target_sources(${PROJECT} PRIVATE
|
||||
# ${CMAKE_CURRENT_SOURCE_DIR}/platforms/ios/iosvpnprotocol.swift
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
enable_language(Swift)
|
||||
|
||||
set(CLIENT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
|
||||
set(AMNEZIA_THIRDPARTY_ROOT "${CLIENT_ROOT_DIR}/3rd" CACHE PATH "Path to Amnezia client/3rd sources")
|
||||
set(AMNEZIA_IOS_APPLETV ${AMNEZIA_IOS_ENABLE_APPLETV_TARGET})
|
||||
|
||||
if(AMNEZIA_IOS_APPLETV)
|
||||
@@ -94,7 +95,7 @@ endif()
|
||||
target_compile_options(networkextension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\")
|
||||
target_compile_options(networkextension PRIVATE -DNETWORK_EXTENSION=1)
|
||||
|
||||
set(WG_APPLE_SOURCE_DIR ${CLIENT_ROOT_DIR}/3rd/amneziawg-apple/Sources)
|
||||
set(WG_APPLE_SOURCE_DIR ${AMNEZIA_THIRDPARTY_ROOT}/amneziawg-apple/Sources)
|
||||
|
||||
set(NE_COMMON_SOURCES
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/NELogController.swift
|
||||
|
||||
6
client/platforms/ios/tvos_cgo_stubs.c
Normal file
6
client/platforms/ios/tvos_cgo_stubs.c
Normal file
@@ -0,0 +1,6 @@
|
||||
/*
|
||||
* tvOS does not export these iOS runtime helpers used by Go cgo archives.
|
||||
* WireGuardKitGo references them indirectly; provide no-op stubs for tvOS.
|
||||
*/
|
||||
void darwin_arm_init_mach_exception_handler(void) {}
|
||||
void darwin_arm_init_thread_exception_port(void) {}
|
||||
@@ -1,11 +1,21 @@
|
||||
if(APPLE)
|
||||
get_property(generator_is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if (generator_is_multi_config)
|
||||
set(CONAN_INSTALL_BUILD_CONFIGURATIONS Release Debug MinSizeRel RelWithDebInfo)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "tvOS")
|
||||
set(CONAN_INSTALL_BUILD_CONFIGURATIONS RelWithDebInfo)
|
||||
else()
|
||||
set(CONAN_INSTALL_BUILD_CONFIGURATIONS Release Debug MinSizeRel RelWithDebInfo)
|
||||
endif()
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "14.0" CACHE STRING "" FORCE)
|
||||
set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "" FORCE)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "tvOS")
|
||||
set(CONAN_INSTALL_ARGS "--build=missing;-o;openssl/3.6.1:no_apps=True" CACHE STRING "" FORCE)
|
||||
set(AMNEZIA_IOS_ENABLE_APPLETV_TARGET ON CACHE BOOL "" FORCE)
|
||||
set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo" CACHE STRING "" FORCE)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "17.0" CACHE STRING "" FORCE)
|
||||
set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "" FORCE)
|
||||
elseif(MACOS_NE)
|
||||
set(CONAN_INSTALL_ARGS "--build=missing;-o=&:macos_ne=True" CACHE STRING "" FORCE)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "13.0" CACHE STRING "" FORCE)
|
||||
|
||||
@@ -14,7 +14,7 @@ class AmneziaVPN(ConanFile):
|
||||
def requirements(self):
|
||||
os = str(self.settings.os)
|
||||
|
||||
has_ne = os == "iOS" or (os == "Macos" and self.options.macos_ne)
|
||||
has_ne = os in ["iOS", "tvOS"] or (os == "Macos" and self.options.macos_ne)
|
||||
has_service = os == "Windows" or os == "Linux" or (os == "Macos" and not has_ne)
|
||||
|
||||
if has_service:
|
||||
@@ -33,8 +33,9 @@ class AmneziaVPN(ConanFile):
|
||||
|
||||
if has_ne:
|
||||
self.requires("awg-apple/2.0.1")
|
||||
self.requires("hev-socks5-tunnel/2.14.4", options={"as_framework": True})
|
||||
self.requires("openvpnadapter/1.0.0")
|
||||
if os != "tvOS":
|
||||
self.requires("hev-socks5-tunnel/2.14.4", options={"as_framework": True})
|
||||
self.requires("openvpnadapter/1.0.0")
|
||||
|
||||
if os == "Android":
|
||||
self.requires("amnezia-libxray/1.0.0")
|
||||
@@ -42,4 +43,4 @@ class AmneziaVPN(ConanFile):
|
||||
self.requires("openvpn-pt-android/1.0.0")
|
||||
|
||||
self.requires("libssh/0.11.3@amnezia")
|
||||
self.requires("openssl/3.6.1")
|
||||
self.requires("openssl/3.6.1", options={"no_apps": os == "tvOS"}, force=os == "tvOS")
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
from conan import ConanFile
|
||||
from conan.errors import ConanInvalidConfiguration
|
||||
from conan.tools.layout import basic_layout
|
||||
from conan.tools.files import get, copy, collect_libs
|
||||
from conan.tools.files import get, copy, collect_libs, replace_in_file
|
||||
from conan.tools.apple import is_apple_os
|
||||
from conan.tools.gnu import AutotoolsToolchain, Autotools
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
TVOS_PREBUILT_DIR_ENV = "AMNEZIA_TVOS_AWG_PREBUILT_DIR"
|
||||
TVOS_VERSION_HEADER_DIR_ENV = "AMNEZIA_TVOS_AWG_VERSION_HEADER_DIR"
|
||||
|
||||
|
||||
class AwgApple(ConanFile):
|
||||
name = "awg-apple"
|
||||
@@ -18,6 +23,10 @@ class AwgApple(ConanFile):
|
||||
"as_framework": False
|
||||
}
|
||||
|
||||
@property
|
||||
def _is_tvos(self):
|
||||
return str(self.settings.os) == "tvOS"
|
||||
|
||||
@property
|
||||
def _goarch(self):
|
||||
arch_map = {
|
||||
@@ -27,9 +36,6 @@ class AwgApple(ConanFile):
|
||||
archs = str(self.settings.arch).split("|")
|
||||
return " ".join(arch_map.get(arch, arch) for arch in archs)
|
||||
|
||||
def build_requirements(self):
|
||||
self.tool_requires("go/1.26.0")
|
||||
|
||||
def layout(self):
|
||||
basic_layout(self, build_folder=os.path.join(self.folders.source, "Sources/WireGuardKitGo"))
|
||||
|
||||
@@ -44,16 +50,96 @@ class AwgApple(ConanFile):
|
||||
sha256="9fe4f8cfbb6a751558b54b7979db3a5ea46e49731912aae99f093e84a1433e97", strip_root=True
|
||||
)
|
||||
|
||||
def _go_env(self):
|
||||
env = os.environ.copy()
|
||||
env["GOTOOLCHAIN"] = "local"
|
||||
return env
|
||||
|
||||
def _go_root(self):
|
||||
try:
|
||||
return subprocess.check_output(
|
||||
["go", "env", "GOROOT"],
|
||||
text=True,
|
||||
env=self._go_env(),
|
||||
cwd="/",
|
||||
).strip()
|
||||
except (FileNotFoundError, subprocess.CalledProcessError) as error:
|
||||
raise ConanInvalidConfiguration(
|
||||
"Go is required to build awg-apple. Install Go or provide a tvOS "
|
||||
f"prebuilt bridge through {TVOS_PREBUILT_DIR_ENV}."
|
||||
) from error
|
||||
|
||||
def _env_path(self, name):
|
||||
value = os.environ.get(name)
|
||||
if not value:
|
||||
return None
|
||||
return os.path.abspath(os.path.expanduser(value))
|
||||
|
||||
def _uses_tvos_prebuilt_bridge(self):
|
||||
return self._is_tvos and self._env_path(TVOS_PREBUILT_DIR_ENV) is not None
|
||||
|
||||
def _make_args(self):
|
||||
if self._uses_tvos_prebuilt_bridge():
|
||||
return []
|
||||
|
||||
sdk = self.settings.get_safe("os.sdk", "macosx")
|
||||
args = [
|
||||
f"ARCHS={self._goarch}",
|
||||
f"PLATFORM_NAME={sdk}",
|
||||
f"REAL_GOROOT={self._go_root()}",
|
||||
"GOTOOLCHAIN=local",
|
||||
]
|
||||
if self._is_tvos:
|
||||
args.extend([
|
||||
"GOOS_appletvos=ios",
|
||||
"GOFLAGS=-tags=netgo",
|
||||
"DEPLOYMENT_TARGET_CLANG_FLAG_NAME=mtvos-version-min",
|
||||
"DEPLOYMENT_TARGET_CLANG_ENV_NAME=TVOS_DEPLOYMENT_TARGET",
|
||||
f"TVOS_DEPLOYMENT_TARGET={self.settings.os.version}",
|
||||
])
|
||||
return args
|
||||
|
||||
def generate(self):
|
||||
tc = AutotoolsToolchain(self)
|
||||
sdk = self.settings.get_safe("os.sdk", "macosx")
|
||||
tc.make_args = [
|
||||
f"ARCHS={self._goarch}",
|
||||
f"PLATFORM_NAME={sdk}"
|
||||
]
|
||||
tc.make_args = self._make_args()
|
||||
tc.generate()
|
||||
|
||||
def _copy_tvos_prebuilt_bridge(self):
|
||||
prebuilt_dir = self._env_path(TVOS_PREBUILT_DIR_ENV)
|
||||
if not prebuilt_dir:
|
||||
return False
|
||||
|
||||
lib_path = os.path.join(prebuilt_dir, "libwg-go.a")
|
||||
if not os.path.isfile(lib_path):
|
||||
raise ConanInvalidConfiguration(
|
||||
f"{TVOS_PREBUILT_DIR_ENV} is set to '{prebuilt_dir}', but libwg-go.a was not found there."
|
||||
)
|
||||
|
||||
header_dir = self._env_path(TVOS_VERSION_HEADER_DIR_ENV) or prebuilt_dir
|
||||
header_path = os.path.join(header_dir, "wireguard-go-version.h")
|
||||
if not os.path.isfile(header_path):
|
||||
raise ConanInvalidConfiguration(
|
||||
f"wireguard-go-version.h was not found in '{header_dir}'. Set "
|
||||
f"{TVOS_VERSION_HEADER_DIR_ENV} if the header lives outside {TVOS_PREBUILT_DIR_ENV}."
|
||||
)
|
||||
|
||||
self.output.warning(
|
||||
f"Using explicit tvOS WireGuard bridge from {TVOS_PREBUILT_DIR_ENV}={prebuilt_dir}"
|
||||
)
|
||||
out_dir = os.path.join(self.build_folder, "out")
|
||||
copy(self, "libwg-go.a", src=prebuilt_dir, dst=out_dir)
|
||||
copy(self, "wireguard-go-version.h", src=header_dir, dst=out_dir)
|
||||
return True
|
||||
|
||||
def _patch_tvos_go_version_for_local_toolchain(self):
|
||||
replace_in_file(self, os.path.join(self.build_folder, "go.mod"), "go 1.26", "go 1.25")
|
||||
|
||||
def build(self):
|
||||
if self._is_tvos:
|
||||
if self._copy_tvos_prebuilt_bridge():
|
||||
return
|
||||
self._patch_tvos_go_version_for_local_toolchain()
|
||||
|
||||
autotools = Autotools(self)
|
||||
autotools.make()
|
||||
autotools.make("version-header")
|
||||
|
||||
@@ -78,6 +78,8 @@ class LibSSHRecipe(ConanFile):
|
||||
tc.cache_variables["WITH_MBEDTLS"] = self.options.crypto_backend == "mbedtls"
|
||||
tc.cache_variables["WITH_NACL"] = False
|
||||
tc.cache_variables["WITH_SYMBOL_VERSIONING"] = self.options.get_safe("with_symbol_versioning", True)
|
||||
if self.settings.os == "tvOS":
|
||||
tc.cache_variables["WITH_EXEC"] = False
|
||||
tc.variables["WITH_ZLIB"] = self.options.with_zlib
|
||||
if is_msvc(self):
|
||||
tc.cache_variables["USE_MSVC_RUNTIME_LIBRARY_DLL"] = not is_msvc_static_runtime(self)
|
||||
|
||||
Reference in New Issue
Block a user