diff --git a/libc/Android.bp b/libc/Android.bp index 8f07ef431..0ee353dd2 100644 --- a/libc/Android.bp +++ b/libc/Android.bp @@ -2084,6 +2084,8 @@ cc_object { local_include_dirs: ["include"], srcs: ["arch-common/bionic/crtbegin.c"], defaults: ["crt_defaults"], + // When using libc.a, we're using the latest library regardless of target API level. + min_sdk_version: "current", } cc_object { @@ -2094,6 +2096,8 @@ cc_object { "crtbrand", ], defaults: ["crt_defaults"], + // When using libc.a, we're using the latest library regardless of target API level. + min_sdk_version: "current", } cc_object { diff --git a/libc/include/android/legacy_signal_inlines.h b/libc/include/android/legacy_signal_inlines.h index 90eda7dc1..a6734464c 100644 --- a/libc/include/android/legacy_signal_inlines.h +++ b/libc/include/android/legacy_signal_inlines.h @@ -45,12 +45,16 @@ int __libc_current_sigrtmax() __attribute__((__weak__)) __VERSIONER_NO_GUARD; int __libc_current_sigrtmin() __attribute__((__weak__)) __VERSIONER_NO_GUARD; static __inline int __ndk_legacy___libc_current_sigrtmax() { - if (__libc_current_sigrtmax) return __libc_current_sigrtmax(); + if (__builtin_available(android 21, *)) { + return __libc_current_sigrtmax(); + } return __SIGRTMAX; /* Should match __libc_current_sigrtmax. */ } static __inline int __ndk_legacy___libc_current_sigrtmin() { - if (__libc_current_sigrtmin) return __libc_current_sigrtmin(); + if (__builtin_available(android 21, *)) { + return __libc_current_sigrtmin(); + } return __SIGRTMIN + 7; /* Should match __libc_current_sigrtmin. */ } diff --git a/libc/include/android/versioning.h b/libc/include/android/versioning.h index 3ea414a45..2b9a0272b 100644 --- a/libc/include/android/versioning.h +++ b/libc/include/android/versioning.h @@ -33,13 +33,62 @@ #else -#define __INTRODUCED_IN(api_level) -#define __DEPRECATED_IN(api_level) -#define __REMOVED_IN(api_level) -#define __INTRODUCED_IN_32(api_level) +// When headers are not processed by the versioner (i.e. compiled into object files), +// the availability attributed is emitted instead. The clang compiler will make the symbol weak +// when targeting old api_level and enforce the reference to the symbol to be guarded with +// __builtin_available(android api_level, *). + +// The 'strict' flag is required for NDK clients where the use of "-Wunguarded-availability" cannot +// be enforced. In the case, the absence of 'strict' makes it possible to call an unavailable API +// without the __builtin_available check, which will cause a link error at runtime. +// Android platform build system defines this macro along with -Wunguarded-availability +#if defined(__ANDROID_UNGUARDED_AVAILABILITY__) +#define __MAYBE_STRICT +#else +#define __MAYBE_STRICT ,strict +#endif + +#define __INTRODUCED_IN(api_level) \ + __attribute__((availability(android __MAYBE_STRICT,introduced=api_level))) +#define __DEPRECATED_IN(api_level) \ + __attribute__((availability(android __MAYBE_STRICT,deprecated=api_level))) +#define __REMOVED_IN(api_level) \ + __attribute__((availability(android __MAYBE_STRICT,obsoleted=api_level))) + +// The same availability attribute can't be annotated multiple times. Therefore, the macros are +// defined for the configuration that it is valid for so that declarations like the below doesn't +// cause inconsistent availability values which is an error with -Wavailability: +// +// void foo() __INTRODUCED_IN_32(30) __INTRODUCED_IN_64(31); +// +// This also takes the advantage of the fact that we never use bitness-specific macro with +// arch-specific macro. In other words, +// +// void foo() __INTRODUCED_IN_ARM(30) __INTRODUCED_IN_64(31); +// +// hasn't been supported and won't be. +#if !defined(__LP64__) +#define __INTRODUCED_IN_32(api_level) \ + __attribute__((availability(android __MAYBE_STRICT,introduced=api_level))) #define __INTRODUCED_IN_64(api_level) +#else +#define __INTRODUCED_IN_32(api_level) +#define __INTRODUCED_IN_64(api_level) \ + __attribute__((availability(android __MAYBE_STRICT,introduced=api_level))) +#endif + +#if defined(__arm__) || defined(__aarch64__) +#define __INTRODUCED_IN_ARM(api_level) \ + __attribute__((availability(android __MAYBE_STRICT,introduced=api_level))) +#define __INTRODUCED_IN_X86(api_level) +#elif defined(__i386__) || defined(__x86_64__) +#define __INTRODUCED_IN_ARM(api_level) +#define __INTRODUCED_IN_X86(api_level) \ + __attribute__((availability(android __MAYBE_STRICT,introduced=api_level))) +#else #define __INTRODUCED_IN_ARM(api_level) #define __INTRODUCED_IN_X86(api_level) +#endif #define __VERSIONER_NO_GUARD #define __VERSIONER_FORTIFY_INLINE