summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitattributes1
-rw-r--r--Modules/Platform/GNUtoMS_lib.bat.in3
-rw-r--r--Modules/Platform/GNUtoMS_lib.cmake10
-rw-r--r--Modules/Platform/Windows-GNU-C-ABI.cmake1
-rw-r--r--Modules/Platform/Windows-GNU-CXX-ABI.cmake1
-rw-r--r--Modules/Platform/Windows-GNU-Fortran-ABI.cmake1
-rw-r--r--Modules/Platform/Windows-GNU.cmake54
-rw-r--r--Source/cmDocumentVariables.cxx9
-rw-r--r--Source/cmExportBuildFileGenerator.cxx2
-rw-r--r--Source/cmInstallTargetGenerator.cxx26
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx7
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx7
-rw-r--r--Source/cmMakefileTargetGenerator.cxx10
-rw-r--r--Source/cmTarget.cxx38
-rw-r--r--Source/cmTarget.h8
15 files changed, 176 insertions, 2 deletions
diff --git a/.gitattributes b/.gitattributes
index d9d64d6..d21f1dd 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -8,6 +8,7 @@ configure crlf=input
*.sh.in crlf=input
*.bat -crlf
+*.bat.in -crlf
*.dsp -crlf
*.dsptemplate -crlf
*.dsw -crlf
diff --git a/Modules/Platform/GNUtoMS_lib.bat.in b/Modules/Platform/GNUtoMS_lib.bat.in
new file mode 100644
index 0000000..2da920a
--- /dev/null
+++ b/Modules/Platform/GNUtoMS_lib.bat.in
@@ -0,0 +1,3 @@
+@echo off
+call "@CMAKE_GNUtoMS_BAT@"
+lib /machine:"@CMAKE_GNUtoMS_ARCH@" %*
diff --git a/Modules/Platform/GNUtoMS_lib.cmake b/Modules/Platform/GNUtoMS_lib.cmake
new file mode 100644
index 0000000..ca9b0f8
--- /dev/null
+++ b/Modules/Platform/GNUtoMS_lib.cmake
@@ -0,0 +1,10 @@
+# Usage: cmake -Dlib=lib.bat -Ddef=out.def -Ddll=out.dll -Dimp=out.dll.a -P GNUtoMS_lib.cmake
+get_filename_component(name ${dll} NAME) # .dll file name
+string(REGEX REPLACE "\\.dll\\.a$" ".lib" out "${imp}") # .dll.a -> .lib
+execute_process(
+ COMMAND ${lib} /def:${def} /name:${name} /out:${out}
+ RESULT_VARIABLE res
+ )
+if(res)
+ message(FATAL_ERROR "lib failed: ${res}")
+endif()
diff --git a/Modules/Platform/Windows-GNU-C-ABI.cmake b/Modules/Platform/Windows-GNU-C-ABI.cmake
new file mode 100644
index 0000000..1189263
--- /dev/null
+++ b/Modules/Platform/Windows-GNU-C-ABI.cmake
@@ -0,0 +1 @@
+__windows_compiler_gnu_abi(C)
diff --git a/Modules/Platform/Windows-GNU-CXX-ABI.cmake b/Modules/Platform/Windows-GNU-CXX-ABI.cmake
new file mode 100644
index 0000000..f3c701c
--- /dev/null
+++ b/Modules/Platform/Windows-GNU-CXX-ABI.cmake
@@ -0,0 +1 @@
+__windows_compiler_gnu_abi(CXX)
diff --git a/Modules/Platform/Windows-GNU-Fortran-ABI.cmake b/Modules/Platform/Windows-GNU-Fortran-ABI.cmake
new file mode 100644
index 0000000..179280b
--- /dev/null
+++ b/Modules/Platform/Windows-GNU-Fortran-ABI.cmake
@@ -0,0 +1 @@
+__windows_compiler_gnu_abi(Fortran)
diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake
index 1d3e4b5..c255d6b 100644
--- a/Modules/Platform/Windows-GNU.cmake
+++ b/Modules/Platform/Windows-GNU.cmake
@@ -108,6 +108,8 @@ macro(__windows_compiler_gnu lang)
set(CMAKE_${lang}_LINK_EXECUTABLE
"<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Wl,--out-implib,<TARGET_IMPLIB> ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES>")
+ list(APPEND CMAKE_${lang}_ABI_FILES "Platform/Windows-GNU-${lang}-ABI")
+
# Support very long lists of object files.
if("${CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG}" STREQUAL "@")
foreach(rule CREATE_SHARED_MODULE CREATE_SHARED_LIBRARY LINK_EXECUTABLE)
@@ -125,3 +127,55 @@ macro(__windows_compiler_gnu lang)
endforeach()
endif()
endmacro()
+
+macro(__windows_compiler_gnu_abi lang)
+ if(CMAKE_NO_GNUtoMS)
+ set(CMAKE_GNUtoMS 0)
+ else()
+ option(CMAKE_GNUtoMS "Convert GNU import libraries to MS format (requires Visual Studio)" OFF)
+ endif()
+
+ if(CMAKE_GNUtoMS AND NOT CMAKE_GNUtoMS_LIB)
+ # Find MS development environment setup script for this architecture.
+ if("${CMAKE_SIZEOF_VOID_P}" EQUAL 4)
+ find_program(CMAKE_GNUtoMS_VCVARS NAMES vcvars32.bat
+ DOC "Visual Studio vcvars32.bat"
+ PATHS
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\11.0\\Setup\\VC;ProductDir]/bin"
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0\\Setup\\VC;ProductDir]/bin"
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\9.0\\Setup\\VC;ProductDir]/bin"
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\Setup\\VC;ProductDir]/bin"
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\7.1\\Setup\\VC;ProductDir]/bin"
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\6.0\\Setup\\Microsoft Visual C++;ProductDir]/bin"
+ )
+ set(CMAKE_GNUtoMS_ARCH x86)
+ elseif("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
+ find_program(CMAKE_GNUtoMS_VCVARS NAMES vcvarsamd64.bat
+ DOC "Visual Studio vcvarsamd64.bat"
+ PATHS
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\11.0\\Setup\\VC;ProductDir]/bin/amd64"
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0\\Setup\\VC;ProductDir]/bin/amd64"
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\9.0\\Setup\\VC;ProductDir]/bin/amd64"
+ "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\Setup\\VC;ProductDir]/bin/amd64"
+ )
+ set(CMAKE_GNUtoMS_ARCH amd64)
+ endif()
+ set_property(CACHE CMAKE_GNUtoMS_VCVARS PROPERTY ADVANCED 1)
+ if(CMAKE_GNUtoMS_VCVARS)
+ # Create helper script to run lib.exe from MS environment.
+ string(REPLACE "/" "\\" CMAKE_GNUtoMS_BAT "${CMAKE_GNUtoMS_VCVARS}")
+ set(CMAKE_GNUtoMS_LIB ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeGNUtoMS_lib.bat)
+ configure_file(${CMAKE_ROOT}/Modules/Platform/GNUtoMS_lib.bat.in ${CMAKE_GNUtoMS_LIB})
+ else()
+ message(WARNING "Disabling CMAKE_GNUtoMS option because CMAKE_GNUtoMS_VCVARS is not set.")
+ set(CMAKE_GNUtoMS 0)
+ endif()
+ endif()
+
+ if(CMAKE_GNUtoMS)
+ # Teach CMake how to create a MS import library at link time.
+ set(CMAKE_${lang}_GNUtoMS_RULE " -Wl,--output-def,<TARGET_NAME>.def"
+ "<CMAKE_COMMAND> -Dlib=\"${CMAKE_GNUtoMS_LIB}\" -Ddef=\"<TARGET_NAME>.def\" -Ddll=\"<TARGET>\" -Dimp=\"<TARGET_IMPLIB>\" -P \"${CMAKE_ROOT}/Modules/Platform/GNUtoMS_lib.cmake\""
+ )
+ endif()
+endmacro()
diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
index 7da07f8..c8c83b9 100644
--- a/Source/cmDocumentVariables.cxx
+++ b/Source/cmDocumentVariables.cxx
@@ -1112,6 +1112,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"Variables that Control the Build");
cm->DefineProperty
+ ("CMAKE_GNUtoMS", cmProperty::VARIABLE,
+ "Convert GNU import libraries (.dll.a) to MS format (.lib).",
+ "This variable is used to initialize the GNUtoMS property on targets "
+ "when they are created. "
+ "See that target property for additional information.",
+ false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
("CMAKE_DEBUG_POSTFIX", cmProperty::VARIABLE,
"See variable CMAKE_<CONFIG>_POSTFIX.",
"This variable is a special case of the more-general "
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index 7e73e36..32595ee 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -125,6 +125,8 @@ cmExportBuildFileGenerator
std::string prop = "IMPORTED_IMPLIB";
prop += suffix;
std::string value = target->GetFullPath(config, true);
+ target->GetImplibGNUtoMS(value, value,
+ "${CMAKE_IMPORT_LIBRARY_SUFFIX}");
properties[prop] = value;
}
}
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 33ffbfb..ac1c949 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -101,6 +101,13 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
std::string to1 = toDir + targetNameImport;
filesFrom.push_back(from1);
filesTo.push_back(to1);
+ std::string targetNameImportLib;
+ if(this->Target->GetImplibGNUtoMS(targetNameImport,
+ targetNameImportLib))
+ {
+ filesFrom.push_back(fromDirConfig + targetNameImportLib);
+ filesTo.push_back(toDir + targetNameImportLib);
+ }
// An import library looks like a static library.
type = cmTarget::STATIC_LIBRARY;
@@ -157,6 +164,13 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
std::string to1 = toDir + targetNameImport;
filesFrom.push_back(from1);
filesTo.push_back(to1);
+ std::string targetNameImportLib;
+ if(this->Target->GetImplibGNUtoMS(targetNameImport,
+ targetNameImportLib))
+ {
+ filesFrom.push_back(fromDirConfig + targetNameImportLib);
+ filesTo.push_back(toDir + targetNameImportLib);
+ }
// An import library looks like a static library.
type = cmTarget::STATIC_LIBRARY;
@@ -314,7 +328,11 @@ std::string cmInstallTargetGenerator::GetInstallFilename(cmTarget* target,
if(nameType == NameImplib)
{
// Use the import library name.
- fname = targetNameImport;
+ if(!target->GetImplibGNUtoMS(targetNameImport, fname,
+ "${CMAKE_IMPORT_LIBRARY_SUFFIX}"))
+ {
+ fname = targetNameImport;
+ }
}
else if(nameType == NameReal)
{
@@ -339,7 +357,11 @@ std::string cmInstallTargetGenerator::GetInstallFilename(cmTarget* target,
if(nameType == NameImplib)
{
// Use the import library name.
- fname = targetNameImport;
+ if(!target->GetImplibGNUtoMS(targetNameImport, fname,
+ "${CMAKE_IMPORT_LIBRARY_SUFFIX}"))
+ {
+ fname = targetNameImport;
+ }
}
else if(nameType == NameSO)
{
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 0fcd269..78278cb 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -241,6 +241,13 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
exeCleanFiles.push_back(this->Convert(targetFullPathImport.c_str(),
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::UNCHANGED));
+ std::string implib;
+ if(this->Target->GetImplibGNUtoMS(targetFullPathImport, implib))
+ {
+ exeCleanFiles.push_back(this->Convert(implib.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::UNCHANGED));
+ }
}
// List the PDB for cleaning only when the whole target is
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 337b286..b4174cc 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -512,6 +512,13 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
libCleanFiles.push_back(this->Convert(targetFullPathImport.c_str(),
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::UNCHANGED));
+ std::string implib;
+ if(this->Target->GetImplibGNUtoMS(targetFullPathImport, implib))
+ {
+ libCleanFiles.push_back(this->Convert(implib.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::UNCHANGED));
+ }
}
// List the PDB for cleaning only when the whole target is
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 004e780..a3a832b 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -1637,6 +1637,16 @@ void cmMakefileTargetGenerator
std::string cmMakefileTargetGenerator::GetLinkRule(const char* linkRuleVar)
{
std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
+ if(this->Target->HasImplibGNUtoMS())
+ {
+ std::string ruleVar = "CMAKE_";
+ ruleVar += this->Target->GetLinkerLanguage(this->ConfigName);
+ ruleVar += "_GNUtoMS_RULE";
+ if(const char* rule = this->Makefile->GetDefinition(ruleVar.c_str()))
+ {
+ linkRule += rule;
+ }
+ }
return linkRule;
}
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index dad0353..48368de 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -980,6 +980,23 @@ void cmTarget::DefineProperties(cmake *cm)
"is created its value is used to initialize this property.");
cm->DefineProperty
+ ("GNUtoMS", cmProperty::TARGET,
+ "Convert GNU import library (.dll.a) to MS format (.lib).",
+ "When linking a shared library or executable that exports symbols "
+ "using GNU tools on Windows (MinGW/MSYS) with Visual Studio installed "
+ "convert the import library (.dll.a) from GNU to MS format (.lib). "
+ "Both import libraries will be installed by install(TARGETS) and "
+ "exported by install(EXPORT) and export() to be linked by applications "
+ "with either GNU- or MS-compatible tools."
+ "\n"
+ "If the variable CMAKE_GNUtoMS is set when a target "
+ "is created its value is used to initialize this property. "
+ "The variable must be set prior to the first command that enables "
+ "a language such as project() or enable_language(). "
+ "CMake provides the variable as an option to the user automatically "
+ "when configuring on Windows with GNU tools.");
+
+ cm->DefineProperty
("XCODE_ATTRIBUTE_<an-attribute>", cmProperty::TARGET,
"Set Xcode target attributes directly.",
"Tell the Xcode generator to set '<an-attribute>' to a given value "
@@ -1195,6 +1212,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0);
this->SetPropertyDefault("Fortran_FORMAT", 0);
this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0);
+ this->SetPropertyDefault("GNUtoMS", 0);
this->SetPropertyDefault("OSX_ARCHITECTURES", 0);
this->SetPropertyDefault("AUTOMOC", 0);
this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", 0);
@@ -3457,6 +3475,26 @@ void cmTarget::GetExecutableNames(std::string& name,
}
//----------------------------------------------------------------------------
+bool cmTarget::HasImplibGNUtoMS()
+{
+ return this->HasImportLibrary() && this->GetPropertyAsBool("GNUtoMS");
+}
+
+//----------------------------------------------------------------------------
+bool cmTarget::GetImplibGNUtoMS(std::string const& gnuName,
+ std::string& out, const char* newExt)
+{
+ if(this->HasImplibGNUtoMS() &&
+ gnuName.size() > 6 && gnuName.substr(gnuName.size()-6) == ".dll.a")
+ {
+ out = gnuName.substr(0, gnuName.size()-6);
+ out += newExt? newExt : ".lib";
+ return true;
+ }
+ return false;
+}
+
+//----------------------------------------------------------------------------
void cmTarget::GenerateTargetManifest(const char* config)
{
cmMakefile* mf = this->Makefile;
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 0abdddb..09fee6c 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -369,6 +369,14 @@ public:
std::string& impName,
std::string& pdbName, const char* config);
+ /** Does this target have a GNU implib to convert to MS format? */
+ bool HasImplibGNUtoMS();
+
+ /** Convert the given GNU import library name (.dll.a) to a name with a new
+ extension (.lib or ${CMAKE_IMPORT_LIBRARY_SUFFIX}). */
+ bool GetImplibGNUtoMS(std::string const& gnuName, std::string& out,
+ const char* newExt = 0);
+
/** Add the target output files to the global generator manifest. */
void GenerateTargetManifest(const char* config);