diff --git a/CMakePresets.json b/CMakePresets.json index 32a76621..2b0ac1f5 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -26,7 +26,8 @@ "cacheVariables": { "VCPKG_TARGET_TRIPLET": "arm64-ios", "VCPKG_CHAINLOAD_TOOLCHAIN_FILE": "${sourceDir}/overlaytriplets/arm64-ios.cmake", - "PLATFORM": "OS64" + "PLATFORM": "OS64", + "DEPLOYMENT_TARGET": "26.0" } }, { diff --git a/MODERNIZATION.md b/MODERNIZATION.md index 33a6da2b..d09a0576 100644 --- a/MODERNIZATION.md +++ b/MODERNIZATION.md @@ -110,7 +110,7 @@ Android NDK r28+. (all three run fully against a local `--local` subscriber on 127.0.0.1:44211). -## Phase 1.2 — Compiler upgrades + CI image modernization (PR #23, in review) +## Phase 1.2 — Compiler upgrades + CI image modernization ✅ (PR #23, merged) - macOS: dead `llvm@17` → latest keg-only Homebrew `llvm` (22.x), located via `LLVM_PREFIX` (exported by `install-prerequisities.sh`, fallback `$HOMEBREW_PREFIX/opt/llvm`); hardcoded `/opt/homebrew/...` libc++ paths @@ -174,7 +174,7 @@ Android NDK r28+. `iostest.sh` green — the compiler's output must stay compatible with the device's fixed libc++ runtime**. -## Phase 1.3 — vcpkg baseline bump + dependency wave (PR pending) +## Phase 1.3 — vcpkg baseline bump + dependency wave ✅ (PR #24, merged) Baseline: vcpkg tag **2026.06.24** (`builtin-baseline` now pinned in `vcpkg.json`; the jq-based merge-dependencies.sh preserves the key — and because the cache keys hash `vcpkg.json`, baseline bumps bust CI caches @@ -225,24 +225,49 @@ the triplet FILE as the chainload toolchain; the triplet then points `VCPKG_CHAINLOAD_TOOLCHAIN_FILE` at ios.toolchain.cmake for ports) — fragile; document/replace in 1.4. -## Phase 1.4 — iOS refresh -- Replace `toolchains/ios.toolchain.cmake` with latest leetal/ios-cmake - verbatim (keep vendored & unmodified). -- **Fix the libc++ header/runtime mismatch properly** in - `overlaytriplets/arm64-ios.cmake`: compile with `-nostdinc++ -isystem - /usr/include/c++/v1` (SDK path via `xcrun`), link SDK libc++ - normally. Delete the Homebrew-libc++ `-isystem`, the - `_LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION=0` define and `-lc++abi`. - SDK headers carry availability annotations consistent with the deployment - target — this kills the whole hack class. (Trade-off, accepted: iOS library - features track the SDK libc++, not Homebrew's; language features - unaffected.) -- Set `DEPLOYMENT_TARGET=17.0` explicitly (preset + install.sh). Re-validate - each folly define in `VCPKG_CMAKE_CONFIGURE_OPTIONS`; keep - `-D__APPLE_USE_RFC_2292` (usrsctp). -- Document/guard the Xcode requirement in `install-prerequisities.sh`. -- **Gate**: `./install.sh --ios` → XCFramework; `./iostest.sh` green; Android - sanity build (`--android`, NDK r28+). +## Phase 1.4 — iOS refresh (PR #25, in review) +- **Deployment target: 26.0** (product decision, 2026-07: iPhones keep + themselves up to date; supporting old iOS runtimes is unnecessary). Set in + the triplet and the CMake presets; verified in the artifact + (`minos 26.0`). Xcode 26+ requirement guarded in + `install-prerequisities.sh`. +- **SDK libc++ arrangement landed**: iOS builds compile with `-nostdinc++ + -isystem /usr/include/c++/v1` (SDK path via `xcrun`) — SDK + headers with the SDK runtime, availability-consistent with the deployment + target. The Homebrew-libc++ `-isystem`, the + `_LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION=0` define and `-lc++abi` + are gone. +- `toolchains/ios.toolchain.cmake` replaced with **pristine** leetal 4.5.0. + Discovery: the previously vendored copy had been locally modified — glue + at its top read `ENV{VCPKG_*_FLAGS}`, paired with env exports in the + triplet; replacing the file silently broke ALL triplet flag flow (vcpkg's + chainload replaces its own flag-applying toolchain). The glue now lives in + a documented wrapper, `toolchains/streamr-ios.toolchain.cmake`, which + consumes `VCPKG_C/CXX/LINKER_FLAGS` and includes the pristine upstream + file — works for both port builds (cache vars) and package builds + (two-stage chainload). +- **folly defines re-validated by experiment** (all five legacy globals + dropped, then failures re-added, now scoped to the folly port block with + documented reasons): `FOLLY_HAVE_MALLOC_USABLE_SIZE=0` (doesn't exist on + iOS; folly's link check false-positives against SDK stubs) and + `IS_AARCH64_ARCH=0` (the iOS toolchain reports `aarch64`, enabling folly's + ELF-only assembly memcpy that Mach-O rejects). `FOLLY_HAVE_CLOCK_GETTIME`, + `FOLLY_MOBILE`, `__APPLE__` stayed dropped. `-D__APPLE_USE_RFC_2292` kept + (usrsctp; iOS 26 SDK still gates IPV6_PKTINFO behind an RFC choice). +- Verified: full iOS dependency set + packages + XCFramework green; + artifact `platform=iOS, minos=26.0`; flags confirmed flowing in port logs + and the package compile database. +- `iostest.sh` gained signing/tooling fixes surfaced by the device run: + `IOS_DEVELOPMENT_TEAM` override (signs with a different team — e.g. a + Personal Team — via command-line build settings when organization + provisioning is unavailable; bundle IDs get a team-ID suffix because the + originals are App IDs registered to the organization team), and + `xcresulttool get object --legacy` (Xcode 16+ requires the flag for the + old JSON format — result processing previously failed after a green run). +- **Gate**: `./install.sh --ios` → XCFramework ✓; `./iostest.sh --device` + ✓ — **GoogleTest suite passed on an iPhone 12 mini running iOS 26.4.2** + (deployment-target-26 / SDK-libc++ build, Personal Team signing); + Android sanity via CI keyword. ## Phase 1.5 — Lint stack remainder - clangd/clang-format 22 already landed in Phase 1.2 (forced by libc++ 22). diff --git a/install-prerequisities.sh b/install-prerequisities.sh index 6c9d4575..aaea7b00 100644 --- a/install-prerequisities.sh +++ b/install-prerequisities.sh @@ -12,6 +12,13 @@ if [[ "$OSTYPE" == "darwin"* ]]; then PROFILE_FILE=./setenvs.sh xcode-select --install || true + + # iOS builds target deployment target 26.0 and need the iOS 26 SDK. + XCODE_MAJOR=$(xcodebuild -version 2>/dev/null | awk 'NR==1{print int($2)}') + if [ -n "$XCODE_MAJOR" ] && [ "$XCODE_MAJOR" -lt 26 ]; then + echo "WARNING: Xcode $XCODE_MAJOR found; Xcode 26 or newer is required for iOS builds." + fi + export HOMEBREW_PREFIX=$(brew --prefix) if [[ -n "$GITHUB_ENV" ]]; then echo "HOMEBREW_PREFIX=$(brew --prefix)" >> $GITHUB_ENV diff --git a/iostest.sh b/iostest.sh index 9161e6f6..8ede5340 100755 --- a/iostest.sh +++ b/iostest.sh @@ -3,6 +3,12 @@ # Usage: ./iostest.sh run the tests on this Mac (default) # ./iostest.sh --device run on a connected iOS device # ./iostest.sh --device "name" run on the named iOS device +# +# Signing: the project is set up for the organization team. To sign with a +# different team (e.g. your Personal Team while organization provisioning +# is unavailable), set IOS_DEVELOPMENT_TEAM to that team's ID: +# IOS_DEVELOPMENT_TEAM=ABCDE12345 ./iostest.sh --device +# Command-line build settings override the project, so nothing is modified. DESTINATION='platform=macOS' if [ "$1" = "--device" ]; then if [ -n "$2" ]; then @@ -12,12 +18,26 @@ if [ "$1" = "--device" ]; then fi fi +SIGNING_OVERRIDES=() +if [ -n "$IOS_DEVELOPMENT_TEAM" ]; then + # The project's bundle identifiers are App IDs registered to the + # organization team, so another team cannot register them — suffix them + # with the team ID to get identifiers the override team can claim. + # $(inherited) resolves per target, keeping app and test bundle unique. + SIGNING_OVERRIDES=( + "DEVELOPMENT_TEAM=$IOS_DEVELOPMENT_TEAM" + "CODE_SIGN_STYLE=Automatic" + "PRODUCT_BUNDLE_IDENTIFIER=\$(inherited).$IOS_DEVELOPMENT_TEAM" + "-allowProvisioningDeviceRegistration" + ) +fi + rm -rf build/ios brew install chargepoint/xcparse/xcparse # Run tests -xcodebuild test -project test/ios/iOSUnitTesting/iOSUnitTesting.xcodeproj -scheme iOSUnitTesting -destination "$DESTINATION" -configuration Debug -resultBundlePath build/ios/TestResults.xcresult -allowProvisioningUpdates +xcodebuild test -project test/ios/iOSUnitTesting/iOSUnitTesting.xcodeproj -scheme iOSUnitTesting -destination "$DESTINATION" -configuration Debug -resultBundlePath build/ios/TestResults.xcresult -allowProvisioningUpdates "${SIGNING_OVERRIDES[@]}" # Check if xcodebuild was successful if [ $? -ne 0 ]; then @@ -26,7 +46,8 @@ if [ $? -ne 0 ]; then fi # Process results -RESULT=$(xcrun xcresulttool get --format json --path build/ios/TestResults.xcresult) +# --legacy: Xcode 16+ requires it for the old object/JSON output format +RESULT=$(xcrun xcresulttool get object --legacy --format json --path build/ios/TestResults.xcresult) # Check if xcresulttool was successful if [ $? -ne 0 ]; then diff --git a/overlaytriplets/arm64-ios.cmake b/overlaytriplets/arm64-ios.cmake index 4ec6aa83..3ab121a4 100644 --- a/overlaytriplets/arm64-ios.cmake +++ b/overlaytriplets/arm64-ios.cmake @@ -1,5 +1,3 @@ - -#own stuff below set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) set(VCPKG_TARGET_ARCHITECTURE arm64) set(VCPKG_CRT_LINKAGE dynamic) @@ -20,11 +18,32 @@ set(CMAKE_CXX_COMPILER "${LLVM_PREFIX}/bin/clang++") set(ENV{CC} "${CMAKE_C_COMPILER}") set(ENV{CXX} "${CMAKE_CXX_COMPILER}") -set(VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_C_COMPILER=${LLVM_PREFIX}/bin/clang -DCMAKE_CXX_COMPILER=${LLVM_PREFIX}/bin/clang++ -DCMAKE_CXX_STANDARD=26 -DFOLLY_HAVE_CLOCK_GETTIME=1 -DFOLLY_MOBILE=0 -DIS_AARCH64_ARCH=0 -D__APPLE__=1 -DFOLLY_HAVE_MALLOC_USABLE_SIZE=0 -DPLATFORM=OS64) +# iOS deployment target. Product decision (2026-07): iPhones keep themselves +# up to date, so the SDK targets the current major. The availability +# annotations in the SDK's libc++ headers follow this value. +set(DEPLOYMENT_TARGET "26.0") + +# Use the iPhoneOS SDK's libc++ HEADERS together with the SDK's libc++ +# RUNTIME. Headers and runtime stay consistent and availability-checked +# against DEPLOYMENT_TARGET — this replaces the old arrangement (Homebrew +# LLVM's libc++ headers against the device runtime), which needed hacks +# like -D_LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION=0 and -lc++abi. +# -nostdinc++ removes the compiler's own libc++ header paths. +execute_process( + COMMAND xcrun --sdk iphoneos --show-sdk-path + OUTPUT_VARIABLE STREAMR_IOS_SDK_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND_ERROR_IS_FATAL ANY) -set(VCPKG_CXX_FLAGS "-isystem ${LLVM_PREFIX}/include/c++/v1 -DFOLLY_MOBILE=0 -D_LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION=0") -set(VCPKG_C_FLAGS "-isystem ${LLVM_PREFIX}/include/c++/v1 -DFOLLY_MOBILE=0 -D_LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION=0") -set(VCPKG_LINKER_FLAGS "-lc++abi") +set(VCPKG_CMAKE_CONFIGURE_OPTIONS + -DCMAKE_C_COMPILER=${LLVM_PREFIX}/bin/clang + -DCMAKE_CXX_COMPILER=${LLVM_PREFIX}/bin/clang++ + -DCMAKE_CXX_STANDARD=26 + -DPLATFORM=OS64 + -DDEPLOYMENT_TARGET=${DEPLOYMENT_TARGET}) + +set(VCPKG_CXX_FLAGS "-nostdinc++ -isystem ${STREAMR_IOS_SDK_PATH}/usr/include/c++/v1") +set(VCPKG_C_FLAGS "") if(${PORT} MATCHES "usrsctp") set(VCPKG_CXX_FLAGS "${VCPKG_CXX_FLAGS} -D__APPLE_USE_RFC_2292") @@ -36,7 +55,17 @@ if(${PORT} MATCHES "folly") # cross-compiling; preset their results (same approach as # arm64-android.cmake). The values mirror what the checks detect when # they actually run on an arm64 Apple host (arm64-osx build). + # malloc_usable_size does not exist on iOS (only malloc_size), but + # folly's link check false-positives against the SDK stubs — pin it off + # or small_vector.h fails to compile. + # IS_AARCH64_ARCH=0: the iOS toolchain reports CMAKE_SYSTEM_PROCESSOR + # "aarch64" (macOS host says "arm64"), which enables folly's + # Arm-Optimized-Routines assembly memcpy — ELF-only directives that the + # Mach-O assembler rejects. Pin off to use folly's portable memcpy, + # matching the macOS host build. set(VCPKG_CMAKE_CONFIGURE_OPTIONS ${VCPKG_CMAKE_CONFIGURE_OPTIONS} + -DFOLLY_HAVE_MALLOC_USABLE_SIZE=0 + -DIS_AARCH64_ARCH=0 -DHAVE_VSNPRINTF_ERRORS_EXITCODE=1 -DHAVE_VSNPRINTF_ERRORS_EXITCODE__TRYRUN_OUTPUT=a -DFOLLY_HAVE_WCHAR_SUPPORT_EXITCODE=0 @@ -49,8 +78,4 @@ if(${PORT} MATCHES "folly") -DFOLLY_HAVE_WEAK_SYMBOLS_EXITCODE__TRYRUN_OUTPUT=a) endif() -set(ENV{VCPKG_CXX_FLAGS} "${VCPKG_CXX_FLAGS}") -set(ENV{VCPKG_C_FLAGS} "${VCPKG_C_FLAGS}") - -#set(ENV{PLATFORM} "SIMULATORARM64") -set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/../toolchains/ios.toolchain.cmake") +set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/../toolchains/streamr-ios.toolchain.cmake") diff --git a/toolchains/ios.toolchain.cmake b/toolchains/ios.toolchain.cmake index 0c0ab10a..a235cd0d 100644 --- a/toolchains/ios.toolchain.cmake +++ b/toolchains/ios.toolchain.cmake @@ -155,13 +155,6 @@ cmake_minimum_required(VERSION 3.8.0) -set(CMAKE_C_FLAGS "$ENV{VCPKG_C_FLAGS}") -set(CMAKE_CXX_FLAGS "$ENV{VCPKG_CXX_FLAGS}") -set(CMAKE_C_LINK_FLAGS "$ENV{VCPKG_LINKER_FLAGS}") -set(CMAKE_CXX_LINK_FLAGS "$ENV{VCPKG_LINKER_FLAGS}") -set(CMAKE_OBJC_LINK_FLAGS "$ENV{VCPKG_LINKER_FLAGS}") -set(CMAKE_OBJCXX_LINK_FLAGS "$ENV{VCPKG_LINKER_FLAGS}") - # CMake invokes the toolchain file twice during the first build, but only once during subsequent rebuilds. # NOTE: To improve single-library build-times, provide the flag "OS_SINGLE_BUILD" as a build argument. if(DEFINED OS_SINGLE_BUILD AND DEFINED ENV{_IOS_TOOLCHAIN_HAS_RUN}) @@ -957,30 +950,6 @@ else() set(CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO "-DNDEBUG -O2 -g ${CMAKE_OBJCXX_FLAGS_RELWITHDEBINFO}") set(CMAKE_OBJCXX_FLAGS_RELEASE "-DNDEBUG -O3 ${CMAKE_OBJCXX_FLAGS_RELEASE}") endif() - - set(ADDITIONAL_LINKER_FLAGS "-F ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks -L ${CMAKE_OSX_SYSROOT_INT}/usr/lib -framework Foundation -lc++abi") - - #set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ADDITIONAL_LINKER_FLAGS}") - #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ADDITIONAL_LINKER_FLAGS}") - #set(CMAKE_OBJC_FLAGS "${CMAKE_OBJC_FLAGS} ${ADDITIONAL_LINKER_FLAGS}") - #set(CMAKE_OBJCXX_FLAGS "${CMAKE_OBJCXX_FLAGS} ${ADDITIONAL_LINKER_FLAGS}") - - set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} ${ADDITIONAL_LINKER_FLAGS}") - set(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} ${ADDITIONAL_LINKER_FLAGS}") - set(CMAKE_OBJC_LINK_FLAGS "${CMAKE_OBJC_LINK_FLAGS} ${ADDITIONAL_LINKER_FLAGS}") - set(CMAKE_OBJCXX_LINK_FLAGS "${CMAKE_OBJCXX_LINK_FLAGS} ${ADDITIONAL_LINKER_FLAGS}") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${ADDITIONAL_LINKER_FLAGS}") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${ADDITIONAL_LINKER_FLAGS}") - #set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${ADDITIONAL_LINKER_FLAGS}") - #set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} ${ADDITIONAL_LINKER_FLAGS}") - set(CMAKE_SHARED_LIBRARY_LINK_STATIC_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_STATIC_CXX_FLAGS} ${ADDITIONAL_LINKER_FLAGS}") - set(CMAKE_SHARED_LIBRARY_LINK_DYNAMIC_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_DYNAMIC_CXX_FLAGS} ${ADDITIONAL_LINKER_FLAGS}") - set(LINK_OPTIONS "${LINK_OPTIONS} ${ADDITIONAL_LINKER_FLAGS}") - set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES} ${CMAKE_OSX_SYSROOT_INT}/usr/lib") - set(CMAKE_CXX_IMPLICIT_FRAMEWORK_DIRECTORIES "${CMAKE_CXX_IMPLICIT_FRAMEWORK_DIRECTORIES} ${CMAKE_OSX_SYSROOT_INT}/System/Library/Frameworks") - add_link_options("SHELL:${ADDITIONAL_LINKER_FLAGS}") - message(STATUS "Trying to set linker flags: ${CMAKE_STATIC_LINKER_FLAGS}") - set(CMAKE_C_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}" CACHE INTERNAL "Flags used by the compiler for all C link types.") set(CMAKE_CXX_LINK_FLAGS "${C_TARGET_FLAGS} ${SDK_NAME_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}" CACHE INTERNAL diff --git a/toolchains/streamr-ios.toolchain.cmake b/toolchains/streamr-ios.toolchain.cmake new file mode 100644 index 00000000..ec3b20bb --- /dev/null +++ b/toolchains/streamr-ios.toolchain.cmake @@ -0,0 +1,24 @@ +# Wrapper around the vendored (unmodified) leetal/ios-cmake toolchain. +# +# A VCPKG_CHAINLOAD_TOOLCHAIN_FILE replaces vcpkg's own iOS toolchain — the +# component that would otherwise apply VCPKG_C_FLAGS / VCPKG_CXX_FLAGS / +# VCPKG_LINKER_FLAGS from the triplet. Consume them here instead, so triplet +# flags keep working for both vcpkg port builds (vcpkg passes the values as +# cache variables) and the SDK's own package builds (the triplet file is +# evaluated in the same configure and sets them as normal variables). +# +# ios.toolchain.cmake folds the pre-set CMAKE_*_FLAGS values into its own +# flag composition, and toolchain files are evaluated multiple times per +# configure, so these are plain overwrites (idempotent), not appends. +# +# Historical note: the previously vendored ios.toolchain.cmake carried this +# glue as in-file modifications reading ENV{VCPKG_*_FLAGS}; the wrapper +# replaces that so the upstream file can stay pristine and updatable. +set(CMAKE_C_FLAGS "${VCPKG_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${VCPKG_CXX_FLAGS}") +set(CMAKE_C_LINK_FLAGS "${VCPKG_LINKER_FLAGS}") +set(CMAKE_CXX_LINK_FLAGS "${VCPKG_LINKER_FLAGS}") +set(CMAKE_OBJC_LINK_FLAGS "${VCPKG_LINKER_FLAGS}") +set(CMAKE_OBJCXX_LINK_FLAGS "${VCPKG_LINKER_FLAGS}") + +include("${CMAKE_CURRENT_LIST_DIR}/ios.toolchain.cmake")