cmTarget: Add a way to represent imported shared library stubs

Shared library stubs can be used for linking, but not at runtime.
Their role is similar to import libraries on Windows, so represent
their location with the `IMPORTED_IMPLIB` target property.

Fixes: #24940
This commit is contained in:
Robert Maynard
2023-07-17 17:44:26 -04:00
committed by Brad King
parent 83574a4772
commit 7351d590ee
15 changed files with 101 additions and 21 deletions

View File

@@ -11,6 +11,12 @@ This property may be set:
* On macOS, to an import file (e.g. ``.tbd``) created for shared libraries (see
the :prop_tgt:`ENABLE_EXPORTS` target property). For frameworks this is the
location of the ``.tbd`` file symlink just inside the framework folder.
* .. versionadded:: 3.28
On non-DLL platforms, to the location of a shared library.
When set without also specifying an :prop_tgt:`IMPORTED_LOCATION`,
the library is considered to be a stub, and its location will not
be added as a runtime search path to dependents that link it.
The ``IMPORTED_IMPLIB`` target property may be overridden for a
given configuration ``<CONFIG>`` by the configuration-specific

View File

@@ -0,0 +1,7 @@
imported-implib-only
--------------------
* On imported shared libraries, the :prop_tgt:`IMPORTED_IMPLIB` target
property may now be used without :prop_tgt:`IMPORTED_LOCATION`.
This can be used to represent a stub library whose location should not
be added as a runtime search path to dependents that link it.

View File

@@ -2241,16 +2241,20 @@ void cmComputeLinkInformation::AddLibraryRuntimeInfo(
if (target->GetType() != cmStateEnums::SHARED_LIBRARY) {
return;
}
auto const* info = target->GetImportInfo(this->Config);
// Try to get the soname of the library. Only files with this name
// could possibly conflict.
std::string soName = target->GetSOName(this->Config);
const char* soname = soName.empty() ? nullptr : soName.c_str();
const char* soname =
(!info || info->SOName.empty()) ? nullptr : info->SOName.c_str();
// Include this library in the runtime path ordering.
this->OrderRuntimeSearchPath->AddRuntimeLibrary(fullPath, soname);
if (this->LinkWithRuntimePath) {
this->OrderLinkerSearchPath->AddRuntimeLibrary(fullPath, soname);
// If this shared library has a known runtime artifact (IMPORTED_LOCATION),
// include its location in the runtime path ordering.
if (!info || !info->Location.empty()) {
this->OrderRuntimeSearchPath->AddRuntimeLibrary(fullPath, soname);
if (this->LinkWithRuntimePath) {
this->OrderLinkerSearchPath->AddRuntimeLibrary(fullPath, soname);
}
}
}

View File

@@ -1076,6 +1076,7 @@ private:
std::string SharedDeps;
};
friend cmComputeLinkInformation;
using ImportInfoMapType = std::map<std::string, ImportInfo>;
mutable ImportInfoMapType ImportInfoMap;
void ComputeImportInfo(std::string const& desired_config,

View File

@@ -2779,6 +2779,8 @@ std::string cmTarget::ImportedGetFullPath(
case cmStateEnums::RuntimeBinaryArtifact:
if (loc) {
result = *loc;
} else if (imp) {
result = *imp;
} else {
std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix);
if (cmValue config_location = this->GetProperty(impProp)) {
@@ -2787,6 +2789,16 @@ std::string cmTarget::ImportedGetFullPath(
this->GetProperty("IMPORTED_LOCATION")) {
result = *location;
}
if (result.empty() &&
(this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->IsExecutableWithExports())) {
impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
if (cmValue config_implib = this->GetProperty(impProp)) {
result = *config_implib;
} else if (cmValue implib = this->GetProperty("IMPORTED_IMPLIB")) {
result = *implib;
}
}
}
break;
@@ -2812,7 +2824,10 @@ std::string cmTarget::ImportedGetFullPath(
std::string unset;
std::string configuration;
if (artifact == cmStateEnums::RuntimeBinaryArtifact) {
if (this->GetType() == cmStateEnums::SHARED_LIBRARY &&
artifact == cmStateEnums::RuntimeBinaryArtifact) {
unset = "IMPORTED_LOCATION or IMPORTED_IMPLIB";
} else if (artifact == cmStateEnums::RuntimeBinaryArtifact) {
unset = "IMPORTED_LOCATION";
} else if (artifact == cmStateEnums::ImportLibraryArtifact) {
unset = "IMPORTED_IMPLIB";
@@ -2985,11 +3000,10 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config, cmValue& loc,
}
// If we needed to find one of the mapped configurations but did not
// On a DLL platform there may be only IMPORTED_IMPLIB for a shared
// library or an executable with exports.
bool allowImp = (this->IsDLLPlatform() &&
(this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->IsExecutableWithExports())) ||
// There may be only IMPORTED_IMPLIB for a shared library or an executable
// with exports.
bool allowImp = (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->IsExecutableWithExports()) ||
(this->IsAIX() && this->IsExecutableWithExports()) ||
(this->GetMakefile()->PlatformSupportsAppleTextStubs() &&
this->IsSharedLibraryWithExports());

View File

@@ -13,6 +13,7 @@ add_cuda_test_macro(Cuda.MixedStandardLevels4 MixedStandardLevels4)
add_cuda_test_macro(Cuda.MixedStandardLevels5 MixedStandardLevels5)
add_cuda_test_macro(Cuda.NotEnabled CudaNotEnabled)
add_cuda_test_macro(Cuda.SeparableCompCXXOnly SeparableCompCXXOnly)
add_cuda_test_macro(Cuda.StubRPATH StubRPATH)
add_cuda_test_macro(Cuda.Toolkit Toolkit)
add_cuda_test_macro(Cuda.IncludePathNoToolkit IncludePathNoToolkit)
add_cuda_test_macro(Cuda.SharedRuntimePlusToolkit SharedRuntimePlusToolkit)

View File

@@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 3.18)
project(StubRPATH CXX)
#Verify that linking to a stub library doesn't cause an `-rpath` entry
# Needed for `CUDAToolkit_LIBRARY_SEARCH_DIRS`
find_package(CUDAToolkit REQUIRED)
find_library(CUDA_DRIVER_STUB_LIBRARY
NAMES cuda
HINTS ${CUDAToolkit_LIBRARY_SEARCH_DIRS}
ENV CUDA_PATH
PATH_SUFFIXES lib64/stubs lib/x64/stubs lib/stubs stubs
)
add_library(imported_stub IMPORTED SHARED)
set_target_properties(imported_stub PROPERTIES IMPORTED_IMPLIB "${CUDA_DRIVER_STUB_LIBRARY}")
set_target_properties(imported_stub PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CUDAToolkit_INCLUDE_DIRS}")
set(CMAKE_CXX_STANDARD 11)
add_executable(StubRPATH main.cxx)
target_link_libraries(StubRPATH PRIVATE imported_stub)

View File

@@ -0,0 +1,17 @@
#include <iostream>
#include <cuda.h>
int main(int argc, char** argv)
{
int nDevices = 0;
cuInit(0);
auto err = cuDeviceGetCount(&nDevices);
if (err != CUDA_SUCCESS) {
std::cerr << "Failed to retrieve the number of CUDA enabled devices "
<< err << std::endl;
return 1;
}
return 0;
}

View File

@@ -248,7 +248,7 @@ add_custom_target(check-part3 ALL
-Dconfig=$<CONFIGURATION>
-Dtest_imported_includes=$<TARGET_PROPERTY:imported4,INCLUDE_DIRECTORIES>
-Dtest_imported_fallback=$<STREQUAL:$<TARGET_FILE_NAME:importedFallback>,fallback_loc>
-Dtest_imported_fallback2=$<IF:$<OR:$<PLATFORM_ID:Windows,CYGWIN,MSYS>,$<AND:$<PLATFORM_ID:Darwin>,$<BOOL:${CMAKE_TAPI}>>>,$<STREQUAL:$<TARGET_LINKER_FILE_NAME:importedFallback2>,special_imp>,$<STREQUAL:$<TARGET_LINKER_FILE_NAME:importedFallback2>,fallback_loc>>
-Dtest_imported_fallback2=$<STREQUAL:$<TARGET_LINKER_FILE_NAME:importedFallback2>,special_imp>
-Dtest_imported_fallback3=$<IF:$<PLATFORM_ID:Windows,CYGWIN,MSYS>,$<STREQUAL:$<TARGET_LINKER_FILE_NAME:importedFallback3>,imp_loc>,$<STREQUAL:$<TARGET_LINKER_FILE_NAME:importedFallback3>,fallback_loc>>
-Dtest_imported_fallback4=$<IF:$<PLATFORM_ID:Windows,CYGWIN,MSYS>,$<STREQUAL:$<TARGET_LINKER_FILE_NAME:importedFallback4>,imp_loc>,$<STREQUAL:$<TARGET_LINKER_FILE_NAME:importedFallback4>,fallback_loc>>
-Dtest_imported_fallback5=$<STREQUAL:$<TARGET_LINKER_FILE_NAME:importedFallback5>,imp_loc>

View File

@@ -1,6 +1,3 @@
# Prevent duplicate errors on some platforms.
set(CMAKE_IMPORT_LIBRARY_SUFFIX "placeholder")
add_library(unknown_lib UNKNOWN IMPORTED)
add_library(static_lib STATIC IMPORTED)
add_library(shared_lib SHARED IMPORTED)

View File

@@ -1,4 +1,6 @@
^(CMake Error in CMakeLists.txt:
IMPORTED_(LOCATION|IMPLIB) not set for imported target "(unknown|static|shared)_lib"( configuration
IMPORTED_(LOCATION|IMPLIB) not set for imported target "(unknown|static)_lib"( configuration
"[^"]+")?.
+)+CMake Generate step failed. Build files cannot be regenerated correctly.$
)+
.*(IMPORTED_LOCATION or )?IMPORTED_IMPLIB not set for imported target.*"shared_lib".*
CMake Generate step failed. Build files cannot be regenerated correctly.$

View File

@@ -4,7 +4,7 @@
details. Use the cmake_policy command to set the policy and suppress this
warning.
IMPORTED_(LOCATION|IMPLIB) not set for imported target "(unknown|static|shared)_lib"( configuration
IMPORTED_(LOCATION|IMPLIB) not set for imported target "(unknown|static)_lib"( configuration
"[^"]+")?.
This warning is for project developers. Use -Wno-dev to suppress it.
+)+CMake Warning \(dev\) in CMakeLists.txt:
@@ -13,6 +13,7 @@ This warning is for project developers. Use -Wno-dev to suppress it.
details. Use the cmake_policy command to set the policy and suppress this
warning.
IMPORTED_(LOCATION|IMPLIB) not set for imported target "(unknown|static|shared)_lib"( configuration
IMPORTED_(LOCATION|IMPLIB) not set for imported target "(unknown|static)_lib"( configuration
"[^"]+")?.
.*(IMPORTED_LOCATION or )?IMPORTED_IMPLIB not set for imported target.*"shared_lib".*
This warning is for project developers. Use -Wno-dev to suppress it.$

View File

@@ -14,8 +14,14 @@ set_property(TARGET import-local PROPERTY IMPORTED_LOCATION "${binary_dir}/${CMA
set_property(TARGET import-local PROPERTY IMPORTED_IMPLIB "${binary_dir}/${CMAKE_STATIC_LIBRARY_PREFIX}func${CMAKE_IMPORT_LIBRARY_SUFFIX}")
add_library(alias::local ALIAS import-local)
if(NOT DEFINED CMAKE_IMPORT_LIBRARY_SUFFIX)
add_library(import-local-stub SHARED IMPORTED)
set_property(TARGET import-local-stub PROPERTY IMPORTED_IMPLIB "${binary_dir}/${CMAKE_STATIC_LIBRARY_PREFIX}func${CMAKE_SHARED_LIBRARY_SUFFIX}")
add_library(alias::local-stub ALIAS import-local-stub)
endif()
add_library (lib-local SHARED lib.c)
target_link_libraries (lib-local PRIVATE alias::local)
target_link_libraries (lib-local PRIVATE alias::local $<TARGET_NAME_IF_EXISTS:alias::local-stub>)
add_executable (main-local main.c)
target_link_libraries (main-local PRIVATE alias::local)

View File

@@ -0,0 +1,2 @@
add_library(SharedStubImportedGlobal SHARED IMPORTED GLOBAL)
set_target_properties(SharedStubImportedGlobal PROPERTIES IMPORTED_IMPLIB z)

View File

@@ -23,6 +23,7 @@ run_cmake(CMP0079-link-NEW-bogus)
run_cmake(CMP0108-OLD-self-link)
run_cmake(CMP0108-NEW-self-link)
run_cmake(ImportedTarget)
run_cmake(ImportedTargetStub)
run_cmake(ImportedTargetFailure)
run_cmake(MixedSignature)
run_cmake(Separate-PRIVATE-LINK_PRIVATE-uses)