diff options
author | Jia Tan <jiat0218@gmail.com> | 2023-11-22 20:33:36 +0800 |
---|---|---|
committer | Jia Tan <jiat0218@gmail.com> | 2023-11-30 20:07:34 +0800 |
commit | d4af167570f2c14b002ee18a39d5b1e7e5a892b1 (patch) | |
tree | f951c3fc098f242cf16acb75440f4f00eabdfc0f /CMakeLists.txt | |
parent | Docs: Update INSTALL for --enable_ifunc change. (diff) | |
download | xz-d4af167570f2c14b002ee18a39d5b1e7e5a892b1.tar.xz |
CMake: Change __attribute__((__ifunc__())) detection.
This renames ALLOW_ATTR_IFUNC to USE_ATTR_IFUNC and applies the ifunc
detection changes that were made to the Autotools build.
Fixes: https://github.com/tukaani-project/xz/issues/70
Diffstat (limited to 'CMakeLists.txt')
-rw-r--r-- | CMakeLists.txt | 53 |
1 files changed, 45 insertions, 8 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 61ff9d94..b1753c37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -796,13 +796,46 @@ endif() # Check for __attribute__((__ifunc__())) support. -option(ALLOW_ATTR_IFUNC "Allow use of __attribute__((__ifunc__())) if \ -supported by the system" ON) +# Supported values for USE_ATTR_IFUNC: +# +# auto (default) - Detect ifunc support with a compile test. +# ON - Always enable ifunc. +# OFF - Disable ifunc usage. +set(USE_ATTR_IFUNC "auto" CACHE STRING "Use __attribute__((__ifunc__())).") + +set(SUPPORTED_USE_ATTR_IFUNC auto ON OFF) + +if(NOT USE_ATTR_IFUNC IN_LIST SUPPORTED_USE_ATTR_IFUNC) + message(FATAL_ERROR "'${USE_ATTR_IFUNC}' is not a supported value for" + "USE_ATTR_IFUNC") +endif() -if(ALLOW_ATTR_IFUNC) +# When USE_ATTR_IFUNC is 'auto', allow the use of __attribute__((__ifunc__())) +# if compiler support is detected and we are building for GNU/Linux (glibc) +# or FreeBSD. uClibc and musl don't support ifunc in their dynamic linkers +# but some compilers still accept the attribute when compiling for these +# C libraries, which results in broken binaries. That's why we need to +# check which libc is being used. +if(USE_ATTR_IFUNC STREQUAL "auto") cmake_push_check_state() set(CMAKE_REQUIRED_FLAGS "-Werror") + check_c_source_compiles(" + /* + * Force a compilation error when not using glibc on Linux + * or if we are not using FreeBSD. uClibc will define + * __GLIBC__ but does not support ifunc, so we must have + * an extra check to disable with uClibc. + */ + #if defined(__linux__) + # include <features.h> + # if !defined(__GLIBC__) || defined(__UCLIBC__) + compile error + # endif + #elif !defined(__FreeBSD__) + compile error + #endif + static void func(void) { return; } static void (*resolve_func(void)) (void) { return func; } void func_ifunc(void) @@ -817,15 +850,19 @@ if(ALLOW_ATTR_IFUNC) void make_clang_quiet(void); void make_clang_quiet(void) { resolve_func()(); } " - HAVE_FUNC_ATTRIBUTE_IFUNC) - cmake_pop_check_state() - tuklib_add_definition_if(liblzma HAVE_FUNC_ATTRIBUTE_IFUNC) + SYSTEM_SUPPORTS_IFUNC) + + cmake_pop_check_state() +endif() + +if(USE_ATTR_IFUNC STREQUAL "ON" OR SYSTEM_SUPPORTS_IFUNC) + tuklib_add_definitions(liblzma HAVE_FUNC_ATTRIBUTE_IFUNC) - if(HAVE_FUNC_ATTRIBUTE_IFUNC AND CMAKE_C_FLAGS MATCHES "-fsanitize=") + if(CMAKE_C_FLAGS MATCHES "-fsanitize=") message(SEND_ERROR "CMAKE_C_FLAGS or the environment variable CFLAGS " "contains '-fsanitize=' which is incompatible " - "with ifunc. Use -DALLOW_ATTR_IFUNC=OFF " + "with ifunc. Use -DUSE_ATTR_IFUNC=OFF " "as an argument to 'cmake' when using '-fsanitize'.") endif() endif() |