-
Notifications
You must be signed in to change notification settings - Fork 12.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reapply [compiler-rt] Check for and use -lunwind when linking with -nodefaultlibs #66584
Conversation
Previously this failed with the following error:
I tried fixing it by wrapping it all in an |
Ping @petrhosek |
I'm surprised that CMake is trying to use targets defined in the same build in |
compiler-rt/cmake/config-ix.cmake
Outdated
if (NOT TARGET unwind) | ||
# Don't check for a library named unwind, if there's a target with that name within | ||
# the same build. | ||
check_library_exists(unwind _Unwind_RaiseException "" COMPILER_RT_HAS_LIBUNWIND) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this use a different symbol? This symbol does not exist when SJLJ exceptions are enabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh - good point. I guess we could check for _Unwind_GetRegionStart
or _Unwind_GetLanguageSpecificData
- both of those exist without any extra name mangling for both ehabi, sjlj, seh and regular dwarf.
I tested replacing this with a check for Thus, if the |
Ping @petrhosek, what do you think about this? |
Thanks, I tried it locally as well to better understand the issue. With the following:
I get the same error:
However, with the following:
CMake fails to find
To me this really looks like a bug in CMake since the behavior is inconsistent. Specifically, I don't think CMake should consider the previously defined targets when performing checks regardless of their type. Perhaps we should file an issue against CMake and include a link in the comment? |
Hmm, maybe. But even if CMake would be fixed to make the former case behave like the latter, what happens in the end when we link the component that we're building, and linking it against
I guess we could - but given the above, I'm not quite sure what we'd do differently here even in the future if we can assume a baseline CMake with this issue fixed. If |
…odefaultlibs If libc++ is available and should be used as the ubsan C++ ABI library, the check for libc++ might fail if libc++ is a static library, as the -nodefaultlibs flag inhibits a potential compiler default -lunwind. Just like the -nodefaultlibs configuration tests for and manually adds a bunch of compiler default libraries, look for -lunwind too. This is a reland of llvm#65912.
11cd99a
to
f12cdda
Compare
I was thinking about always ignoring previously defined targets, regardless of the type, since I cannot think of a case where using a previously defined target in a check call would be desirable. |
To follow up on this; I'm not quite sure that this is a bug that reasonably can be resolved in CMake anyway (and taking it further; not a bug at all?). Let's look at a couple of progressive CMake snippets: cmake_minimum_required(VERSION 3.13.4)
project(Test LANGUAGES CXX)
include(CheckLibraryExists)
check_library_exists(unwind _Unwind_RaiseException "" COMPILER_RT_HAS_LIBUNWIND)
add_executable(main main.cpp)
if (COMPILER_RT_HAS_LIBUNWIND)
target_link_libraries(main PRIVATE unwind)
endif() This would be the primary use. Here we find an If we proceed further with the working case: cmake_minimum_required(VERSION 3.13.4)
project(Test LANGUAGES CXX)
add_library(unwind STATIC unwind.cpp)
include(CheckLibraryExists)
check_library_exists(unwind _Unwind_RaiseException "" COMPILER_RT_HAS_LIBUNWIND)
add_executable(main main.cpp)
if (COMPILER_RT_HAS_LIBUNWIND)
target_link_libraries(main PRIVATE unwind)
endif() This also works. But in this case, we don't link with Now the case that fails: cmake_minimum_required(VERSION 3.13.4)
project(Test LANGUAGES CXX)
add_library(unwind_static STATIC unwind.cpp)
add_custom_target(unwind DEPENDS unwind_static)
include(CheckLibraryExists)
check_library_exists(unwind _Unwind_RaiseException "" COMPILER_RT_HAS_LIBUNWIND)
add_executable(main main.cpp)
if (COMPILER_RT_HAS_LIBUNWIND)
target_link_libraries(main PRIVATE unwind)
endif() This fails, as discussed earlier, like this:
Now if we instead skip cmake_minimum_required(VERSION 3.13.4)
project(Test LANGUAGES CXX)
add_library(unwind_static STATIC unwind.cpp)
add_custom_target(unwind DEPENDS unwind_static)
include(CheckLibraryExists)
# Skipping check_library_exists which fails here
#check_library_exists(unwind _Unwind_RaiseException "" COMPILER_RT_HAS_LIBUNWIND)
add_executable(main main.cpp)
if (TRUE) # COMPILER_RT_HAS_LIBUNWIND
target_link_libraries(main PRIVATE unwind)
endif() Then we finally end up with a similar error:
So as long as In the case of compiler-rt right now, we only append it to cmake_minimum_required(VERSION 3.13.4)
project(Test LANGUAGES CXX)
add_library(unwind_static STATIC unwind.cpp)
add_custom_target(unwind DEPENDS unwind_static)
#add_library(unwind STATIC unwind.cpp)
include(CheckLibraryExists)
#check_library_exists(unwind _Unwind_RaiseException "" COMPILER_RT_HAS_LIBUNWIND)
list(APPEND CMAKE_REQUIRED_LIBRARIES unwind)
check_library_exists(c++ __cxa_throw "" COMPILER_RT_HAS_LIBCXX) Resulting in this:
Thus - there's really no well defined thing to do here. For the cases where Hence, I don't think this is a proper bug, and even if it would be fixed for I'll go ahead and land the patch in its current form (I changed the symbol to check to one that has the same name in SjLj builds as well) soon. |
when checking ie __i386__ symbol existence llvm compiles a binary with libunwind linked-in although it does not seem to be required in actual compiler rt artifacts caused by: llvm/llvm-project#66584
if (COMPILER_RT_HAS_LIBUNWIND) | ||
# If we're omitting default libraries, we might need to manually link in libunwind. | ||
# This can affect whether we detect a statically linked libc++ correctly. | ||
list(APPEND CMAKE_REQUIRED_LIBRARIES unwind) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that one of the implications of this change is that for example on x86_64
test for __i386__
symbol existence will fail if 32-bit
version of libunwind
is not installed:
test_target_arch(i386 __i386__ "-m32") |
Although
32-bit libunwind
does not seem to be required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, so you have an x86_64 libunwind, and enough 32 bit libraries, so that compilation with -m32
works, but as we detected the x86_64 libunwind we now also require linking libunwind in all other tests, which makes the test for -m32
fail suddenly.
That's unfortunate...
@petrhosek Do you have any good ideas about how to handle this? In principle, I think the whole handling of multiple archs (like compiler-rt does, when building both x86_64 and i386 in the same cmake invocation) to be kind of wrong - ideally each arch build should be a separate cmake configuration of all the runtimes, so that all the tests are done specifically for that arch. But untangling those bits of compiler-rt is outside of what I want to take on.
If libc++ is available and should be used as the ubsan C++ ABI library, the check for libc++ might fail if libc++ is a static library, as the -nodefaultlibs flag inhibits a potential compiler default -lunwind.
Just like the -nodefaultlibs configuration tests for and manually adds a bunch of compiler default libraries, look for -lunwind too.
This is a reland of #65912.