fix: include TargetConditionals.h in target.h for iOS cross-compilation#3111
fix: include TargetConditionals.h in target.h for iOS cross-compilation#3111
Conversation
aws-lc-sys 0.38.0 fails to compile urandom.c for aarch64-apple-ios on Xcode 16.2 because target.h doesn't include <TargetConditionals.h>, so OPENSSL_IOS is never defined and the build falls through to the Linux urandom path. Patches target.h in the cargo registry before building iOS targets. This directly proves the upstream root cause fix works: aws/aws-lc#3111 Made-with: Cursor
Replace the CFLAGS workaround (which masked symptoms by stubbing RNDGETENTCNT and suppressing warnings) with a build-time source patch that fixes the actual root cause: aws-lc's target.h missing an #include <TargetConditionals.h>. Upstream PR: aws/aws-lc#3111 Made-with: Cursor
Replace the CFLAGS workaround (which masked symptoms by stubbing RNDGETENTCNT and suppressing warnings) with a build-time source patch that fixes the actual root cause: aws-lc's target.h missing an #include <TargetConditionals.h>. Upstream PR: aws/aws-lc#3111 Made-with: Cursor
aws-lc-sys 0.38.0 fails to compile urandom.c for aarch64-apple-ios on Xcode 16.2 because target.h doesn't include <TargetConditionals.h>, so OPENSSL_IOS is never defined and the build falls through to the Linux urandom path. Patches target.h in the cargo registry before building iOS targets. This directly proves the upstream root cause fix works: aws/aws-lc#3111 Made-with: Cursor
aws-lc-sys 0.38.0 fails to compile urandom.c for aarch64-apple-ios on Xcode 16.2 because target.h doesn't include <TargetConditionals.h>, so OPENSSL_IOS is never defined and the build falls through to the Linux urandom path. Patches target.h in the cargo registry before building iOS targets. This directly proves the upstream root cause fix works: aws/aws-lc#3111 Made-with: Cursor
…NDGETENTCNT Two fixes for urandom.c failing to compile on aarch64-apple-ios with Xcode 16.2 / iPhoneOS 18.2 SDK: 1. target.h: include <TargetConditionals.h> so OPENSSL_IOS is defined (guarded by !__ASSEMBLER__ for .S file compatibility) 2. urandom.c: guard RNDGETENTCNT/ioctl usage behind OPENSSL_LINUX, matching the guards already on the #include directives for <linux/random.h> and <sys/ioctl.h> Made-with: Cursor
9b08d0a to
061fdbe
Compare
| #if defined(OPENSSL_LINUX) | ||
| // On Linux, where urandom doesn't block at startup, we ensure that the | ||
| // kernel has sufficient entropy before continuing. RNDGETENTCNT and ioctl | ||
| // are Linux-specific (from <linux/random.h> and <sys/ioctl.h>). |
There was a problem hiding this comment.
Hi @lukejmann -- Thanks for the PR, and the detailed write up! We also have an issue related to this in the aws-lc-rs repo: aws/aws-lc-rs#1068. I wrote up my initial analysis here.
The change here to "urandom.c" is concerning. This is guarding the loop with OPENSSL_LINUX while still leaving random_flavor_state = STATE_READY below unconditional. The problem is that if this code were ever compiled/used on a non-Linux platform, it would silently skip entropy initialization entirely.
We believe the correct fix is likely in crypto/rand_extra/internal.h: adding an OPENSSL_APPLE catch-all so Apple platforms never fall through to OPENSSL_RAND_URANDOM in the first place.
We're working on this now — thanks again for bringing it to our attention!
### Issues: Related: aws/aws-lc-rs#1068 Related: #3111 ### Context: When cross-compiling for iOS on certain toolchains, `TARGET_OS_IPHONE` from `TargetConditionals.h` can evaluate to 0 (e.g., due to compiler/SDK version mismatches). This causes `OPENSSL_IOS` to not be defined, and the entropy source selection in `crypto/rand_extra/internal.h` falls through to `OPENSSL_RAND_URANDOM`, which is inherently Linux-specific. The build then fails in `urandom.c` due to its use of `ioctl()` and `RNDGETENTCNT`. ### Description of changes: The fix widens the `CCRandomGenerateBytes` branch from `OPENSSL_IOS` to `OPENSSL_APPLE`. `OPENSSL_APPLE` is derived from `__APPLE__` (a compiler intrinsic) so it has no dependency on `TargetConditionals.h`. `CCRandomGenerateBytes` is available on all Apple platforms, so this is safe regardless of the specific Apple target. ### Call-outs: We considered instead redefining `OPENSSL_IOS` using a `TargetConditionals.h`-independent condition (e.g., `OPENSSL_APPLE && !OPENSSL_MACOS`), but `OPENSSL_MACOS` depends on the same `TargetConditionals.h` mechanism and fails in the same way. It would also incorrectly label non-iOS Apple platforms (tvOS, watchOS, etc.) as iOS. ### Testing: Added an iOS aarch64 cross-compilation job to the `aws-lc-rs.yml` workflow. This job installs Homebrew LLVM (which reproduces the `TargetConditionals.h` detection failure) and builds aws-lc-rs for `aarch64-apple-ios`. By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.
Issues:
None filed yet — discovered in the wild cross-compiling for iOS via
aws-lc-sys0.38.0.Description of changes:
target.hchecksTARGET_OS_IPHONEandTARGET_OS_OSXto defineOPENSSL_IOSandOPENSSL_MACOS, but never includes<TargetConditionals.h>itself. It relies onbase.hhaving done the include first. On toolchains whereTARGET_OS_*are not compiler builtins (observed with Xcode 16.2 / iPhoneOS 18.2 SDK, compiled through the cc-rs build system), the macros are absent whentarget.his processed.OPENSSL_IOSis never defined.That causes the entropy source selection in
crypto/rand_extra/internal.hto skipOPENSSL_RAND_CCRANDOMGENERATEBYTESand fall through toOPENSSL_RAND_URANDOM.urandom.cthen fails to compile becauseensure_dev_urandom_is_initialized()referencesioctl()andRNDGETENTCNT, whose headers (<linux/random.h>,<sys/ioctl.h>) are only included behind#if defined(OPENSSL_LINUX):Fix: include
<TargetConditionals.h>directly intarget.hso it is self-contained on Apple platforms. Guarded by!__ASSEMBLER__sincetarget.his also pulled into.Sfiles.Call-outs:
The
target.hheader is documented as safe for C, C++, and assembly. The!__ASSEMBLER__guard keeps<TargetConditionals.h>out of assembly contexts where system headers aren't available. In assembly, theTARGET_OS_*checks simply evaluate to false, which matches current behavior (assembly files don't inspectOPENSSL_IOS).Testing:
We verified this end-to-end. Our project (worldcoin/walletkit) cross-compiles
aws-lc-sys0.38.0 foraarch64-apple-ios,aarch64-apple-ios-sim, andx86_64-apple-iosin CI on a macOS 14 / Xcode 16.2 runner.Before (no fix): CI fails compiling
urandom.c— failing runAfter (this fix): We forked
aws-lc-rs, pointed theaws-lc-sys/aws-lcsubmodule at this branch (lukejmann/aws-lc@fix/ios-cross-compilation), then patched ourCargo.tomlto use the fork:CI passes with no workarounds — passing run
The fix and test wiring can be seen in this walletkit PR, which is structured as a single commit on top of the original failing commit: worldcoin/walletkit#314 (base
bump-aws-lc-broken= the commit that bumps to aws-lc-sys 0.38.0 and fails, headfix/aws-lc-ios= same + the[patch.crates-io]line).Existing CI for Linux / macOS / Windows targets should be unaffected since the change only adds an include that's already present in
base.hfor those paths.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.