Commit 81677b31 authored by Brad King's avatar Brad King
Browse files

ENH: Generate import libraries for DLLs on Cygwin and MinGW.

parent 9ba02838
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-shared -Wl,--export-all-symbols -Wl,--enable-auto-import")
SET(CMAKE_DL_LIBS "-lgdi32" )
SET(CMAKE_SHARED_LIBRARY_PREFIX "lib")
SET(CMAKE_SHARED_LIBRARY_PREFIX "cyg")
SET(CMAKE_SHARED_LIBRARY_SUFFIX ".dll")
SET(CMAKE_IMPORT_LIBRARY_PREFIX "lib")
SET(CMAKE_IMPORT_LIBRARY_SUFFIX ".dll.a")
# no pic for gcc on cygwin
SET(CMAKE_SHARED_LIBRARY_C_FLAGS "")
SET(CMAKE_SHARED_LIBRARY_CXX_FLAGS "")
......@@ -9,3 +11,13 @@ SET(CMAKE_EXECUTABLE_SUFFIX ".exe") # .exe
SET(CMAKE_FIND_LIBRARY_PREFIXES "cyg" "lib")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".dll" ".dll.a" ".a")
SET(CMAKE_C_CREATE_SHARED_MODULE
"<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
SET(CMAKE_CXX_CREATE_SHARED_MODULE
"<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
SET(CMAKE_C_CREATE_SHARED_LIBRARY
"<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> -o <TARGET> -Wl,--out-implib,<TARGET_IMPLIB> <OBJECTS> <LINK_LIBRARIES>")
SET(CMAKE_CXX_CREATE_SHARED_LIBRARY
"<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> -Wl,--out-implib,<TARGET_IMPLIB> <OBJECTS> <LINK_LIBRARIES>")
......@@ -29,7 +29,7 @@ SET (CMAKE_MANGLE_OBJECT_FILE_NAMES "ON")
# create a shared C++ library
SET(CMAKE_CXX_CREATE_SHARED_LIBRARY
"<CMAKE_CXX_COMPILER> ${CMAKE_START_TEMP_FILE}-e<TARGET> -tWD <LINK_FLAGS> -tWR <LINK_LIBRARIES> <OBJECTS>${CMAKE_END_TEMP_FILE}"
"implib -c -w <TARGET_BASE>.lib <TARGET_BASE>.dll"
"implib -c -w <TARGET_IMPLIB> <TARGET>"
)
SET(CMAKE_CXX_CREATE_SHARED_MODULE ${CMAKE_CXX_CREATE_SHARED_LIBRARY})
......@@ -37,7 +37,7 @@ SET(CMAKE_CXX_CREATE_SHARED_MODULE ${CMAKE_CXX_CREATE_SHARED_LIBRARY})
# create a C shared library
SET(CMAKE_C_CREATE_SHARED_LIBRARY
"<CMAKE_C_COMPILER> ${CMAKE_START_TEMP_FILE}-e<TARGET> -tWD <LINK_FLAGS> -tWR <LINK_LIBRARIES> <OBJECTS>${CMAKE_END_TEMP_FILE}"
"implib -c -w <TARGET_BASE>.lib <TARGET_BASE>.dll"
"implib -c -w <TARGET_IMPLIB> <TARGET>"
)
# create a C shared module just copy the shared library rule
......
......@@ -5,6 +5,8 @@ SET(CMAKE_SHARED_LIBRARY_PREFIX "lib") # lib
SET(CMAKE_SHARED_LIBRARY_SUFFIX ".dll") # .so
SET(CMAKE_SHARED_MODULE_PREFIX "lib") # lib
SET(CMAKE_SHARED_MODULE_SUFFIX ".dll") # .so
SET(CMAKE_IMPORT_LIBRARY_PREFIX "lib")
SET(CMAKE_IMPORT_LIBRARY_SUFFIX ".dll.a")
SET(CMAKE_EXECUTABLE_SUFFIX ".exe") # .exe
SET(CMAKE_DL_LIBS "")
SET(CMAKE_SHARED_LIBRARY_C_FLAGS "") # -pic
......@@ -20,3 +22,13 @@ IF(MINGW)
SET(CMAKE_FIND_LIBRARY_PREFIXES "lib" "")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".dll" ".dll.a" ".a")
ENDIF(MINGW)
SET(CMAKE_C_CREATE_SHARED_MODULE
"<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
SET(CMAKE_CXX_CREATE_SHARED_MODULE
"<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
SET(CMAKE_C_CREATE_SHARED_LIBRARY
"<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> -o <TARGET_BASE>.dll -Wl,--out-implib,<TARGET_IMPLIB> <OBJECTS> <LINK_LIBRARIES>")
SET(CMAKE_CXX_CREATE_SHARED_LIBRARY
"<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET_BASE>.dll -Wl,--out-implib,<TARGET_IMPLIB> <OBJECTS> <LINK_LIBRARIES>")
......@@ -40,7 +40,7 @@ SET(CMAKE_C_COMPILE_OBJECT
SET(CMAKE_CXX_CREATE_SHARED_LIBRARY
"wlink ${CMAKE_START_TEMP_FILE} system nt_dll ${CMAKE_WLINK_QUIET} name <TARGET> option caseexact file {<OBJECTS>} <LINK_LIBRARIES>"
"wlib -q -n -b <TARGET_BASE>.lib +<TARGET_BASE>.dll ${CMAKE_END_TEMP_FILE}")
"wlib -q -n -b <TARGET_IMPLIB> +<TARGET> ${CMAKE_END_TEMP_FILE}")
SET(CMAKE_CXX_CREATE_SHARED_MODULE ${CMAKE_CXX_CREATE_SHARED_LIBRARY})
# create a C shared library
......
......@@ -2,6 +2,8 @@ SET(CMAKE_STATIC_LIBRARY_PREFIX "")
SET(CMAKE_STATIC_LIBRARY_SUFFIX ".lib")
SET(CMAKE_SHARED_LIBRARY_PREFIX "") # lib
SET(CMAKE_SHARED_LIBRARY_SUFFIX ".dll") # .so
SET(CMAKE_IMPORT_LIBRARY_PREFIX "")
SET(CMAKE_IMPORT_LIBRARY_SUFFIX ".lib")
SET(CMAKE_EXECUTABLE_SUFFIX ".exe") # .exe
SET(CMAKE_LINK_LIBRARY_SUFFIX ".lib")
SET(CMAKE_DL_LIBS "")
......
......@@ -872,6 +872,10 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable,
{
return target;
}
if(variable == "TARGET_IMPLIB")
{
return m_TargetImplib;
}
if(variable == "TARGET_BASE")
{
// Strip the last extension off the target name.
......
......@@ -247,6 +247,10 @@ protected:
bool m_UseRelativePaths;
bool m_IgnoreLibPrefix;
bool Configured;
// Hack for ExpandRuleVariable until object-oriented version is
// committed.
std::string m_TargetImplib;
};
#endif
......@@ -202,8 +202,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
std::string targetName;
std::string targetNameSO;
std::string targetNameReal;
this->Target->GetLibraryNames(targetName, targetNameSO, targetNameReal,
this->LocalGenerator->m_ConfigurationName.c_str());
std::string targetNameImport;
this->Target->GetLibraryNames(
targetName, targetNameSO, targetNameReal, targetNameImport,
this->LocalGenerator->m_ConfigurationName.c_str());
// Construct the full path version of the names.
std::string outpath = this->LocalGenerator->m_LibraryOutputPath;
......@@ -222,6 +224,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
std::string targetFullPath = outpath + targetName;
std::string targetFullPathSO = outpath + targetNameSO;
std::string targetFullPathReal = outpath + targetNameReal;
std::string targetFullPathImport = outpath + targetNameImport;
// Construct the output path version of the names for use in command
// arguments.
......@@ -234,6 +237,9 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
std::string targetOutPathReal =
this->Convert(targetFullPathReal.c_str(),cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::MAKEFILE);
std::string targetOutPathImport =
this->Convert(targetFullPathImport.c_str(),cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::MAKEFILE);
// Add the link message.
std::string buildEcho = "Linking ";
......@@ -260,15 +266,19 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
std::string cleanSharedName;
std::string cleanSharedSOName;
std::string cleanSharedRealName;
this->Target->GetLibraryCleanNames(cleanStaticName,
cleanSharedName,
cleanSharedSOName,
cleanSharedRealName,
this->LocalGenerator->m_ConfigurationName.c_str());
std::string cleanImportName;
this->Target->GetLibraryCleanNames(
cleanStaticName,
cleanSharedName,
cleanSharedSOName,
cleanSharedRealName,
cleanImportName,
this->LocalGenerator->m_ConfigurationName.c_str());
std::string cleanFullStaticName = outpath + cleanStaticName;
std::string cleanFullSharedName = outpath + cleanSharedName;
std::string cleanFullSharedSOName = outpath + cleanSharedSOName;
std::string cleanFullSharedRealName = outpath + cleanSharedRealName;
std::string cleanFullImportName = outpath + cleanImportName;
libCleanFiles.push_back
(this->Convert(cleanFullStaticName.c_str(),cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::MAKEFILE));
......@@ -293,6 +303,16 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::MAKEFILE));
}
if(!cleanImportName.empty() &&
cleanImportName != cleanStaticName &&
cleanImportName != cleanSharedSOName &&
cleanImportName != cleanSharedRealName &&
cleanImportName != cleanSharedName)
{
libCleanFiles.push_back(this->Convert(cleanFullImportName.c_str(),
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::MAKEFILE));
}
}
// Add a command to remove any existing files for this library.
std::vector<std::string> commands1;
......@@ -363,6 +383,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
cleanObjs += ")";
// Expand placeholders in the commands.
this->LocalGenerator->m_TargetImplib = targetOutPathImport;
for(std::vector<std::string>::iterator i = commands.begin();
i != commands.end(); ++i)
{
......@@ -375,6 +396,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
targetNameSO.c_str(),
linkFlags.c_str());
}
this->LocalGenerator->m_TargetImplib = "";
// Write the build rule.
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
......
......@@ -809,7 +809,7 @@ const char* cmTarget::GetLocation(const char* config)
m_Location += cfgid;
m_Location += "/";
}
m_Location += this->GetFullName(config);
m_Location += this->GetFullName(config, false);
return m_Location.c_str();
}
......@@ -997,19 +997,17 @@ const char* cmTarget::GetCreateRuleVariable()
return "";
}
const char* cmTarget::GetSuffixVariable()
{
return this->GetSuffixVariableInternal(this->GetType());
}
const char* cmTarget::GetSuffixVariableInternal(TargetType type)
const char* cmTarget::GetSuffixVariableInternal(TargetType type,
bool implib)
{
switch(type)
{
case cmTarget::STATIC_LIBRARY:
return "CMAKE_STATIC_LIBRARY_SUFFIX";
case cmTarget::SHARED_LIBRARY:
return "CMAKE_SHARED_LIBRARY_SUFFIX";
return (implib
? "CMAKE_IMPORT_LIBRARY_SUFFIX"
: "CMAKE_SHARED_LIBRARY_SUFFIX");
case cmTarget::MODULE_LIBRARY:
return "CMAKE_SHARED_MODULE_SUFFIX";
case cmTarget::EXECUTABLE:
......@@ -1023,19 +1021,17 @@ const char* cmTarget::GetSuffixVariableInternal(TargetType type)
}
const char* cmTarget::GetPrefixVariable()
{
return this->GetPrefixVariableInternal(this->GetType());
}
const char* cmTarget::GetPrefixVariableInternal(TargetType type)
const char* cmTarget::GetPrefixVariableInternal(TargetType type,
bool implib)
{
switch(type)
{
case cmTarget::STATIC_LIBRARY:
return "CMAKE_STATIC_LIBRARY_PREFIX";
case cmTarget::SHARED_LIBRARY:
return "CMAKE_SHARED_LIBRARY_PREFIX";
return (implib
? "CMAKE_IMPORT_LIBRARY_PREFIX"
: "CMAKE_SHARED_LIBRARY_PREFIX");
case cmTarget::MODULE_LIBRARY:
return "CMAKE_SHARED_MODULE_PREFIX";
case cmTarget::EXECUTABLE:
......@@ -1048,20 +1044,22 @@ const char* cmTarget::GetPrefixVariableInternal(TargetType type)
}
//----------------------------------------------------------------------------
std::string cmTarget::GetFullName(const char* config)
std::string cmTarget::GetFullName(const char* config, bool implib)
{
return this->GetFullNameInternal(this->GetType(), config);
return this->GetFullNameInternal(this->GetType(), config, implib);
}
//----------------------------------------------------------------------------
void cmTarget::GetFullName(std::string& prefix, std::string& base,
std::string& suffix, const char* config)
std::string& suffix, const char* config,
bool implib)
{
this->GetFullNameInternal(this->GetType(), config, prefix, base, suffix);
this->GetFullNameInternal(this->GetType(), config, implib,
prefix, base, suffix);
}
//----------------------------------------------------------------------------
std::string cmTarget::GetFullPath(const char* config)
std::string cmTarget::GetFullPath(const char* config, bool implib)
{
// Start with the output directory for the target.
std::string fpath = this->GetDirectory();
......@@ -1072,23 +1070,25 @@ std::string cmTarget::GetFullPath(const char* config)
// Add the full name of the target.
fpath += "/";
fpath += this->GetFullName(config);
fpath += this->GetFullName(config, implib);
return fpath;
}
//----------------------------------------------------------------------------
std::string cmTarget::GetFullNameInternal(TargetType type, const char* config)
std::string cmTarget::GetFullNameInternal(TargetType type, const char* config,
bool implib)
{
std::string prefix;
std::string base;
std::string suffix;
this->GetFullNameInternal(type, config, prefix, base, suffix);
this->GetFullNameInternal(type, config, implib, prefix, base, suffix);
return prefix+base+suffix;
}
//----------------------------------------------------------------------------
void cmTarget::GetFullNameInternal(TargetType type,
const char* config,
bool implib,
std::string& outPrefix,
std::string& outBase,
std::string& outSuffix)
......@@ -1105,9 +1105,19 @@ void cmTarget::GetFullNameInternal(TargetType type,
return;
}
// The implib option is only allowed for shared libraries.
if(type != cmTarget::SHARED_LIBRARY)
{
implib = false;
}
// Compute the full name for main target types.
const char* targetPrefix = this->GetProperty("PREFIX");
const char* targetSuffix = this->GetProperty("SUFFIX");
const char* targetPrefix = (implib
? this->GetProperty("IMPORT_PREFIX")
: this->GetProperty("PREFIX"));
const char* targetSuffix = (implib
? this->GetProperty("IMPORT_SUFFIX")
: this->GetProperty("SUFFIX"));
const char* configPostfix = 0;
if(config && *config && type != cmTarget::EXECUTABLE)
{
......@@ -1117,8 +1127,8 @@ void cmTarget::GetFullNameInternal(TargetType type,
configVar = cmSystemTools::UpperCase(configVar);
configPostfix = m_Makefile->GetDefinition(configVar.c_str());
}
const char* prefixVar = this->GetPrefixVariableInternal(type);
const char* suffixVar = this->GetSuffixVariableInternal(type);
const char* prefixVar = this->GetPrefixVariableInternal(type, implib);
const char* suffixVar = this->GetSuffixVariableInternal(type, implib);
const char* ll =
this->GetLinkerLanguage(
m_Makefile->GetLocalGenerator()->GetGlobalGenerator());
......@@ -1173,23 +1183,26 @@ void cmTarget::GetFullNameInternal(TargetType type,
void cmTarget::GetLibraryNames(std::string& name,
std::string& soName,
std::string& realName,
std::string& impName,
const char* config)
{
// Get the names based on the real type of the library.
this->GetLibraryNamesInternal(name, soName, realName, this->GetType(),
config);
this->GetLibraryNamesInternal(name, soName, realName, impName,
this->GetType(), config);
}
void cmTarget::GetLibraryCleanNames(std::string& staticName,
std::string& sharedName,
std::string& sharedSOName,
std::string& sharedRealName,
std::string& importName,
const char* config)
{
// Get the name as if this were a static library.
std::string soName;
std::string realName;
this->GetLibraryNamesInternal(staticName, soName, realName,
std::string impName;
this->GetLibraryNamesInternal(staticName, soName, realName, impName,
cmTarget::STATIC_LIBRARY, config);
// Get the names as if this were a shared library.
......@@ -1200,22 +1213,22 @@ void cmTarget::GetLibraryCleanNames(std::string& staticName,
// shared library will never be present. In the latter case the
// type will never be MODULE. Either way the only names that
// might have to be cleaned are the shared library names.
this->GetLibraryNamesInternal(sharedName, sharedSOName,
sharedRealName, cmTarget::SHARED_LIBRARY,
this->GetLibraryNamesInternal(sharedName, sharedSOName, sharedRealName,
importName, cmTarget::SHARED_LIBRARY,
config);
}
else
{
// Use the name of the real type of the library (shared or module).
this->GetLibraryNamesInternal(sharedName, sharedSOName,
sharedRealName, this->GetType(),
config);
this->GetLibraryNamesInternal(sharedName, sharedSOName, sharedRealName,
importName, this->GetType(), config);
}
}
void cmTarget::GetLibraryNamesInternal(std::string& name,
std::string& soName,
std::string& realName,
std::string& impName,
TargetType type,
const char* config)
{
......@@ -1250,7 +1263,7 @@ void cmTarget::GetLibraryNamesInternal(std::string& name,
}
// The library name.
name = this->GetFullNameInternal(type, config);
name = this->GetFullNameInternal(type, config, false);
// The library's soname.
soName = name;
......@@ -1272,6 +1285,16 @@ void cmTarget::GetLibraryNamesInternal(std::string& name,
realName += ".";
realName += soversion;
}
// The import library name.
if(type == cmTarget::SHARED_LIBRARY)
{
impName = this->GetFullNameInternal(type, config, true);
}
else
{
impName = "";
}
}
void cmTarget::GetExecutableNames(std::string& name,
......@@ -1310,7 +1333,7 @@ void cmTarget::GetExecutableNamesInternal(std::string& name,
#endif
// The executable name.
name = this->GetFullNameInternal(type, config);
name = this->GetFullNameInternal(type, config, false);
// The executable's real name on disk.
realName = name;
......
......@@ -166,26 +166,23 @@ public:
///! Return the rule variable used to create this type of target,
// need to add CMAKE_(LANG) for full name.
const char* GetCreateRuleVariable();
///! Return the name of the variable to look up the target suffix
const char* GetSuffixVariable();
///! Return the name of the variable to look up the target suffix
const char* GetPrefixVariable();
/** Get the full name of the target according to the settings in its
makefile. */
std::string GetFullName(const char* config=0);
std::string GetFullName(const char* config=0, bool implib = false);
void GetFullName(std::string& prefix, std::string& base, std::string& suffix,
const char* config=0);
const char* config=0, bool implib = false);
/** Get the full path to the target according to the settings in its
makefile and the configuration type. */
std::string GetFullPath(const char* config=0);
std::string GetFullPath(const char* config=0, bool implib = false);
/** Get the names of the library needed to generate a build rule
that takes into account shared library version numbers. This
should be called only on a library target. */
void GetLibraryNames(std::string& name, std::string& soName,
std::string& realName, const char* config);
std::string& realName, std::string& impName,
const char* config);
/** Get the names of the library used to remove existing copies of
the library from the build tree either before linking or during
......@@ -195,6 +192,7 @@ public:
std::string& sharedName,
std::string& sharedSOName,
std::string& sharedRealName,
std::string& importName,
const char* config);
/** Get the names of the executable needed to generate a build rule
......@@ -272,15 +270,17 @@ private:
void GatherDependencies( const cmMakefile& mf, const std::string& lib,
DependencyMap& dep_map );
const char* GetSuffixVariableInternal(TargetType type);
const char* GetPrefixVariableInternal(TargetType type);
std::string GetFullNameInternal(TargetType type, const char* config);
void GetFullNameInternal(TargetType type, const char* config,
const char* GetSuffixVariableInternal(TargetType type, bool implib);
const char* GetPrefixVariableInternal(TargetType type, bool implib);
std::string GetFullNameInternal(TargetType type, const char* config,
bool implib);
void GetFullNameInternal(TargetType type, const char* config, bool implib,
std::string& outPrefix, std::string& outBase,
std::string& outSuffix);
void GetLibraryNamesInternal(std::string& name,
std::string& soName,
std::string& realName,
std::string& impName,
TargetType type,
const char* config);
void GetExecutableNamesInternal(std::string& name,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment