diff --git a/apps/ios/CrossDeskMobile.xcodeproj/project.pbxproj b/apps/ios/CrossDeskMobile.xcodeproj/project.pbxproj index 3cebddfe..c3a2d28d 100644 --- a/apps/ios/CrossDeskMobile.xcodeproj/project.pbxproj +++ b/apps/ios/CrossDeskMobile.xcodeproj/project.pbxproj @@ -391,7 +391,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 3; - DEVELOPMENT_TEAM = 8DNC3SZ86S; + DEVELOPMENT_TEAM = RJZC936RL7; ENABLE_BITCODE = NO; ENABLE_USER_SCRIPT_SANDBOXING = NO; GENERATE_INFOPLIST_FILE = NO; @@ -424,7 +424,7 @@ "-framework", Foundation, ); - PRODUCT_BUNDLE_IDENTIFIER = cn.crossdesk.mobile; + PRODUCT_BUNDLE_IDENTIFIER = com.chunkdash.crossdesk; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SWIFT_OBJC_BRIDGING_HEADER = "CrossDeskMobile/CrossDeskMobile-Bridging-Header.h"; @@ -441,7 +441,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 3; - DEVELOPMENT_TEAM = 8DNC3SZ86S; + DEVELOPMENT_TEAM = RJZC936RL7; ENABLE_BITCODE = NO; ENABLE_USER_SCRIPT_SANDBOXING = NO; GENERATE_INFOPLIST_FILE = NO; @@ -474,7 +474,7 @@ "-framework", Foundation, ); - PRODUCT_BUNDLE_IDENTIFIER = cn.crossdesk.mobile; + PRODUCT_BUNDLE_IDENTIFIER = com.chunkdash.crossdesk; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SWIFT_OBJC_BRIDGING_HEADER = "CrossDeskMobile/CrossDeskMobile-Bridging-Header.h"; diff --git a/apps/ios/CrossDeskMobile.xcodeproj/xcshareddata/xcodecloud/manifest.json b/apps/ios/CrossDeskMobile.xcodeproj/xcshareddata/xcodecloud/manifest.json new file mode 100644 index 00000000..636a2849 --- /dev/null +++ b/apps/ios/CrossDeskMobile.xcodeproj/xcshareddata/xcodecloud/manifest.json @@ -0,0 +1,9 @@ +{ + "id" : "528214fb-1170-4293-86d0-859db2b1908b", + "targets" : [ + { + "id" : "34a4d067-7914-4e8a-b72a-fda820282321", + "name" : "CrossDeskMobile" + } + ] +} \ No newline at end of file diff --git a/apps/ios/README.md b/apps/ios/README.md index db95aabb..18f9c60a 100644 --- a/apps/ios/README.md +++ b/apps/ios/README.md @@ -88,7 +88,7 @@ with Xmake precompiled package downloads disabled. target and scheme. 2. Under **Signing & Capabilities**, select your own development team and set a bundle identifier available to that team. The checked-in signing team - and `cn.crossdesk.mobile` identifier belong to the project maintainer. + and `com.chunkdash.crossdesk` identifier belong to ChunkDash. 3. Connect and select a physical iPhone or iPad, configure device trust and Developer Mode as prompted by Xcode, then build and run. See Apple's [device setup guide](https://developer.apple.com/documentation/xcode/running-your-app-on-simulated-or-physical-devices). @@ -141,6 +141,27 @@ for that server. Remote control sessions then log in as `C-` and use the desktop-compatible `DisplayN`, `control_audio`, `mouse`, `keyboard`, `control_data`, `clipboard`, `file`, and `file_feedback` streams. +## Xcode Cloud + +Select `apps/ios/CrossDeskMobile.xcodeproj`, the shared `CrossDeskMobile` +scheme, and an **Archive - iOS** action with **App Store Connect** distribution +preparation (called **TestFlight and App Store** in some Xcode versions). +Commit and push the intended signing settings and shared scheme to the branch +selected by the workflow before starting a build. + +Xcode Cloud automatically runs `ci_scripts/ci_post_clone.sh` next to the Xcode +project. It installs Xmake, CMake, and Python 3.13 with Homebrew, prepares an +isolated host Python environment with pip/setuptools/wheel, verifies the minimum +Xmake version, and initializes the pinned MiniRTC submodules. The native build +phase selects these tools again and preserves Cloud's proxy settings for package +downloads. No manual workflow PATH setting or `sudo` command is required. + +The first archive compiles native dependencies from source and may take longer +than later builds. After changing the setup script, start a build from the new +commit; rebuilding an older commit does not include the fix. App Store releases +still need the source-tag and bundle checks described in **App Store archive +and bundle validation** below. + ## GitHub Actions [`Build iOS`](../../.github/workflows/build-ios.yml) can run independently from diff --git a/apps/ios/ci_scripts/ci_post_clone.sh b/apps/ios/ci_scripts/ci_post_clone.sh new file mode 100755 index 00000000..20b433e5 --- /dev/null +++ b/apps/ios/ci_scripts/ci_post_clone.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +set -eu + +SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" +IOS_DIR="$(dirname "$SCRIPT_DIR")" +REPO_DIR="$(git -C "$IOS_DIR" rev-parse --show-toplevel)" +HOST_TOOLS_DIR="${IOS_DIR}/.xmake/xcode-cloud-host" + +if ! command -v brew >/dev/null 2>&1; then + echo "Xcode Cloud requires Homebrew to install the iOS build tools." >&2 + exit 69 +fi + +echo "Installing Xcode Cloud native build tools" +brew install xmake cmake python@3.13 +BREW_PREFIX="$(brew --prefix)" +PYTHON_PREFIX="$(brew --prefix python@3.13)" + +# Match GitHub Actions' host Python dependencies without modifying Homebrew's +# externally managed Python. The Xcode build phase selects this environment +# explicitly because exports here do not persist into later Cloud steps. +"${PYTHON_PREFIX}/bin/python3.13" -m venv "$HOST_TOOLS_DIR" +"${HOST_TOOLS_DIR}/bin/python3" -m pip install --upgrade pip setuptools wheel +for tool in xmake xrepo cmake ctest cpack; do + ln -sf "${BREW_PREFIX}/bin/${tool}" "${HOST_TOOLS_DIR}/bin/${tool}" +done + +"${HOST_TOOLS_DIR}/bin/xmake" --version > "${HOST_TOOLS_DIR}/xmake-version.txt" +"${HOST_TOOLS_DIR}/bin/python3" -B "${IOS_DIR}/scripts/verify_native_build.py" \ + --xmake-version "${HOST_TOOLS_DIR}/xmake-version.txt" + +echo "Initializing MiniRTC submodules" +git -C "$REPO_DIR" submodule sync --recursive +git -C "$REPO_DIR" submodule update --init --recursive + +echo "Xcode Cloud iOS build tools are ready" diff --git a/apps/ios/scripts/build_minirtc_ios.sh b/apps/ios/scripts/build_minirtc_ios.sh index d2a458fa..d3109903 100755 --- a/apps/ios/scripts/build_minirtc_ios.sh +++ b/apps/ios/scripts/build_minirtc_ios.sh @@ -46,6 +46,17 @@ if [[ "${ARCH_NAME}" != "arm64" ]]; then exit 64 fi +# Post-clone scripts run in a separate process, so select their installed host +# tools again here instead of relying on exported PATH changes surviving. +if [[ "${CI_XCODE_CLOUD:-}" == "TRUE" ]]; then + CLOUD_HOST_BIN="${IOS_DIR}/.xmake/xcode-cloud-host/bin" + if [[ ! -x "${CLOUD_HOST_BIN}/xmake" || ! -x "${CLOUD_HOST_BIN}/python3" ]]; then + print -u2 "Xcode Cloud build tools are missing. Run ci_scripts/ci_post_clone.sh before building." + exit 69 + fi + export PATH="${CLOUD_HOST_BIN}:${PATH}" +fi + XMAKE_BIN="${XMAKE_BIN:-}" if [[ -z "${XMAKE_BIN}" ]]; then XMAKE_BIN="$(command -v xmake 2>/dev/null || true)" @@ -89,6 +100,16 @@ run_xmake() { if [[ -n "${XMAKE_MAIN_REPO:-}" ]]; then xmake_env+=("XMAKE_MAIN_REPO=${XMAKE_MAIN_REPO}") fi + # Cloud dependency downloads use Apple's HTTP proxy. Keep those settings + # while still stripping Xcode's iOS compiler and SDK environment variables. + if [[ "${CI_XCODE_CLOUD:-}" == "TRUE" ]]; then + local proxy_name + for proxy_name in HTTP_PROXY HTTPS_PROXY NO_PROXY http_proxy https_proxy no_proxy; do + if (( ${+parameters[$proxy_name]} )); then + xmake_env+=("${proxy_name}=${(P)proxy_name}") + fi + done + fi /usr/bin/env -i \ HOME="${HOME}" \ PATH="${XMAKE_HOST_PATH}" \