diff --git a/ci/docker/aarch64-linux-android/Dockerfile b/ci/docker/aarch64-linux-android/Dockerfile index 91c074150f94..420e594108c5 100644 --- a/ci/docker/aarch64-linux-android/Dockerfile +++ b/ci/docker/aarch64-linux-android/Dockerfile @@ -27,9 +27,9 @@ RUN chmod 777 -R /tmp/.android RUN chmod 755 /android/sdk/cmdline-tools/tools/* /android/sdk/emulator/qemu/linux-x86_64/* ENV PATH=$PATH:/rust/bin \ - CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=aarch64-linux-android28-clang \ + CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=aarch64-linux-android24-clang \ CARGO_TARGET_AARCH64_LINUX_ANDROID_RUNNER=/tmp/runtest \ - CC_aarch64_linux_android=aarch64-linux-android28-clang \ + CC_aarch64_linux_android=aarch64-linux-android24-clang \ AR_aarch64_linux_android=llvm-ar \ HOME=/tmp diff --git a/ci/docker/arm-linux-androideabi/Dockerfile b/ci/docker/arm-linux-androideabi/Dockerfile index 657ff81097c7..90124e093fcf 100644 --- a/ci/docker/arm-linux-androideabi/Dockerfile +++ b/ci/docker/arm-linux-androideabi/Dockerfile @@ -27,9 +27,9 @@ RUN chmod 777 -R /tmp/.android RUN chmod 755 /android/sdk/cmdline-tools/tools/* /android/sdk/emulator/qemu/linux-x86_64/* ENV PATH=$PATH:/rust/bin \ - CARGO_TARGET_ARM_LINUX_ANDROIDEABI_LINKER=armv7a-linux-androideabi28-clang \ + CARGO_TARGET_ARM_LINUX_ANDROIDEABI_LINKER=armv7a-linux-androideabi24-clang \ CARGO_TARGET_ARM_LINUX_ANDROIDEABI_RUNNER=/tmp/runtest \ - CC_arm_linux_androideabi=armv7a-linux-androideabi28-clang \ + CC_arm_linux_androideabi=armv7a-linux-androideabi24-clang \ AR_arm_linux_androideabi=llvm-ar \ HOME=/tmp diff --git a/ci/docker/x86_64-linux-android/Dockerfile b/ci/docker/x86_64-linux-android/Dockerfile index bc9580e6e1c0..80827d0bdb00 100644 --- a/ci/docker/x86_64-linux-android/Dockerfile +++ b/ci/docker/x86_64-linux-android/Dockerfile @@ -19,8 +19,8 @@ COPY android-sysimage.sh /android/ RUN /android/android-sysimage.sh x86_64 x86_64-24_r07.zip ENV PATH=$PATH:/rust/bin:/android/linux-x86_64/bin \ - CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER=x86_64-linux-android28-clang \ - CC_x86_64_linux_android=x86_64-linux-android28-clang \ - CXX_x86_64_linux_android=x86_64-linux-android28-clang++ \ + CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER=x86_64-linux-android24-clang \ + CC_x86_64_linux_android=x86_64-linux-android24-clang \ + CXX_x86_64_linux_android=x86_64-linux-android24-clang++ \ AR_x86_64_linux_android=llvm-ar \ HOME=/tmp diff --git a/libc-test/build.rs b/libc-test/build.rs old mode 100644 new mode 100755 index 2cf2eba99dda..e1cdd9dde76f --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -2045,6 +2045,10 @@ fn test_android(target: &str) { }; let x86 = target.contains("i686") || target.contains("x86_64"); let aarch64 = target.contains("aarch64"); + // The API level the NDK toolchain targets, which caps the available libc + // API surface (see `Versions`). Items introduced later must be skipped when + // building below their level and also when no level could be detected. + let skip_below_api = |level: u32| VERSIONS.android.map_or(true, |api| api < level); let mut cfg = ctest_cfg(); cfg.define("_GNU_SOURCE", None); @@ -2237,7 +2241,7 @@ fn test_android(target: &str) { "posix_spawnattr_t" => true, // Added in API level 24 - "if_nameindex" => true, + "if_nameindex" => skip_below_api(24), _ => false, } @@ -2429,40 +2433,32 @@ fn test_android(target: &str) { "reallocarray" => true, "__system_property_wait" => true, - // Added in API level 30, but tests use level 28. - "memfd_create" | "mlock2" | "renameat2" | "statx" | "statx_timestamp" => true, + // Added in API level 30. + "memfd_create" | "mlock2" | "renameat2" | "statx" | "statx_timestamp" => { + skip_below_api(30) + } // Added in glibc 2.25. "getentropy" => true, - // Added in API level 28, but some tests use level 24. - "getrandom" => true, - - // Added in API level 28, but some tests use level 24. - "syncfs" => true, - - // Added in API level 28, but some tests use level 24. - "pthread_attr_getinheritsched" | "pthread_attr_setinheritsched" => true, - // Added in API level 28, but some tests use level 24. - "fread_unlocked" | "fwrite_unlocked" | "fgets_unlocked" | "fflush_unlocked" => true, - - // Added in API level 28, but some tests use level 24. - "aligned_alloc" => true, + // Added in API level 28. + "getrandom" | "syncfs" | "aligned_alloc" => skip_below_api(28), - // Added in API level 26, but some tests use level 24. - "getgrent" => true, + // Added in API level 28. + "pthread_attr_getinheritsched" | "pthread_attr_setinheritsched" => skip_below_api(28), - // Added in API level 26, but some tests use level 24. - "setgrent" => true, - - // Added in API level 26, but some tests use level 24. - "endgrent" => true, + // Added in API level 28. + "fread_unlocked" | "fwrite_unlocked" | "fgets_unlocked" | "fflush_unlocked" => { + skip_below_api(28) + } - // Added in API level 26, but some tests use level 24. - "getpwent" | "setpwent" | "endpwent" => true, + // Added in API level 26. + "getgrent" | "setgrent" | "endgrent" | "getpwent" | "setpwent" | "endpwent" => { + skip_below_api(26) + } - // Added in API level 26, but some tests use level 24. - "getdomainname" | "setdomainname" => true, + // Added in API level 26. + "getdomainname" | "setdomainname" => skip_below_api(26), // FIXME(android): bad function pointers: "isalnum" | "isalpha" | "iscntrl" | "isdigit" | "isgraph" | "islower" | "isprint" @@ -2480,6 +2476,17 @@ fn test_android(target: &str) { } }); + cfg.skip_fn_ptrcheck(move |func| { + match func { + // termios functions are inlines below API 28, so + // their C-side address never matches the symbol Rust links. + "tcdrain" | "tcflow" | "tcflush" | "tcgetattr" | "tcgetsid" | "tcsendbreak" + | "tcsetattr" | "cfgetispeed" | "cfgetospeed" | "cfmakeraw" | "cfsetispeed" + | "cfsetospeed" | "cfsetspeed" => skip_below_api(28), + _ => false, + } + }); + cfg.skip_struct_field_type(move |struct_, field| { match (struct_.ident(), field.ident()) { // This is a weird union, don't check the type. @@ -6376,6 +6383,10 @@ struct Versions { netbsd: Option<(u32, u32)>, macos: Option<(u32, u32)>, emscripten: Option<(u32, u32)>, + /// Android API level. Unlike the (major, minor) platform versions + /// above, Android versions its libc ABI with a single increasing + /// integer (e.g. 28). There is no minor component. + android: Option, } impl Versions { @@ -6394,6 +6405,13 @@ impl Versions { #include "gnu/libc-version.h" #endif + #ifdef __ANDROID__ + /* The clang driver predefines __ANDROID_API__ and __ANDROID_MIN_SDK_VERSION__ + * from the API level in the target triple. When that is missing, this header + * supplies the __ANDROID_API_FUTURE__ fallback definition. */ + #include "android/api-level.h" + #endif + #if defined(__FreeBSD__) \ || defined(__NetBSD__) \ || defined(__OpenBSD__) \ @@ -6458,6 +6476,15 @@ impl Versions { } "__GLIBC__" => ret.glibc.get_or_insert_default().0 = value.parse().unwrap(), "__GLIBC_MINOR__" => ret.glibc.get_or_insert_default().1 = value.parse().unwrap(), + // The API level is in __ANDROID_API__ (old clang) or __ANDROID_MIN_SDK_VERSION__ + // (modern clang), so take a number from either. When the API is undetected (e.g. + // the triple carries no API level), its consumers fall back to skipping every + // API-gated test as if the toolchain targeted the oldest level possible. + "__ANDROID_API__" | "__ANDROID_MIN_SDK_VERSION__" => { + if let Ok(level) = value.parse() { + ret.android = Some(level); + } + } "__MAC_OS_X_VERSION_MAX_ALLOWED" => { let caps = mac_re.captures(value).unwrap(); let major: u32 = caps[1].parse().unwrap();