diff options
-rw-r--r-- | Modules/FindCUDAToolkit.cmake | 5 | ||||
-rw-r--r-- | Source/cmComputeLinkInformation.cxx | 12 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 14 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.h | 3 | ||||
-rw-r--r-- | Tests/RunCMake/CMakeLists.txt | 7 | ||||
-rw-r--r-- | Tests/RunCMake/RuntimePath/RunCMakeTest.cmake | 41 | ||||
-rw-r--r-- | Tests/RunCMake/RuntimePath/Stub-fail-result.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/RuntimePath/Stub-fail-stderr.txt | 1 | ||||
-rw-r--r-- | Tests/RunCMake/RuntimePath/Stub.c | 4 | ||||
-rw-r--r-- | Tests/RunCMake/RuntimePath/Stub.cmake | 25 | ||||
-rw-r--r-- | Tests/RunCMake/RuntimePath/StubExe.c | 5 | ||||
-rw-r--r-- | Tests/RunCMake/RuntimePath/StubUse.c | 5 |
12 files changed, 112 insertions, 11 deletions
diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index 469a7ad..ac72c17 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -1100,7 +1100,10 @@ if(CUDAToolkit_FOUND) if(CUDA_${lib_name}_LIBRARY MATCHES "/stubs/" AND NOT WIN32) # Use a SHARED library with IMPORTED_IMPLIB, but not IMPORTED_LOCATION, # to indicate that the stub is for linkers but not dynamic loaders. - # It will not contribute any RPATH entry. + # It will not contribute any RPATH entry. When encountered as + # a private transitive dependency of another shared library, + # it will be passed explicitly to linkers so they can find it + # even when the runtime library file does not exist on disk. set(CUDA_IMPORT_PROPERTY IMPORTED_IMPLIB) set(CUDA_IMPORT_TYPE SHARED) endif() diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index e7bef68..40eb902 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1331,7 +1331,17 @@ void cmComputeLinkInformation::AddSharedDepItem(LinkEntry const& entry) } // If in linking mode, just link to the shared library. - if (this->SharedDependencyMode == SharedDepModeLink) { + if (this->SharedDependencyMode == SharedDepModeLink || + // For an imported shared library without a known runtime artifact, + // such as a CUDA stub, a library file named with the real soname + // may not be available at all, so '-rpath-link' cannot help linkers + // find it to satisfy '--no-allow-shlib-undefined' recursively. + // Pass this dependency to the linker explicitly just in case. + // If the linker also uses '--as-needed' behavior, this will not + // add an unnecessary direct dependency. + (tgt && tgt->IsImported() && + !tgt->HasKnownRuntimeArtifactLocation(this->Config) && + this->Target->LinkerEnforcesNoAllowShLibUndefined(this->Config))) { this->AddItem(entry); return; } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 289bb24..11253db 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -5596,6 +5596,20 @@ std::string cmGeneratorTarget::GetLinkerTool(const std::string& lang, return linkerTool; } +bool cmGeneratorTarget::LinkerEnforcesNoAllowShLibUndefined( + std::string const& config) const +{ + // FIXME(#25486): Account for the LINKER_TYPE target property. + // Also factor out the hard-coded list below into a platform + // information table based on the linker id. + std::string ll = this->GetLinkerLanguage(config); + std::string linkerIdVar = cmStrCat("CMAKE_", ll, "_COMPILER_LINKER_ID"); + cmValue linkerId = this->Makefile->GetDefinition(linkerIdVar); + // The GNU bfd-based linker may enforce '--no-allow-shlib-undefined' + // recursively by default. The Solaris linker has similar behavior. + return linkerId && (*linkerId == "GNU" || *linkerId == "Solaris"); +} + std::string cmGeneratorTarget::GetPDBOutputName( const std::string& config) const { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index cfb08fa..fb56a0d 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -805,6 +805,9 @@ public: std::string GetLinkerTool(const std::string& lang, const std::string& config) const; + /** Is the linker known to enforce '--no-allow-shlib-undefined'? */ + bool LinkerEnforcesNoAllowShLibUndefined(std::string const& config) const; + /** Does this target have a GNU implib to convert to MS format? */ bool HasImplibGNUtoMS(std::string const& config) const; diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 324a4da..a4e4800 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -434,8 +434,11 @@ endif() add_RunCMake_test(ObjectLibrary) add_RunCMake_test(ParseImplicitIncludeInfo) add_RunCMake_test(ParseImplicitLinkInfo) -if(UNIX AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG AND CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF") - add_RunCMake_test(RuntimePath) +if(UNIX AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG) + add_RunCMake_test(RuntimePath + -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} + -DCMAKE_EXECUTABLE_FORMAT=${CMAKE_EXECUTABLE_FORMAT} + ) endif() add_RunCMake_test(ScriptMode) add_RunCMake_test(Swift -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME} diff --git a/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake b/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake index ad446e9..180a0fe 100644 --- a/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake +++ b/Tests/RunCMake/RuntimePath/RunCMakeTest.cmake @@ -21,12 +21,39 @@ if(RunCMake_GENERATOR_IS_MULTI_CONFIG) set(cfg_dir /Debug) endif() -run_RuntimePath(SymlinkImplicit) -run_cmake_command(SymlinkImplicitCheck - ${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/SymlinkImplicit-build -Dcfg_dir=${cfg_dir} -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake) +if(CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF") + run_RuntimePath(SymlinkImplicit) + run_cmake_command(SymlinkImplicitCheck + ${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/SymlinkImplicit-build -Dcfg_dir=${cfg_dir} -P ${RunCMake_SOURCE_DIR}/SymlinkImplicitCheck.cmake) -run_RuntimePath(Relative) + run_RuntimePath(Relative) -run_RuntimePath(Genex) -run_cmake_command(GenexCheck - ${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/Genex-build -P ${RunCMake_SOURCE_DIR}/GenexCheck.cmake) + run_RuntimePath(Genex) + run_cmake_command(GenexCheck + ${CMAKE_COMMAND} -Ddir=${RunCMake_BINARY_DIR}/Genex-build -P ${RunCMake_SOURCE_DIR}/GenexCheck.cmake) +endif() + +block() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Stub-build) + if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(bin_dir "${RunCMake_TEST_BINARY_DIR}/Debug") + set(lib_dir "${RunCMake_TEST_BINARY_DIR}/lib/Debug") + else() + set(bin_dir "${RunCMake_TEST_BINARY_DIR}") + set(lib_dir "${RunCMake_TEST_BINARY_DIR}/lib") + endif() + run_cmake(Stub) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(Stub-build ${CMAKE_COMMAND} --build . --config Debug) + if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|SunOS)$|BSD") + set(ldpath LD_LIBRARY_PATH) + elseif(CMAKE_SYSTEM_NAME MATCHES "^(Darwin)$") + set(ldpath DYLD_LIBRARY_PATH) + elseif(CMAKE_SYSTEM_NAME MATCHES "^(AIX)$") + set(ldpath LIBPATH) + endif() + if(ldpath) + run_cmake_command(Stub-fail ${CMAKE_COMMAND} -E env LANG=C ${bin_dir}/StubExe) + run_cmake_command(Stub-pass ${CMAKE_COMMAND} -E env --modify ${ldpath}=path_list_prepend:${lib_dir} ${bin_dir}/StubExe) + endif() +endblock() diff --git a/Tests/RunCMake/RuntimePath/Stub-fail-result.txt b/Tests/RunCMake/RuntimePath/Stub-fail-result.txt new file mode 100644 index 0000000..d197c91 --- /dev/null +++ b/Tests/RunCMake/RuntimePath/Stub-fail-result.txt @@ -0,0 +1 @@ +[^0] diff --git a/Tests/RunCMake/RuntimePath/Stub-fail-stderr.txt b/Tests/RunCMake/RuntimePath/Stub-fail-stderr.txt new file mode 100644 index 0000000..9c17414 --- /dev/null +++ b/Tests/RunCMake/RuntimePath/Stub-fail-stderr.txt @@ -0,0 +1 @@ +(error while loading shared libraries: libStub\.so\.1|Library not loaded: '?@rpath/libStub\.1\.dylib'?|(Cannot|Could not) load module libStub\.so|fatal: libStub\.so\.1: open failed|Shared object "libStub\.so\.1" not found) diff --git a/Tests/RunCMake/RuntimePath/Stub.c b/Tests/RunCMake/RuntimePath/Stub.c new file mode 100644 index 0000000..2ff333a --- /dev/null +++ b/Tests/RunCMake/RuntimePath/Stub.c @@ -0,0 +1,4 @@ +int Stub(void) +{ + return 0; +} diff --git a/Tests/RunCMake/RuntimePath/Stub.cmake b/Tests/RunCMake/RuntimePath/Stub.cmake new file mode 100644 index 0000000..18e99c1 --- /dev/null +++ b/Tests/RunCMake/RuntimePath/Stub.cmake @@ -0,0 +1,25 @@ +enable_language(C) + +add_library(Stub SHARED Stub.c) +set_target_properties(Stub PROPERTIES + SOVERSION 1 + LIBRARY_OUTPUT_DIRECTORY lib + ) + +set(StubDir ${CMAKE_CURRENT_BINARY_DIR}/lib/stubs) +set(Stub "${StubDir}/${CMAKE_SHARED_LIBRARY_PREFIX}Stub${CMAKE_SHARED_LIBRARY_SUFFIX}") +add_custom_target(StubCopy + COMMAND ${CMAKE_COMMAND} -E make_directory "${StubDir}" + COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_SONAME_FILE:Stub>" "${Stub}" + BYPRODUCTS ${Stub} + ) +add_dependencies(StubCopy Stub) +add_library(Imp::Stub SHARED IMPORTED) +set_property(TARGET Imp::Stub PROPERTY IMPORTED_IMPLIB "${Stub}") +add_dependencies(Imp::Stub StubCopy) + +add_library(StubUse SHARED StubUse.c) +target_link_libraries(StubUse PRIVATE Imp::Stub) + +add_executable(StubExe StubExe.c) +target_link_libraries(StubExe PRIVATE StubUse) diff --git a/Tests/RunCMake/RuntimePath/StubExe.c b/Tests/RunCMake/RuntimePath/StubExe.c new file mode 100644 index 0000000..14b3fe4 --- /dev/null +++ b/Tests/RunCMake/RuntimePath/StubExe.c @@ -0,0 +1,5 @@ +extern int StubUse(void); +int main(void) +{ + return StubUse(); +} diff --git a/Tests/RunCMake/RuntimePath/StubUse.c b/Tests/RunCMake/RuntimePath/StubUse.c new file mode 100644 index 0000000..ffdaf6d --- /dev/null +++ b/Tests/RunCMake/RuntimePath/StubUse.c @@ -0,0 +1,5 @@ +extern int Stub(void); +int StubUse(void) +{ + return Stub(); +} |