ENH: Allow IMPORTED_IMPLIB w/o IMPORTED_LOCATION
Linking to a Windows shared library (.dll) requires only its import library (.lib). This teaches CMake to recognize SHARED IMPORTED library targets that set only IMPORTED_IMPLIB and not IMPORTED_LOCATION.
This commit is contained in:
parent
5886d10334
commit
d05e98f8d7
@ -2527,23 +2527,17 @@ std::string cmTarget::NormalGetFullPath(const char* config, bool implib,
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
std::string cmTarget::ImportedGetFullPath(const char* config, bool implib)
|
std::string cmTarget::ImportedGetFullPath(const char* config, bool implib)
|
||||||
{
|
{
|
||||||
|
std::string result;
|
||||||
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
|
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
|
||||||
{
|
{
|
||||||
if(implib)
|
result = implib? info->ImportLibrary : info->Location;
|
||||||
{
|
|
||||||
return info->ImportLibrary;
|
|
||||||
}
|
}
|
||||||
else
|
if(result.empty())
|
||||||
{
|
{
|
||||||
return info->Location;
|
result = this->GetName();
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::string result = this->GetName();
|
|
||||||
result += "-NOTFOUND";
|
result += "-NOTFOUND";
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@ -3467,7 +3461,7 @@ cmTarget::GetImportInfo(const char* config)
|
|||||||
|
|
||||||
// If the location is empty then the target is not available for
|
// If the location is empty then the target is not available for
|
||||||
// this configuration.
|
// this configuration.
|
||||||
if(i->second.Location.empty())
|
if(i->second.Location.empty() && i->second.ImportLibrary.empty())
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -3491,6 +3485,12 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
|
|||||||
std::string suffix = "_";
|
std::string suffix = "_";
|
||||||
suffix += desired_config;
|
suffix += desired_config;
|
||||||
|
|
||||||
|
// On a DLL platform there may be only IMPORTED_IMPLIB for a shared
|
||||||
|
// library or an executable with exports.
|
||||||
|
bool allowImp =
|
||||||
|
this->DLLPlatform && (this->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||||
|
this->IsExecutableWithExports());
|
||||||
|
|
||||||
// Look for a mapping from the current project's configuration to
|
// Look for a mapping from the current project's configuration to
|
||||||
// the imported project's configuration.
|
// the imported project's configuration.
|
||||||
std::vector<std::string> mappedConfigs;
|
std::vector<std::string> mappedConfigs;
|
||||||
@ -3505,17 +3505,24 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
|
|||||||
|
|
||||||
// If a mapping was found, check its configurations.
|
// If a mapping was found, check its configurations.
|
||||||
const char* loc = 0;
|
const char* loc = 0;
|
||||||
|
const char* imp = 0;
|
||||||
for(std::vector<std::string>::const_iterator mci = mappedConfigs.begin();
|
for(std::vector<std::string>::const_iterator mci = mappedConfigs.begin();
|
||||||
!loc && mci != mappedConfigs.end(); ++mci)
|
!loc && !imp && mci != mappedConfigs.end(); ++mci)
|
||||||
{
|
{
|
||||||
// Look for this configuration.
|
// Look for this configuration.
|
||||||
std::string mcUpper = cmSystemTools::UpperCase(mci->c_str());
|
std::string mcUpper = cmSystemTools::UpperCase(mci->c_str());
|
||||||
std::string locProp = "IMPORTED_LOCATION_";
|
std::string locProp = "IMPORTED_LOCATION_";
|
||||||
locProp += mcUpper;
|
locProp += mcUpper;
|
||||||
loc = this->GetProperty(locProp.c_str());
|
loc = this->GetProperty(locProp.c_str());
|
||||||
|
if(allowImp)
|
||||||
|
{
|
||||||
|
std::string impProp = "IMPORTED_IMPLIB_";
|
||||||
|
impProp += mcUpper;
|
||||||
|
imp = this->GetProperty(impProp.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
// If it was found, use it for all properties below.
|
// If it was found, use it for all properties below.
|
||||||
if(loc)
|
if(loc || imp)
|
||||||
{
|
{
|
||||||
suffix = "_";
|
suffix = "_";
|
||||||
suffix += mcUpper;
|
suffix += mcUpper;
|
||||||
@ -3525,23 +3532,29 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
|
|||||||
// If we needed to find one of the mapped configurations but did not
|
// If we needed to find one of the mapped configurations but did not
|
||||||
// then the target is not found. The project does not want any
|
// then the target is not found. The project does not want any
|
||||||
// other configuration.
|
// other configuration.
|
||||||
if(!mappedConfigs.empty() && !loc)
|
if(!mappedConfigs.empty() && !loc && !imp)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have not yet found it then there are no mapped
|
// If we have not yet found it then there are no mapped
|
||||||
// configurations. Look for an exact-match.
|
// configurations. Look for an exact-match.
|
||||||
if(!loc)
|
if(!loc && !imp)
|
||||||
{
|
{
|
||||||
std::string locProp = "IMPORTED_LOCATION";
|
std::string locProp = "IMPORTED_LOCATION";
|
||||||
locProp += suffix;
|
locProp += suffix;
|
||||||
loc = this->GetProperty(locProp.c_str());
|
loc = this->GetProperty(locProp.c_str());
|
||||||
|
if(allowImp)
|
||||||
|
{
|
||||||
|
std::string impProp = "IMPORTED_IMPLIB";
|
||||||
|
impProp += suffix;
|
||||||
|
imp = this->GetProperty(impProp.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have not yet found it then there are no mapped
|
// If we have not yet found it then there are no mapped
|
||||||
// configurations and no exact match.
|
// configurations and no exact match.
|
||||||
if(!loc)
|
if(!loc && !imp)
|
||||||
{
|
{
|
||||||
// The suffix computed above is not useful.
|
// The suffix computed above is not useful.
|
||||||
suffix = "";
|
suffix = "";
|
||||||
@ -3549,11 +3562,15 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
|
|||||||
// Look for a configuration-less location. This may be set by
|
// Look for a configuration-less location. This may be set by
|
||||||
// manually-written code.
|
// manually-written code.
|
||||||
loc = this->GetProperty("IMPORTED_LOCATION");
|
loc = this->GetProperty("IMPORTED_LOCATION");
|
||||||
|
if(allowImp)
|
||||||
|
{
|
||||||
|
imp = this->GetProperty("IMPORTED_IMPLIB");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have not yet found it then the project is willing to try
|
// If we have not yet found it then the project is willing to try
|
||||||
// any available configuration.
|
// any available configuration.
|
||||||
if(!loc)
|
if(!loc && !imp)
|
||||||
{
|
{
|
||||||
std::vector<std::string> availableConfigs;
|
std::vector<std::string> availableConfigs;
|
||||||
if(const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS"))
|
if(const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS"))
|
||||||
@ -3562,25 +3579,49 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
|
|||||||
}
|
}
|
||||||
for(std::vector<std::string>::const_iterator
|
for(std::vector<std::string>::const_iterator
|
||||||
aci = availableConfigs.begin();
|
aci = availableConfigs.begin();
|
||||||
!loc && aci != availableConfigs.end(); ++aci)
|
!loc && !imp && aci != availableConfigs.end(); ++aci)
|
||||||
{
|
{
|
||||||
suffix = "_";
|
suffix = "_";
|
||||||
suffix += cmSystemTools::UpperCase(*aci);
|
suffix += cmSystemTools::UpperCase(*aci);
|
||||||
std::string locProp = "IMPORTED_LOCATION";
|
std::string locProp = "IMPORTED_LOCATION";
|
||||||
locProp += suffix;
|
locProp += suffix;
|
||||||
loc = this->GetProperty(locProp.c_str());
|
loc = this->GetProperty(locProp.c_str());
|
||||||
|
if(allowImp)
|
||||||
|
{
|
||||||
|
std::string impProp = "IMPORTED_IMPLIB";
|
||||||
|
impProp += suffix;
|
||||||
|
imp = this->GetProperty(impProp.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have not yet found it then the target is not available.
|
// If we have not yet found it then the target is not available.
|
||||||
if(!loc)
|
if(!loc && !imp)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A provided configuration has been chosen. Load the
|
// A provided configuration has been chosen. Load the
|
||||||
// configuration's properties.
|
// configuration's properties.
|
||||||
|
|
||||||
|
// Get the location.
|
||||||
|
if(loc)
|
||||||
|
{
|
||||||
info.Location = loc;
|
info.Location = loc;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string impProp = "IMPORTED_LOCATION";
|
||||||
|
impProp += suffix;
|
||||||
|
if(const char* config_location = this->GetProperty(impProp.c_str()))
|
||||||
|
{
|
||||||
|
info.Location = config_location;
|
||||||
|
}
|
||||||
|
else if(const char* location = this->GetProperty("IMPORTED_LOCATION"))
|
||||||
|
{
|
||||||
|
info.Location = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get the soname.
|
// Get the soname.
|
||||||
if(this->GetType() == cmTarget::SHARED_LIBRARY)
|
if(this->GetType() == cmTarget::SHARED_LIBRARY)
|
||||||
@ -3613,7 +3654,11 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the import library.
|
// Get the import library.
|
||||||
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
|
if(imp)
|
||||||
|
{
|
||||||
|
info.ImportLibrary = imp;
|
||||||
|
}
|
||||||
|
else if(this->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||||
this->IsExecutableWithExports())
|
this->IsExecutableWithExports())
|
||||||
{
|
{
|
||||||
std::string impProp = "IMPORTED_IMPLIB";
|
std::string impProp = "IMPORTED_IMPLIB";
|
||||||
|
@ -39,6 +39,8 @@ set_property(TARGET testLib3 PROPERTY SOVERSION 3)
|
|||||||
add_library(testLib4 SHARED testLib4.c)
|
add_library(testLib4 SHARED testLib4.c)
|
||||||
set_property(TARGET testLib4 PROPERTY FRAMEWORK 1)
|
set_property(TARGET testLib4 PROPERTY FRAMEWORK 1)
|
||||||
|
|
||||||
|
add_library(testLib5 SHARED testLib5.c)
|
||||||
|
|
||||||
# Work-around: Visual Studio 6 does not support per-target object files.
|
# Work-around: Visual Studio 6 does not support per-target object files.
|
||||||
set(VS6)
|
set(VS6)
|
||||||
if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6")
|
if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6")
|
||||||
@ -85,15 +87,27 @@ install(
|
|||||||
LIBRARY DESTINATION lib/impl
|
LIBRARY DESTINATION lib/impl
|
||||||
ARCHIVE DESTINATION lib/impl
|
ARCHIVE DESTINATION lib/impl
|
||||||
)
|
)
|
||||||
|
install(
|
||||||
|
TARGETS testLib5
|
||||||
|
EXPORT exp
|
||||||
|
# Leave out RUNTIME DESTINATION to test implib-only export.
|
||||||
|
LIBRARY DESTINATION lib
|
||||||
|
ARCHIVE DESTINATION lib
|
||||||
|
)
|
||||||
install(EXPORT exp NAMESPACE exp_ DESTINATION lib/exp)
|
install(EXPORT exp NAMESPACE exp_ DESTINATION lib/exp)
|
||||||
|
|
||||||
|
# Install testLib5.dll outside the export.
|
||||||
|
if(WIN32)
|
||||||
|
install(TARGETS testLib5 RUNTIME DESTINATION bin)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
# Export from build tree.
|
# Export from build tree.
|
||||||
export(TARGETS testExe1 testLib1 testLib2 testLib3
|
export(TARGETS testExe1 testLib1 testLib2 testLib3
|
||||||
testExe2libImp testLib3Imp
|
testExe2libImp testLib3Imp
|
||||||
NAMESPACE bld_
|
NAMESPACE bld_
|
||||||
FILE ExportBuildTree.cmake
|
FILE ExportBuildTree.cmake
|
||||||
)
|
)
|
||||||
export(TARGETS testExe2 testLib4 testExe3 testExe2lib
|
export(TARGETS testExe2 testLib4 testLib5 testExe3 testExe2lib
|
||||||
testLib4lib testLib4libdbg testLib4libopt
|
testLib4lib testLib4libdbg testLib4libopt
|
||||||
NAMESPACE bld_
|
NAMESPACE bld_
|
||||||
APPEND FILE ExportBuildTree.cmake
|
APPEND FILE ExportBuildTree.cmake
|
||||||
|
7
Tests/ExportImport/Export/testLib5.c
Normal file
7
Tests/ExportImport/Export/testLib5.c
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||||
|
# define testLib5_EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
# define testLib5_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
testLib5_EXPORT int testLib5(void) { return 0; }
|
@ -23,7 +23,12 @@ add_executable(imp_testExe1
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Try linking to a library imported from the install tree.
|
# Try linking to a library imported from the install tree.
|
||||||
target_link_libraries(imp_testExe1 exp_testLib2 exp_testLib3 exp_testLib4)
|
target_link_libraries(imp_testExe1
|
||||||
|
exp_testLib2
|
||||||
|
exp_testLib3
|
||||||
|
exp_testLib4
|
||||||
|
exp_testLib5
|
||||||
|
)
|
||||||
|
|
||||||
# Try building a plugin to an executable imported from the install tree.
|
# Try building a plugin to an executable imported from the install tree.
|
||||||
add_library(imp_mod1 MODULE imp_mod1.c)
|
add_library(imp_mod1 MODULE imp_mod1.c)
|
||||||
@ -48,7 +53,12 @@ add_executable(imp_testExe1b
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Try linking to a library imported from the build tree.
|
# Try linking to a library imported from the build tree.
|
||||||
target_link_libraries(imp_testExe1b bld_testLib2 bld_testLib3 bld_testLib4)
|
target_link_libraries(imp_testExe1b
|
||||||
|
bld_testLib2
|
||||||
|
bld_testLib3
|
||||||
|
bld_testLib4
|
||||||
|
bld_testLib5
|
||||||
|
)
|
||||||
|
|
||||||
# Try building a plugin to an executable imported from the build tree.
|
# Try building a plugin to an executable imported from the build tree.
|
||||||
add_library(imp_mod1b MODULE imp_mod1.c)
|
add_library(imp_mod1b MODULE imp_mod1.c)
|
||||||
|
@ -4,6 +4,7 @@ extern int testLib2();
|
|||||||
extern int testLib3();
|
extern int testLib3();
|
||||||
extern int testLib4();
|
extern int testLib4();
|
||||||
extern int testLib4lib();
|
extern int testLib4lib();
|
||||||
|
extern int testLib5();
|
||||||
|
|
||||||
/* Switch a symbol between debug and optimized builds to make sure the
|
/* Switch a symbol between debug and optimized builds to make sure the
|
||||||
proper library is found from the testLib4 link interface. */
|
proper library is found from the testLib4 link interface. */
|
||||||
@ -17,5 +18,6 @@ extern testLib4libcfg(void);
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
return (testLib2() + generated_by_testExe1() + testLib3() + testLib4()
|
return (testLib2() + generated_by_testExe1() + testLib3() + testLib4()
|
||||||
|
+ testLib5()
|
||||||
+ generated_by_testExe3() + testLib4lib() + testLib4libcfg());
|
+ generated_by_testExe3() + testLib4lib() + testLib4libcfg());
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user