CMake: Check for func attributes without -Werror.

This matches the modified m4/ax_gcc_func_attribute.m4.
Only constructor and ifunc attribute checks were implemented.

CMake-based build doesn't have the trouble of Autoconf confdefs.h
but writing warning-free tests would still some extra care.
If looking for attribute-related warnings works well enough then
this method should be nicer than the -Werror method in CMake too.
This commit is contained in:
Lasse Collin 2023-10-16 20:55:05 +03:00
parent 146664519f
commit 4a1ef58ae7
2 changed files with 59 additions and 30 deletions

View File

@ -53,6 +53,7 @@ include(CheckSymbolExists)
include(CheckStructHasMember)
include(CheckCSourceCompiles)
include(cmake/tuklib_integer.cmake)
include(cmake/tuklib_gnu_c_attributes.cmake)
include(cmake/tuklib_cpucores.cmake)
include(cmake/tuklib_physmem.cmake)
include(cmake/tuklib_progname.cmake)
@ -750,17 +751,7 @@ if(NOT TUKLIB_CPUCORES_FOUND OR NOT TUKLIB_PHYSMEM_FOUND)
endif()
# Check for __attribute__((__constructor__)) support.
# This needs -Werror because some compilers just warn
# about this being unsupported.
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS "-Werror")
check_c_source_compiles("
__attribute__((__constructor__))
static void my_constructor_func(void) { return; }
int main(void) { return 0; }
"
HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR)
cmake_pop_check_state()
tuklib_check_func_attribute_constructor(HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR)
tuklib_add_definition_if(liblzma HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR)
# The Win95 threading lacks a thread-safe one-time initialization function.
@ -782,25 +773,7 @@ option(ALLOW_ATTR_IFUNC "Allow use of __attribute__((__ifunc__())) if \
supported by the system" ON)
if(ALLOW_ATTR_IFUNC)
cmake_push_check_state()
set(CMAKE_REQUIRED_FLAGS "-Werror")
check_c_source_compiles("
static void func(void) { return; }
static void (*resolve_func(void)) (void) { return func; }
void func_ifunc(void)
__attribute__((__ifunc__(\"resolve_func\")));
int main(void) { return 0; }
/*
* 'clang -Wall' incorrectly warns that resolve_func is
* unused (-Wunused-function). Correct assembly output is
* still produced. This problem exists at least in Clang
* versions 4 to 17. The following silences the bogus warning:
*/
void make_clang_quiet(void);
void make_clang_quiet(void) { resolve_func()(); }
"
HAVE_FUNC_ATTRIBUTE_IFUNC)
cmake_pop_check_state()
tuklib_check_func_attribute_ifunc(HAVE_FUNC_ATTRIBUTE_IFUNC)
tuklib_add_definition_if(liblzma HAVE_FUNC_ATTRIBUTE_IFUNC)
endif()

View File

@ -0,0 +1,56 @@
#
# tuklib_gnu_c_attributes.cmake - Checks for GNU C attributes
#
# Author: Lasse Collin
#
# This file has been put into the public domain.
# You can do whatever you want with this file.
#
include("${CMAKE_CURRENT_LIST_DIR}/tuklib_common.cmake")
include(CheckCSourceCompiles)
# This is a helper function for the actual attribute tests.
function(tuklib_check_attribute CODE RESULT)
# GCC, Clang, ICC, Solaris Studio, and XLC don't exit with
# a non-zero exit status if an unknown attribute is provided.
# They only print a warning. Accept the attribute only if no
# attribute-related warnings were issued.
#
# - XLC doesn't use the lower-case string "warning".
# It might use "WARNING" on z/OS or "(W)" on AIX.
# So "warning" isn't checked.
#
# - A few XLC messages use "Attribute" instead of "attribute".
#
# - ICC doesn't use the word "ignored".
#
# The problem with this method is that the regex might become
# outdated with newer compiler versions. Using -Werror would be
# an alternative but it fails if warnings occur for reasons other
# than unsupported attribute.
#
# The first pattern is for GCC, Solaris Studio, and XLC.
# The second one is for ICC. Both patterns work with Clang.
# Matching the leading space or colon reduces chances of
# matching any unrelated messages.
check_c_source_compiles("${CODE} int main(void) { return 0; }" "${RESULT}"
FAIL_REGEX " [Aa]ttribute .* ignored"
": unknown attribute")
endfunction()
function(tuklib_check_func_attribute_constructor RESULT)
tuklib_check_attribute("
__attribute__((__constructor__))
void my_constructor_func(void) { return; }
" "${RESULT}")
endfunction()
function(tuklib_check_func_attribute_ifunc RESULT)
tuklib_check_attribute("
static void func(void) { return; }
static void (*resolve_func(void))(void) { return &func; }
void func_ifunc(void)
__attribute__((__ifunc__(\"resolve_func\")));
" "${RESULT}")
endfunction()