Skip to content

Strict Memory Checking C interop Doesn't Work on Android #86237

@marcprux

Description

@marcprux

Description

Strict Memory Checking and the automatic Span conversion when interacting with C code does not work on Android. This works well on macOS and Linux but fails to build with a missing header on Android (as well as on Windows, as reported at #86087).

Reproduction

git clone https://github.com/vapor/authentication.git
cd authentication
swift build --swift-sdk aarch64-unknown-linux-android28

This fails with missing headers lifetimebound.h and ptrcheck.h:

Build errors
[490/498] Compiling Authentication BcryptHasher.swift
/opt/src/github/vapor/authentication/Sources/CVaporAuthBcrypt/include/../bcrypt.h:4:10: error: 'lifetimebound.h' file not found
 2 | #include <string.h>
 3 | #include <stdio.h>
 4 | #include <lifetimebound.h>
   |          `- error: 'lifetimebound.h' file not found
 5 | #include <ptrcheck.h>
 6 | 

/opt/src/github/vapor/authentication/Sources/Authentication/Passwords/Bcrypt/VaporBcrypt.swift:1:17: error: could not build C module 'CVaporAuthBcrypt'
  1 | internal import CVaporAuthBcrypt
    |                 `- error: could not build C module 'CVaporAuthBcrypt'
  2 | 
  3 | #if canImport(FoundationEssentials)
[491/498] Compiling Authentication Data+Array.swift
/opt/src/github/vapor/authentication/Sources/CVaporAuthBcrypt/include/../bcrypt.h:4:10: error: 'lifetimebound.h' file not found
 2 | #include <string.h>
 3 | #include <stdio.h>
 4 | #include <lifetimebound.h>
   |          `- error: 'lifetimebound.h' file not found
 5 | #include <ptrcheck.h>
 6 | 

/opt/src/github/vapor/authentication/Sources/Authentication/Passwords/Bcrypt/VaporBcrypt.swift:1:17: error: could not build C module 'CVaporAuthBcrypt'
  1 | internal import CVaporAuthBcrypt
    |                 `- error: could not build C module 'CVaporAuthBcrypt'
  2 | 
  3 | #if canImport(FoundationEssentials)
[492/498] Compiling Authentication PlaintextHasher.swift
/opt/src/github/vapor/authentication/Sources/CVaporAuthBcrypt/include/../bcrypt.h:4:10: error: 'lifetimebound.h' file not found
 2 | #include <string.h>
 3 | #include <stdio.h>
 4 | #include <lifetimebound.h>
   |          `- error: 'lifetimebound.h' file not found
 5 | #include <ptrcheck.h>
 6 | 

/opt/src/github/vapor/authentication/Sources/Authentication/Passwords/Bcrypt/VaporBcrypt.swift:1:17: error: could not build C module 'CVaporAuthBcrypt'
  1 | internal import CVaporAuthBcrypt
    |                 `- error: could not build C module 'CVaporAuthBcrypt'
  2 | 
  3 | #if canImport(FoundationEssentials)
[493/498] Compiling Authentication VaporBcrypt.swift
/opt/src/github/vapor/authentication/Sources/CVaporAuthBcrypt/include/../bcrypt.h:4:10: error: 'lifetimebound.h' file not found
 2 | #include <string.h>
 3 | #include <stdio.h>
 4 | #include <lifetimebound.h>
   |          `- error: 'lifetimebound.h' file not found
 5 | #include <ptrcheck.h>
 6 | 

/opt/src/github/vapor/authentication/Sources/Authentication/Passwords/Bcrypt/VaporBcrypt.swift:1:17: error: could not build C module 'CVaporAuthBcrypt'
  1 | internal import CVaporAuthBcrypt
    |                 `- error: could not build C module 'CVaporAuthBcrypt'
  2 | 
  3 | #if canImport(FoundationEssentials)
[494/498] Compiling Authentication PasswordHasher.swift
/opt/src/github/vapor/authentication/Sources/CVaporAuthBcrypt/include/../bcrypt.h:4:10: error: 'lifetimebound.h' file not found
 2 | #include <string.h>
 3 | #include <stdio.h>
 4 | #include <lifetimebound.h>
   |          `- error: 'lifetimebound.h' file not found
 5 | #include <ptrcheck.h>
 6 | 

/opt/src/github/vapor/authentication/Sources/Authentication/Passwords/Bcrypt/VaporBcrypt.swift:1:17: error: could not build C module 'CVaporAuthBcrypt'
  1 | internal import CVaporAuthBcrypt
    |                 `- error: could not build C module 'CVaporAuthBcrypt'
  2 | 
  3 | #if canImport(FoundationEssentials)
error: emit-module command failed with exit code 1 (use -v to see invocation)
[495/498] Emitting module Authentication
/opt/src/github/vapor/authentication/Sources/CVaporAuthBcrypt/include/../bcrypt.h:4:10: error: 'lifetimebound.h' file not found
 2 | #include <string.h>
 3 | #include <stdio.h>
 4 | #include <lifetimebound.h>
   |          `- error: 'lifetimebound.h' file not found
 5 | #include <ptrcheck.h>
 6 | 

/opt/src/github/vapor/authentication/Sources/Authentication/Passwords/Bcrypt/VaporBcrypt.swift:1:17: error: could not build C module 'CVaporAuthBcrypt'
  1 | internal import CVaporAuthBcrypt
    |                 `- error: could not build C module 'CVaporAuthBcrypt'
  2 | 
  3 | #if canImport(FoundationEssentials)
[496/498] Compiling Authentication BcryptError.swift
/opt/src/github/vapor/authentication/Sources/CVaporAuthBcrypt/include/../bcrypt.h:4:10: error: 'lifetimebound.h' file not found
 2 | #include <string.h>
 3 | #include <stdio.h>
 4 | #include <lifetimebound.h>
   |          `- error: 'lifetimebound.h' file not found
 5 | #include <ptrcheck.h>
 6 | 

/opt/src/github/vapor/authentication/Sources/Authentication/Passwords/Bcrypt/VaporBcrypt.swift:1:17: error: could not build C module 'CVaporAuthBcrypt'
  1 | internal import CVaporAuthBcrypt
    |                 `- error: could not build C module 'CVaporAuthBcrypt'
  2 | 
  3 | #if canImport(FoundationEssentials)
[497/498] Compiling Authentication Collection+SecureCompare.swift
/opt/src/github/vapor/authentication/Sources/CVaporAuthBcrypt/include/../bcrypt.h:4:10: error: 'lifetimebound.h' file not found
 2 | #include <string.h>
 3 | #include <stdio.h>
 4 | #include <lifetimebound.h>
   |          `- error: 'lifetimebound.h' file not found
 5 | #include <ptrcheck.h>
 6 | 

/opt/src/github/vapor/authentication/Sources/Authentication/Passwords/Bcrypt/VaporBcrypt.swift:1:17: error: could not build C module 'CVaporAuthBcrypt'
  1 | internal import CVaporAuthBcrypt
    |                 `- error: could not build C module 'CVaporAuthBcrypt'
  2 | 
  3 | #if canImport(FoundationEssentials)
[498/498] Compiling Authentication OTP.swift
/opt/src/github/vapor/authentication/Sources/CVaporAuthBcrypt/include/../bcrypt.h:4:10: error: 'lifetimebound.h' file not found
 2 | #include <string.h>
 3 | #include <stdio.h>
 4 | #include <lifetimebound.h>
   |          `- error: 'lifetimebound.h' file not found
 5 | #include <ptrcheck.h>
 6 | 

/opt/src/github/vapor/authentication/Sources/Authentication/Passwords/Bcrypt/VaporBcrypt.swift:1:17: error: could not build C module 'CVaporAuthBcrypt'
  1 | internal import CVaporAuthBcrypt
    |                 `- error: could not build C module 'CVaporAuthBcrypt'
  2 | 
  3 | #if canImport(FoundationEssentials)
Error: Error terminated(code: 1) running command: /Users/marc/Library/Developer/Toolchains/swift-6.3-DEVELOPMENT-SNAPSHOT-2025-12-24-a.xctoolchain/usr/bin/swift build --swift-sdk aarch64-unknown-linux-android28 -Xswiftc -DSKIP_BRIDGE -Xswiftc -DTARGET_OS_ANDROID

Expected behavior

The package should build.

Environment

marc@zap authentication % swift --version
Apple Swift version 6.3-dev (LLVM 8322c7222063676, Swift d1735f66f43c37f)
Target: arm64-apple-macosx15.0
Build config: +assertions

marc@zap authentication % skip android build --version
Swift Package Manager - Swift 6.3.0-dev

marc@zap authentication % sw_vers 
ProductName:		macOS
ProductVersion:		15.7.2
BuildVersion:		24G325

marc@zap authentication % swift sdk list
swift-6.3-DEVELOPMENT-SNAPSHOT-2025-12-24-a_android

Additional information

The Swift SDK for Android uses the NDK clang includes, which do not seem to contain lifetimebound.h and ptrcheck.h for some reason.

The diff of the headers in the host toolchain and the NDK toolchain can be seen:

$ ls -1 ~/Library/Developer/Toolchains/swift-6.3-DEVELOPMENT-SNAPSHOT-2025-12-24-a.xctoolchain/usr/lib/clang/21/include/ > /tmp/clang-host.txt

$ ls -1 ~/Library/org.swift.swiftpm/swift-sdks/swift-6.3-DEVELOPMENT-SNAPSHOT-2025-12-24-a_android.artifactbundle/swift-android/android-ndk-r29/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/21/include/ > /tmp/clang-ndk.txt

$ diff /tmp/clang-*.txt

16,19d15
< __clang_spirv_builtins.h
< __float_float.h
< __float_header_macro.h
< __float_infinity_nan.h
57d52
< andes_vector.h
71d65
< availability_domain.h
117a112
> bits
120d114
< bounds_safety_soft_traps.h
135d128
< feature-availability.h
160d152
< lifetimebound.h
178a171,172
> omp-tools.h
> omp.h
192d185
< ptrcheck.h
219d211
< stdcountof.h

Interestingly, just manually copying the header files over with:

$ cp ~/Library/Developer/Toolchains/swift-6.3-DEVELOPMENT-SNAPSHOT-2025-12-24-a.xctoolchain/usr/lib/clang/21/include/{ptrcheck.h,lifetimebound.h} ~/Library/org.swift.swiftpm/swift-sdks/swift-6.3-DEVELOPMENT-SNAPSHOT-2025-12-24-a_android.artifactbundle/swift-android/android-ndk-r29/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/21/include/

does enable the package to be built and all the tests pass.

Metadata

Metadata

Assignees

No one assigned

    Labels

    AndroidPlatform: AndroidbugA deviation from expected or documented behavior. Also: expected but undesirable behavior.c interopFeature: Interoperability with Cmemory safetyFeature: memory safety

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions