diff --git a/cmake/Modules/CheckLinkerFlag.cmake b/cmake/Modules/CheckLinkerFlag.cmake new file mode 100644 --- /dev/null +++ b/cmake/Modules/CheckLinkerFlag.cmake @@ -0,0 +1,17 @@ +include(CMakePushCheckState) +include(CheckCCompilerFlag) + +function(llvm_check_linker_flag flag dest) + # If testing a flag with check_c_compiler_flag, it gets added to the compile + # command only, but not to the linker command in that test. If the flag + # is vital for linking to succeed, the test would fail even if it would + # have succeeded if it was included on both commands. + # + # Therefore, try adding the flag to CMAKE_REQUIRED_FLAGS, which gets + # added to both compiling and linking commands in the tests. + + cmake_push_check_state() + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${flag}") + check_c_compiler_flag("" ${dest}) + cmake_pop_check_state() +endfunction() diff --git a/cmake/Modules/EnableLanguageNolink.cmake b/cmake/Modules/EnableLanguageNolink.cmake new file mode 100644 --- /dev/null +++ b/cmake/Modules/EnableLanguageNolink.cmake @@ -0,0 +1,11 @@ +macro(llvm_enable_language_nolink) + # Set CMAKE_TRY_COMPILE_TARGET_TYPE to STATIC_LIBRARY to disable linking + # in the compiler sanity checks. When bootstrapping the toolchain, + # the toolchain itself is still incomplete and sanity checks that include + # linking may fail. + set(__SAVED_TRY_COMPILE_TARGET_TYPE ${CMAKE_TRY_COMPILE_TARGET_TYPE}) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + enable_language(${ARGV}) + set(CMAKE_TRY_COMPILE_TARGET_TYPE ${__SAVED_TRY_COMPILE_TARGET_TYPE}) + unset(__SAVED_TRY_COMPILE_TARGET_TYPE) +endmacro() diff --git a/libunwind/CMakeLists.txt b/libunwind/CMakeLists.txt --- a/libunwind/CMakeLists.txt +++ b/libunwind/CMakeLists.txt @@ -23,7 +23,11 @@ "Specify path to libc++ source.") if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBUNWIND_STANDALONE_BUILD) - project(libunwind LANGUAGES C CXX ASM) + # We may have an incomplete toolchain - do language support tests without + # linking. + include(EnableLanguageNolink) + project(libunwind LANGUAGES NONE) + llvm_enable_language_nolink(C CXX ASM) set(PACKAGE_NAME libunwind) set(PACKAGE_VERSION 14.0.0git) @@ -179,6 +183,14 @@ # Get required flags. add_target_flags_if(LIBUNWIND_BUILD_32_BITS "-m32") +# Compiler tests may be failing if the compiler implicitly links in libunwind, +# which doesn't exist yet. This gets waived by --unwindlib=none +# later in config-ix below, but the tests for --target etc before that may +# be failing due to it. Only test compilation, not linking, for these +# tests here now. +set(CMAKE_TRY_COMPILE_TARGET_TYPE_ORIG ${CMAKE_TRY_COMPILE_TARGET_TYPE}) +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + if(LIBUNWIND_TARGET_TRIPLE) add_target_flags_if_supported("--target=${LIBUNWIND_TARGET_TRIPLE}") endif() @@ -188,6 +200,7 @@ if(LIBUNWIND_SYSROOT) add_target_flags_if_supported("--sysroot=${LIBUNWIND_SYSROOT}") endif() +set(CMAKE_TRY_COMPILE_TARGET_TYPE ${CMAKE_TRY_COMPILE_TARGET_TYPE_ORIG}) # Configure compiler. include(config-ix) diff --git a/libunwind/cmake/config-ix.cmake b/libunwind/cmake/config-ix.cmake --- a/libunwind/cmake/config-ix.cmake +++ b/libunwind/cmake/config-ix.cmake @@ -2,9 +2,18 @@ include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) include(CheckLibraryExists) +include(CheckLinkerFlag) include(CheckSymbolExists) include(CheckCSourceCompiles) +# The compiler driver may be implicitly trying to link against libunwind, which +# might not work if libunwind doesn't exist yet. Try to check if +# --unwindlib=none is supported, and use that if possible. +llvm_check_linker_flag("--unwindlib=none" LIBUNWIND_SUPPORTS_UNWINDLIB_NONE_FLAG) +if (LIBUNWIND_SUPPORTS_UNWINDLIB_NONE_FLAG) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} --unwindlib=none") +endif() + check_library_exists(c fopen "" LIBUNWIND_HAS_C_LIB) if (NOT LIBUNWIND_USE_COMPILER_RT) @@ -25,11 +34,11 @@ # required for the link to go through. We remove sanitizers from the # configuration checks to avoid spurious link errors. -check_c_compiler_flag(-nostdlib++ LIBUNWIND_SUPPORTS_NOSTDLIBXX_FLAG) +llvm_check_linker_flag(-nostdlib++ LIBUNWIND_SUPPORTS_NOSTDLIBXX_FLAG) if (LIBUNWIND_SUPPORTS_NOSTDLIBXX_FLAG) set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nostdlib++") else() - check_c_compiler_flag(-nodefaultlibs LIBUNWIND_SUPPORTS_NODEFAULTLIBS_FLAG) + llvm_check_linker_flag(-nodefaultlibs LIBUNWIND_SUPPORTS_NODEFAULTLIBS_FLAG) if (LIBUNWIND_SUPPORTS_NODEFAULTLIBS_FLAG) set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -nodefaultlibs") endif() diff --git a/libunwind/src/CMakeLists.txt b/libunwind/src/CMakeLists.txt --- a/libunwind/src/CMakeLists.txt +++ b/libunwind/src/CMakeLists.txt @@ -83,6 +83,7 @@ endif() # Setup flags. +add_link_flags_if(LIBUNWIND_SUPPORTS_UNWINDLIB_NONE_FLAG --unwindlib=none) if (LIBUNWIND_SUPPORTS_NOSTDLIBXX_FLAG) add_link_flags_if_supported(-nostdlib++) else()