summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2009-04-08 20:29:04 (GMT)
committerBrad King <brad.king@kitware.com>2009-04-08 20:29:04 (GMT)
commitd05e98f8d77e03c0c68ae3d7b5e5617f54dc6b07 (patch)
tree6e74a9ece72ee60b14423a2312ffc9add11ab0ef
parent5886d103348ba7c14e464c851d3316f09cc2c0c6 (diff)
downloadCMake-d05e98f8d77e03c0c68ae3d7b5e5617f54dc6b07.zip
CMake-d05e98f8d77e03c0c68ae3d7b5e5617f54dc6b07.tar.gz
CMake-d05e98f8d77e03c0c68ae3d7b5e5617f54dc6b07.tar.bz2
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.
-rw-r--r--Source/cmTarget.cxx91
-rw-r--r--Tests/ExportImport/Export/CMakeLists.txt16
-rw-r--r--Tests/ExportImport/Export/testLib5.c7
-rw-r--r--Tests/ExportImport/Import/A/CMakeLists.txt14
-rw-r--r--Tests/ExportImport/Import/A/imp_testExe1.c2
5 files changed, 104 insertions, 26 deletions
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 09f261d..8c8352f 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -2527,23 +2527,17 @@ std::string cmTarget::NormalGetFullPath(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(implib)
- {
- return info->ImportLibrary;
- }
- else
- {
- return info->Location;
- }
+ result = implib? info->ImportLibrary : info->Location;
}
- else
+ if(result.empty())
{
- std::string result = this->GetName();
+ result = this->GetName();
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
// this configuration.
- if(i->second.Location.empty())
+ if(i->second.Location.empty() && i->second.ImportLibrary.empty())
{
return 0;
}
@@ -3491,6 +3485,12 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
std::string suffix = "_";
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
// the imported project's configuration.
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.
const char* loc = 0;
+ const char* imp = 0;
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.
std::string mcUpper = cmSystemTools::UpperCase(mci->c_str());
std::string locProp = "IMPORTED_LOCATION_";
locProp += mcUpper;
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(loc)
+ if(loc || imp)
{
suffix = "_";
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
// then the target is not found. The project does not want any
// other configuration.
- if(!mappedConfigs.empty() && !loc)
+ if(!mappedConfigs.empty() && !loc && !imp)
{
return;
}
// If we have not yet found it then there are no mapped
// configurations. Look for an exact-match.
- if(!loc)
+ if(!loc && !imp)
{
std::string locProp = "IMPORTED_LOCATION";
locProp += suffix;
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
// configurations and no exact match.
- if(!loc)
+ if(!loc && !imp)
{
// The suffix computed above is not useful.
suffix = "";
@@ -3549,11 +3562,15 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
// Look for a configuration-less location. This may be set by
// manually-written code.
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
// any available configuration.
- if(!loc)
+ if(!loc && !imp)
{
std::vector<std::string> availableConfigs;
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
aci = availableConfigs.begin();
- !loc && aci != availableConfigs.end(); ++aci)
+ !loc && !imp && aci != availableConfigs.end(); ++aci)
{
suffix = "_";
suffix += cmSystemTools::UpperCase(*aci);
std::string locProp = "IMPORTED_LOCATION";
locProp += suffix;
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(!loc)
+ if(!loc && !imp)
{
return;
}
// A provided configuration has been chosen. Load the
// configuration's properties.
- info.Location = loc;
+
+ // Get the location.
+ if(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.
if(this->GetType() == cmTarget::SHARED_LIBRARY)
@@ -3613,8 +3654,12 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
}
// Get the import library.
- if(this->GetType() == cmTarget::SHARED_LIBRARY ||
- this->IsExecutableWithExports())
+ if(imp)
+ {
+ info.ImportLibrary = imp;
+ }
+ else if(this->GetType() == cmTarget::SHARED_LIBRARY ||
+ this->IsExecutableWithExports())
{
std::string impProp = "IMPORTED_IMPLIB";
impProp += suffix;
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index 26687b1..19cd22f 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -39,6 +39,8 @@ set_property(TARGET testLib3 PROPERTY SOVERSION 3)
add_library(testLib4 SHARED testLib4.c)
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.
set(VS6)
if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6")
@@ -85,15 +87,27 @@ install(
LIBRARY 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 testLib5.dll outside the export.
+if(WIN32)
+ install(TARGETS testLib5 RUNTIME DESTINATION bin)
+endif(WIN32)
+
# Export from build tree.
export(TARGETS testExe1 testLib1 testLib2 testLib3
testExe2libImp testLib3Imp
NAMESPACE bld_
FILE ExportBuildTree.cmake
)
-export(TARGETS testExe2 testLib4 testExe3 testExe2lib
+export(TARGETS testExe2 testLib4 testLib5 testExe3 testExe2lib
testLib4lib testLib4libdbg testLib4libopt
NAMESPACE bld_
APPEND FILE ExportBuildTree.cmake
diff --git a/Tests/ExportImport/Export/testLib5.c b/Tests/ExportImport/Export/testLib5.c
new file mode 100644
index 0000000..20a8215
--- /dev/null
+++ b/Tests/ExportImport/Export/testLib5.c
@@ -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; }
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt
index 16cff2d..e874cdb 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -23,7 +23,12 @@ add_executable(imp_testExe1
)
# 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.
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.
-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.
add_library(imp_mod1b MODULE imp_mod1.c)
diff --git a/Tests/ExportImport/Import/A/imp_testExe1.c b/Tests/ExportImport/Import/A/imp_testExe1.c
index 6424d33..6a6ba0f 100644
--- a/Tests/ExportImport/Import/A/imp_testExe1.c
+++ b/Tests/ExportImport/Import/A/imp_testExe1.c
@@ -4,6 +4,7 @@ extern int testLib2();
extern int testLib3();
extern int testLib4();
extern int testLib4lib();
+extern int testLib5();
/* Switch a symbol between debug and optimized builds to make sure the
proper library is found from the testLib4 link interface. */
@@ -17,5 +18,6 @@ extern testLib4libcfg(void);
int main()
{
return (testLib2() + generated_by_testExe1() + testLib3() + testLib4()
+ + testLib5()
+ generated_by_testExe3() + testLib4lib() + testLib4libcfg());
}