diff --git a/.gitattributes b/.gitattributes index d9d64d639d..d21f1dda0e 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/CMakeCInformation.cmake b/Modules/CMakeCInformation.cmake index 9285fefb25..6b5efba9d0 100644 --- a/Modules/CMakeCInformation.cmake +++ b/Modules/CMakeCInformation.cmake @@ -68,6 +68,12 @@ IF (NOT _INCLUDED_FILE) INCLUDE(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL) ENDIF (NOT _INCLUDED_FILE) +IF(CMAKE_C_SIZEOF_DATA_PTR) + FOREACH(f ${CMAKE_C_ABI_FILES}) + INCLUDE(${f}) + ENDFOREACH() + UNSET(CMAKE_C_ABI_FILES) +ENDIF() # This should be included before the _INIT variables are # used to initialize the cache. Since the rule variables diff --git a/Modules/CMakeCXXInformation.cmake b/Modules/CMakeCXXInformation.cmake index 620de634e7..b97a69c3bf 100644 --- a/Modules/CMakeCXXInformation.cmake +++ b/Modules/CMakeCXXInformation.cmake @@ -67,6 +67,12 @@ IF (NOT _INCLUDED_FILE) INCLUDE(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL) ENDIF (NOT _INCLUDED_FILE) +IF(CMAKE_CXX_SIZEOF_DATA_PTR) + FOREACH(f ${CMAKE_CXX_ABI_FILES}) + INCLUDE(${f}) + ENDFOREACH() + UNSET(CMAKE_CXX_ABI_FILES) +ENDIF() # This should be included before the _INIT variables are # used to initialize the cache. Since the rule variables diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake index a808a284dc..1c9899e64d 100644 --- a/Modules/CMakeDetermineCompilerABI.cmake +++ b/Modules/CMakeDetermineCompilerABI.cmake @@ -57,6 +57,8 @@ FUNCTION(CMAKE_DETERMINE_COMPILER_ABI lang src) IF(ABI_SIZEOF_DPTR) SET(CMAKE_${lang}_SIZEOF_DATA_PTR "${ABI_SIZEOF_DPTR}" PARENT_SCOPE) + ELSEIF(CMAKE_${lang}_SIZEOF_DATA_PTR_DEFAULT) + SET(CMAKE_${lang}_SIZEOF_DATA_PTR "${CMAKE_${lang}_SIZEOF_DATA_PTR_DEFAULT}" PARENT_SCOPE) ENDIF(ABI_SIZEOF_DPTR) IF(ABI_NAME) diff --git a/Modules/CMakeFortranCompilerABI.F b/Modules/CMakeFortranCompilerABI.F index b8efb426e0..7e24553fb1 100644 --- a/Modules/CMakeFortranCompilerABI.F +++ b/Modules/CMakeFortranCompilerABI.F @@ -15,6 +15,11 @@ PRINT *, 'INFO:sizeof_dptr[4]' #elif defined(_M_IX86) PRINT *, 'INFO:sizeof_dptr[4]' + +#elif defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 8 + PRINT *, 'INFO:sizeof_dptr[8]' +#elif defined(__SIZEOF_POINTER__) && __SIZEOF_POINTER__ == 4 + PRINT *, 'INFO:sizeof_dptr[4]' #endif #if 0 diff --git a/Modules/CMakeFortranInformation.cmake b/Modules/CMakeFortranInformation.cmake index dc15e556e7..aed1fd2df6 100644 --- a/Modules/CMakeFortranInformation.cmake +++ b/Modules/CMakeFortranInformation.cmake @@ -44,6 +44,12 @@ IF (NOT _INCLUDED_FILE) INCLUDE(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL) ENDIF (NOT _INCLUDED_FILE) +IF(CMAKE_Fortran_SIZEOF_DATA_PTR) + FOREACH(f ${CMAKE_Fortran_ABI_FILES}) + INCLUDE(${f}) + ENDFOREACH() + UNSET(CMAKE_Fortran_ABI_FILES) +ENDIF() # This should be included before the _INIT variables are # used to initialize the cache. Since the rule variables diff --git a/Modules/CMakeTestCCompiler.cmake b/Modules/CMakeTestCCompiler.cmake index 038c2fd47f..4d4e35fcc1 100644 --- a/Modules/CMakeTestCCompiler.cmake +++ b/Modules/CMakeTestCCompiler.cmake @@ -76,5 +76,11 @@ ELSE(NOT CMAKE_C_COMPILER_WORKS) ) INCLUDE(${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeCCompiler.cmake) ENDIF(CMAKE_C_COMPILER_FORCED) + IF(CMAKE_C_SIZEOF_DATA_PTR) + FOREACH(f ${CMAKE_C_ABI_FILES}) + INCLUDE(${f}) + ENDFOREACH() + UNSET(CMAKE_C_ABI_FILES) + ENDIF() ENDIF(NOT CMAKE_C_COMPILER_WORKS) diff --git a/Modules/CMakeTestCXXCompiler.cmake b/Modules/CMakeTestCXXCompiler.cmake index c1a3b3a10f..494add371a 100644 --- a/Modules/CMakeTestCXXCompiler.cmake +++ b/Modules/CMakeTestCXXCompiler.cmake @@ -69,4 +69,10 @@ ELSE(NOT CMAKE_CXX_COMPILER_WORKS) ) INCLUDE(${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeCXXCompiler.cmake) ENDIF(CMAKE_CXX_COMPILER_FORCED) + IF(CMAKE_CXX_SIZEOF_DATA_PTR) + FOREACH(f ${CMAKE_CXX_ABI_FILES}) + INCLUDE(${f}) + ENDFOREACH() + UNSET(CMAKE_CXX_ABI_FILES) + ENDIF() ENDIF(NOT CMAKE_CXX_COMPILER_WORKS) diff --git a/Modules/CMakeTestFortranCompiler.cmake b/Modules/CMakeTestFortranCompiler.cmake index 33f62eb50b..b4dcea634e 100644 --- a/Modules/CMakeTestFortranCompiler.cmake +++ b/Modules/CMakeTestFortranCompiler.cmake @@ -92,4 +92,10 @@ ELSE(NOT CMAKE_Fortran_COMPILER_WORKS) ) INCLUDE(${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeFortranCompiler.cmake) ENDIF(CMAKE_Fortran_COMPILER_FORCED) + IF(CMAKE_Fortran_SIZEOF_DATA_PTR) + FOREACH(f ${CMAKE_Fortran_ABI_FILES}) + INCLUDE(${f}) + ENDFOREACH() + UNSET(CMAKE_Fortran_ABI_FILES) + ENDIF() ENDIF(NOT CMAKE_Fortran_COMPILER_WORKS) diff --git a/Modules/Platform/GNUtoMS_lib.bat.in b/Modules/Platform/GNUtoMS_lib.bat.in new file mode 100644 index 0000000000..2da920ab00 --- /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 0000000000..ca9b0f8da9 --- /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 0000000000..1189263fad --- /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 0000000000..f3c701c3c0 --- /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 0000000000..179280b4d8 --- /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-Fortran.cmake b/Modules/Platform/Windows-GNU-Fortran.cmake index c66feedbb3..b81b79679d 100644 --- a/Modules/Platform/Windows-GNU-Fortran.cmake +++ b/Modules/Platform/Windows-GNU-Fortran.cmake @@ -1,2 +1,5 @@ include(Platform/Windows-GNU) __windows_compiler_gnu(Fortran) + +# gfortran on 64-bit MinGW defines __SIZEOF_POINTER__ +set(CMAKE_Fortran_SIZEOF_DATA_PTR_DEFAULT 4) diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake index 1d3e4b5a92..c255d6bafd 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 " -o -Wl,--out-implib, ${CMAKE_GNULD_IMAGE_VERSION} ") + 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,.def" + " -Dlib=\"${CMAKE_GNUtoMS_LIB}\" -Ddef=\".def\" -Ddll=\"\" -Dimp=\"\" -P \"${CMAKE_ROOT}/Modules/Platform/GNUtoMS_lib.cmake\"" + ) + endif() +endmacro() diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index ed303c9c64..c8c83b9c11 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -1111,6 +1111,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm) false, "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__POSTFIX.", @@ -1515,6 +1524,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE__COMPILER_ID_RUN", cmProperty::VARIABLE,0,0); + cm->DefineProperty("CMAKE__ABI_FILES", + cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE__CREATE_ASSEMBLY_SOURCE", cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE__CREATE_PREPROCESSED_SOURCE", diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 7e73e36599..32595ee4b2 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 33ffbfb3ce..ac1c949443 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 cd75d7977c..78278cbbfa 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 @@ -270,8 +277,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) std::string linkRuleVar = "CMAKE_"; linkRuleVar += linkLanguage; linkRuleVar += "_LINK_EXECUTABLE"; - std::string linkRule = - this->Makefile->GetRequiredDefinition(linkRuleVar.c_str()); + std::string linkRule = this->GetLinkRule(linkRuleVar.c_str()); std::vector commands1; cmSystemTools::ExpandListArgument(linkRule, real_link_commands); if(this->Target->IsExecutableWithExports()) diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 31f7be5cf9..b4174cc36d 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 @@ -772,7 +779,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules else { // Get the set of commands. - std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar); + std::string linkRule = this->GetLinkRule(linkRuleVar); cmSystemTools::ExpandListArgument(linkRule, real_link_commands); // Expand placeholders. diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 8b91194005..a3a832bc88 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1633,6 +1633,23 @@ 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; +} + //---------------------------------------------------------------------------- void cmMakefileTargetGenerator ::CloseFileStreams() diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 674cd1306e..8fba13f6e4 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -120,6 +120,9 @@ protected: // Append link rule dependencies (objects, etc.). void AppendLinkDepends(std::vector& depends); + // Lookup the link rule for this target. + std::string GetLinkRule(const char* linkRuleVar); + /** In order to support parallel builds for custom commands with multiple outputs the outputs are given a serial order, and only the first output actually has the build rule. Other outputs diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 7e02a39b74..87f8c5e861 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -971,6 +971,23 @@ void cmTarget::DefineProperties(cmake *cm) "If the variable CMAKE_Fortran_MODULE_DIRECTORY is set when a target " "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_", cmProperty::TARGET, "Set Xcode target attributes directly.", @@ -1210,6 +1227,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); @@ -3471,6 +3489,26 @@ void cmTarget::GetExecutableNames(std::string& name, pdbName = prefix+base+".pdb"; } +//---------------------------------------------------------------------------- +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) { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 0abdddb0a8..09fee6c9b2 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); diff --git a/Tests/ExportImport/CMakeLists.txt b/Tests/ExportImport/CMakeLists.txt index 2e01c50670..ccfb8940c1 100644 --- a/Tests/ExportImport/CMakeLists.txt +++ b/Tests/ExportImport/CMakeLists.txt @@ -22,6 +22,11 @@ else(CMAKE_CONFIGURATION_TYPES) endif(CMAKE_BUILD_TYPE) endif(CMAKE_CONFIGURATION_TYPES) +if(MINGW OR MSYS) + # Test CMAKE_GNUtoMS whether we have VS or not. + set(ExportImport_GNUtoMS 1) +endif() + configure_file(${ExportImport_SOURCE_DIR}/InitialCache.cmake.in ${ExportImport_BINARY_DIR}/InitialCache.cmake @ONLY) diff --git a/Tests/ExportImport/InitialCache.cmake.in b/Tests/ExportImport/InitialCache.cmake.in index f920b1f947..4893f70208 100644 --- a/Tests/ExportImport/InitialCache.cmake.in +++ b/Tests/ExportImport/InitialCache.cmake.in @@ -12,3 +12,4 @@ SET(CMAKE_CXX_FLAGS_MINSIZEREL "@CMAKE_CXX_FLAGS_MINSIZEREL@" CACHE STRING "C++ SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "@CMAKE_CXX_FLAGS_RELWITHDEBINFO@" CACHE STRING "C++ Flags") SET(CMAKE_INSTALL_PREFIX "@ExportImport_BINARY_DIR@/Root" CACHE STRING "Installation Prefix") SET(CMAKE_SKIP_RPATH ON CACHE BOOL "No RPATH") +SET(CMAKE_GNUtoMS "@ExportImport_GNUtoMS@" CACHE BOOL "CMAKE_GNUtoMS")