summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2007-03-19 14:00:36 (GMT)
committerBrad King <brad.king@kitware.com>2007-03-19 14:00:36 (GMT)
commitfc7c43346318744d05829579e6312aecddc66207 (patch)
treec5189c40170f90423c4b2a0cf72a5610282d1d8e /Source
parent43589ec702cd037ed6b5c9f2c8b7558f4cb8801b (diff)
downloadCMake-fc7c43346318744d05829579e6312aecddc66207.zip
CMake-fc7c43346318744d05829579e6312aecddc66207.tar.gz
CMake-fc7c43346318744d05829579e6312aecddc66207.tar.bz2
ENH: Added support for import libraries created by executable and module targets. The module import libraries should never be used but some windows compilers always create them for .dll files since there is no distinction from shared libraries on that platform. The executable import libraries may be used to create modules that when loaded bind to symbols from the executables. This is an enhancement related to bug#4210 though not requested by it explicitly.
Diffstat (limited to 'Source')
-rw-r--r--Source/cmInstallCommand.cxx14
-rw-r--r--Source/cmInstallTargetGenerator.cxx32
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx3
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx4
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx20
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx35
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx11
-rw-r--r--Source/cmTarget.cxx77
-rw-r--r--Source/cmTarget.h4
9 files changed, 149 insertions, 51 deletions
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index d270c77..5244b9f 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -532,6 +532,20 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
this->SetError(e.str().c_str());
return false;
}
+
+ // On DLL platforms an executable may also have an import
+ // library. Install it to the archive destination if it
+ // exists.
+ if(dll_platform && archive_destination)
+ {
+ // The import library uses the ARCHIVE properties.
+ this->Makefile->AddInstallGenerator(
+ new cmInstallTargetGenerator(target, archive_dest.c_str(), true,
+ archive_permissions.c_str(),
+ archive_configurations,
+ archive_component.c_str(),
+ true));
+ }
}
break;
default:
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 3acabec..fd92eab 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -208,11 +208,21 @@ cmInstallTargetGenerator
{
std::string targetName;
std::string targetNameReal;
+ std::string targetNameImport;
std::string targetNamePDB;
target->GetExecutableNames(targetName, targetNameReal,
- targetNamePDB, i->c_str());
- // Use the canonical name.
- fname += targetName;
+ targetNameImport, targetNamePDB,
+ i->c_str());
+ if(this->ImportLibrary)
+ {
+ // Use the import library name.
+ fname += targetNameImport;
+ }
+ else
+ {
+ // Use the canonical name.
+ fname += targetName;
+ }
}
else
{
@@ -259,11 +269,21 @@ std::string cmInstallTargetGenerator::GetScriptReference(cmTarget* target,
{
std::string targetName;
std::string targetNameReal;
+ std::string targetNameImport;
std::string targetNamePDB;
target->GetExecutableNames(targetName, targetNameReal,
- targetNamePDB, this->ConfigurationName);
- // Use the canonical name.
- return targetName;
+ targetNameImport, targetNamePDB,
+ this->ConfigurationName);
+ if(this->ImportLibrary)
+ {
+ // Use the import library name.
+ return targetNameImport;
+ }
+ else
+ {
+ // Use the canonical name.
+ return targetName;
+ }
}
else
{
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 008061a..2b8f346 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -1645,8 +1645,9 @@ cmLocalUnixMakefileGenerator3
objectName = cmSystemTools::GetFilenameName(objectName.c_str());
std::string targetName;
std::string targetNameReal;
+ std::string targetNameImport;
std::string targetNamePDB;
- target.GetExecutableNames(targetName, targetNameReal,
+ target.GetExecutableNames(targetName, targetNameReal, targetNameImport,
targetNamePDB, this->ConfigurationName.c_str());
std::string obj;
if ( target.GetPropertyAsBool("MACOSX_BUNDLE") )
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index 3a72de6..40ba473 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -1221,7 +1221,9 @@ void cmLocalVisualStudio6Generator
std::string targetImplibFlagRelease;
std::string targetImplibFlagMinSizeRel;
std::string targetImplibFlagRelWithDebInfo;
- if(target.GetType() == cmTarget::SHARED_LIBRARY)
+ if(target.GetType() == cmTarget::SHARED_LIBRARY ||
+ target.GetType() == cmTarget::MODULE_LIBRARY ||
+ target.GetType() == cmTarget::EXECUTABLE)
{
std::string fullPathImpDebug = target.GetDirectory("Debug", true);
std::string fullPathImpRelease = target.GetDirectory("Release", true);
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index e627f0d..71a1e0d 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -733,17 +733,6 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
target.GetLibraryNames(targetName, targetNameSO, targetNameFull,
targetNameImport, targetNamePDB, configName);
- // VS does not distinguish between shared libraries and module
- // libraries so it still wants to be given the name of an import
- // library for modules.
- if(targetNameImport.empty() &&
- target.GetType() == cmTarget::MODULE_LIBRARY)
- {
- targetNameImport =
- cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull);
- targetNameImport += ".lib";
- }
-
// Compute the link library and directory information.
std::vector<cmStdString> linkLibs;
std::vector<cmStdString> linkDirs;
@@ -816,9 +805,10 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
{
std::string targetName;
std::string targetNameFull;
+ std::string targetNameImport;
std::string targetNamePDB;
target.GetExecutableNames(targetName, targetNameFull,
- targetNamePDB, configName);
+ targetNameImport, targetNamePDB, configName);
// Compute the link library and directory information.
std::vector<cmStdString> linkLibs;
@@ -886,7 +876,11 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
{
fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"";
}
- fout << "/>\n";
+ temp = target.GetDirectory(configName, true);
+ temp += "/";
+ temp += targetNameImport;
+ fout << "\t\t\t\tImportLibrary=\""
+ << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"/>\n";
break;
}
case cmTarget::UTILITY:
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 06b054a..2414458 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -110,9 +110,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Get the name of the executable to generate.
std::string targetName;
std::string targetNameReal;
+ std::string targetNameImport;
std::string targetNamePDB;
this->Target->GetExecutableNames
- (targetName, targetNameReal, targetNamePDB,
+ (targetName, targetNameReal, targetNameImport, targetNamePDB,
this->LocalGenerator->ConfigurationName.c_str());
// Construct the full path version of the names.
@@ -167,6 +168,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
false, false, false);
}
#endif
+ std::string outpathImp;
if(relink)
{
outpath = this->Makefile->GetStartOutputDirectory();
@@ -174,10 +176,23 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
outpath += "/CMakeRelink.dir";
cmSystemTools::MakeDirectory(outpath.c_str());
outpath += "/";
+ if(!targetNameImport.empty())
+ {
+ outpathImp = outpath;
+ }
+ }
+ else
+ {
+ if(!targetNameImport.empty())
+ {
+ outpathImp = this->Target->GetDirectory(0, true);
+ outpathImp += "/";
+ }
}
std::string targetFullPath = outpath + targetName;
std::string targetFullPathReal = outpath + targetNameReal;
std::string targetFullPathPDB = outpath + targetNamePDB;
+ std::string targetFullPathImport = outpathImp + targetNameImport;
std::string targetOutPathPDB =
this->Convert(targetFullPathPDB.c_str(),
cmLocalGenerator::FULL,
@@ -191,7 +206,11 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
this->Convert(targetFullPathReal.c_str(),
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::SHELL);
-
+ std::string targetOutPathImport =
+ this->Convert(targetFullPathImport.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::SHELL);
+
// Get the language to use for linking this executable.
const char* linkLanguage =
this->Target->GetLinkerLanguage(this->GlobalGenerator);
@@ -258,14 +277,16 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
{
std::string cleanName;
std::string cleanRealName;
+ std::string cleanImportName;
std::string cleanPDBName;
this->Target->GetExecutableCleanNames
- (cleanName, cleanRealName, cleanPDBName,
+ (cleanName, cleanRealName, cleanImportName, cleanPDBName,
this->LocalGenerator->ConfigurationName.c_str());
std::string cleanFullName = outpath + cleanName;
std::string cleanFullRealName = outpath + cleanRealName;
std::string cleanFullPDBName = outpath + cleanPDBName;
+ std::string cleanFullImportName = outpathImp + cleanImportName;
exeCleanFiles.push_back(this->Convert(cleanFullName.c_str(),
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::UNCHANGED));
@@ -282,6 +303,12 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::UNCHANGED));
}
+ if(!cleanImportName.empty())
+ {
+ exeCleanFiles.push_back(this->Convert(cleanFullImportName.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::UNCHANGED));
+ }
// List the PDB for cleaning only when the whole target is
// cleaned. We do not want to delete the .pdb file just before
@@ -394,11 +421,13 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
vars.Flags = flags.c_str();
vars.LinkFlags = linkFlags.c_str();
// Expand placeholders in the commands.
+ this->LocalGenerator->TargetImplib = targetOutPathImport;
for(std::vector<std::string>::iterator i = commands.begin();
i != commands.end(); ++i)
{
this->LocalGenerator->ExpandRuleVariables(*i, vars);
}
+ this->LocalGenerator->TargetImplib = "";
// Write the build rule.
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream,
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index d1398a1..717b0dd 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -341,10 +341,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::UNCHANGED));
}
- if(!targetNameImport.empty() &&
- targetNameImport != targetName &&
- targetNameImport != targetNameReal &&
- targetNameImport != targetNameSO)
+ if(!targetNameImport.empty())
{
libCleanFiles.push_back(this->Convert(targetFullPathImport.c_str(),
cmLocalGenerator::START_OUTPUT,
@@ -401,11 +398,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::UNCHANGED));
}
- if(!cleanImportName.empty() &&
- cleanImportName != cleanStaticName &&
- cleanImportName != cleanSharedSOName &&
- cleanImportName != cleanSharedRealName &&
- cleanImportName != cleanSharedName)
+ if(!cleanImportName.empty())
{
libCleanFiles.push_back(this->Convert(cleanFullImportName.c_str(),
cmLocalGenerator::START_OUTPUT,
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 45e71d0..ef4a07e 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -37,6 +37,7 @@ cmTarget::cmTarget()
this->LinkLibrariesAnalyzed = false;
this->LinkDirectoriesComputed = false;
this->HaveInstallRule = false;
+ this->DLLPlatform = false;
}
@@ -335,6 +336,11 @@ void cmTarget::SetMakefile(cmMakefile* mf)
// set the cmake instance of the properties
this->Properties.SetCMakeInstance(mf->GetCMakeInstance());
+ // Check whether this is a DLL platform.
+ this->DLLPlatform = (this->Makefile->IsOn("WIN32") ||
+ this->Makefile->IsOn("CYGWIN") ||
+ this->Makefile->IsOn("MINGW"));
+
// Setup default property values.
this->SetPropertyDefault("INSTALL_NAME_DIR", "");
this->SetPropertyDefault("INSTALL_RPATH", "");
@@ -1427,9 +1433,13 @@ const char* cmTarget::GetSuffixVariableInternal(TargetType type,
? "CMAKE_IMPORT_LIBRARY_SUFFIX"
: "CMAKE_SHARED_LIBRARY_SUFFIX");
case cmTarget::MODULE_LIBRARY:
- return "CMAKE_SHARED_MODULE_SUFFIX";
+ return (implib
+ ? "CMAKE_IMPORT_LIBRARY_SUFFIX"
+ : "CMAKE_SHARED_MODULE_SUFFIX");
case cmTarget::EXECUTABLE:
- return "CMAKE_EXECUTABLE_SUFFIX";
+ return (implib
+ ? "CMAKE_IMPORT_LIBRARY_SUFFIX"
+ : "CMAKE_EXECUTABLE_SUFFIX");
case cmTarget::UTILITY:
case cmTarget::GLOBAL_TARGET:
case cmTarget::INSTALL_FILES:
@@ -1453,8 +1463,11 @@ const char* cmTarget::GetPrefixVariableInternal(TargetType type,
? "CMAKE_IMPORT_LIBRARY_PREFIX"
: "CMAKE_SHARED_LIBRARY_PREFIX");
case cmTarget::MODULE_LIBRARY:
- return "CMAKE_SHARED_MODULE_PREFIX";
+ return (implib
+ ? "CMAKE_IMPORT_LIBRARY_PREFIX"
+ : "CMAKE_SHARED_MODULE_PREFIX");
case cmTarget::EXECUTABLE:
+ return (implib? "CMAKE_IMPORT_LIBRARY_PREFIX" : "");
case cmTarget::UTILITY:
case cmTarget::GLOBAL_TARGET:
case cmTarget::INSTALL_FILES:
@@ -1545,8 +1558,11 @@ void cmTarget::GetFullNameInternal(TargetType type,
return;
}
- // The implib option is only allowed for shared libraries.
- if(type != cmTarget::SHARED_LIBRARY)
+ // The implib option is only allowed for shared libraries, module
+ // libraries, and executables.
+ if(type != cmTarget::SHARED_LIBRARY &&
+ type != cmTarget::MODULE_LIBRARY &&
+ type != cmTarget::EXECUTABLE)
{
implib = false;
}
@@ -1769,7 +1785,8 @@ void cmTarget::GetLibraryNamesInternal(std::string& name,
#endif
// The import library name.
- if(type == cmTarget::SHARED_LIBRARY)
+ if(type == cmTarget::SHARED_LIBRARY ||
+ type == cmTarget::MODULE_LIBRARY)
{
impName = this->GetFullNameInternal(type, config, true);
}
@@ -1784,26 +1801,29 @@ void cmTarget::GetLibraryNamesInternal(std::string& name,
void cmTarget::GetExecutableNames(std::string& name,
std::string& realName,
+ std::string& impName,
std::string& pdbName,
const char* config)
{
// Get the names based on the real type of the executable.
- this->GetExecutableNamesInternal(name, realName, pdbName,
+ this->GetExecutableNamesInternal(name, realName, impName, pdbName,
this->GetType(), config);
}
void cmTarget::GetExecutableCleanNames(std::string& name,
std::string& realName,
+ std::string& impName,
std::string& pdbName,
const char* config)
{
// Get the name and versioned name of this executable.
- this->GetExecutableNamesInternal(name, realName, pdbName,
+ this->GetExecutableNamesInternal(name, realName, impName, pdbName,
cmTarget::EXECUTABLE, config);
}
void cmTarget::GetExecutableNamesInternal(std::string& name,
std::string& realName,
+ std::string& impName,
std::string& pdbName,
TargetType type,
const char* config)
@@ -1845,6 +1865,9 @@ void cmTarget::GetExecutableNamesInternal(std::string& name,
realName += suffix;
#endif
+ // The import library name.
+ impName = this->GetFullNameInternal(type, config, true);
+
// The program database file name.
pdbName = prefix+base+".pdb";
}
@@ -1986,8 +2009,11 @@ std::string cmTarget::GetInstallNameDirForInstallTree(const char*)
//----------------------------------------------------------------------------
const char* cmTarget::GetOutputDir(bool implib)
{
- // The implib option is only allowed for shared libraries.
- if(this->GetType() != cmTarget::SHARED_LIBRARY)
+ // The implib option is only allowed for shared libraries, module
+ // libraries, and executables.
+ if(this->GetType() != cmTarget::SHARED_LIBRARY &&
+ this->GetType() != cmTarget::MODULE_LIBRARY &&
+ this->GetType() != cmTarget::EXECUTABLE)
{
implib = false;
}
@@ -2000,6 +2026,10 @@ const char* cmTarget::GetOutputDir(bool implib)
{
abort();
}
+ if(implib && !this->DLLPlatform)
+ {
+ abort();
+ }
// Select whether we are constructing the directory for the main
// target or the import library.
@@ -2019,12 +2049,7 @@ const char* cmTarget::GetOutputDir(bool implib)
// shared library is treated as a runtime target and the
// corresponding import library is treated as an archive
// target.
-
- // Check whether this is a DLL platform.
- bool dll_platform = (this->Makefile->IsOn("WIN32") ||
- this->Makefile->IsOn("CYGWIN") ||
- this->Makefile->IsOn("MINGW"));
- if(dll_platform)
+ if(this->DLLPlatform)
{
if(implib)
{
@@ -2048,12 +2073,28 @@ const char* cmTarget::GetOutputDir(bool implib)
case cmTarget::MODULE_LIBRARY:
{
// Module libraries are always treated as library targets.
- propertyName = "LIBRARY_OUTPUT_DIRECTORY";
+ // Module import libraries are treated as archive targets.
+ if(implib)
+ {
+ propertyName = "ARCHIVE_OUTPUT_DIRECTORY";
+ }
+ else
+ {
+ propertyName = "LIBRARY_OUTPUT_DIRECTORY";
+ }
} break;
case cmTarget::EXECUTABLE:
{
// Executables are always treated as runtime targets.
- propertyName = "RUNTIME_OUTPUT_DIRECTORY";
+ // Executable import libraries are treated as archive targets.
+ if(implib)
+ {
+ propertyName = "ARCHIVE_OUTPUT_DIRECTORY";
+ }
+ else
+ {
+ propertyName = "RUNTIME_OUTPUT_DIRECTORY";
+ }
} break;
default: break;
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 6e446e0..028231a 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -228,6 +228,7 @@ public:
that takes into account executable version numbers. This should
be called only on an executable target. */
void GetExecutableNames(std::string& name, std::string& realName,
+ std::string& impName,
std::string& pdbName, const char* config);
/** Get the names of the executable used to remove existing copies
@@ -235,6 +236,7 @@ public:
during a clean step. This should be called only on an
executable target. */
void GetExecutableCleanNames(std::string& name, std::string& realName,
+ std::string& impName,
std::string& pdbName, const char* config);
/**
@@ -323,6 +325,7 @@ private:
const char* config);
void GetExecutableNamesInternal(std::string& name,
std::string& realName,
+ std::string& impName,
std::string& pdbName,
TargetType type,
const char* config);
@@ -360,6 +363,7 @@ private:
bool RecordDependencies;
cmPropertyMap Properties;
LinkLibraryVectorType OriginalLinkLibraries;
+ bool DLLPlatform;
// The cmMakefile instance that owns this target. This should
// always be set.