Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
},
{
Expand Down
65 changes: 45 additions & 20 deletions MODERNIZATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
<iphoneos-sdk>/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 <iphoneos-sdk>/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).
Expand Down
7 changes: 7 additions & 0 deletions install-prerequisities.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 23 additions & 2 deletions iostest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
47 changes: 36 additions & 11 deletions overlaytriplets/arm64-ios.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@

#own stuff below
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(VCPKG_TARGET_ARCHITECTURE arm64)
set(VCPKG_CRT_LINKAGE dynamic)
Expand All @@ -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")
Expand All @@ -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
Expand All @@ -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")
31 changes: 0 additions & 31 deletions toolchains/ios.toolchain.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Expand Down Expand Up @@ -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
Expand Down
24 changes: 24 additions & 0 deletions toolchains/streamr-ios.toolchain.cmake
Original file line number Diff line number Diff line change
@@ -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")
Loading