diff options
27 files changed, 242 insertions, 5 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/CMakeCInformation.cmake b/Modules/CMakeCInformation.cmake index 9285fef..6b5efba 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 620de63..b97a69c 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 a808a28..1c9899e 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 b8efb42..7e24553 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 dc15e55..aed1fd2 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 038c2fd..4d4e35f 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 c1a3b3a..494add3 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 33f62eb..b4dcea6 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 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-Fortran.cmake b/Modules/Platform/Windows-GNU-Fortran.cmake index c66feed..b81b796 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 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 ed303c9..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 " @@ -1515,6 +1524,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm) cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE_<LANG>_COMPILER_ID_RUN", cmProperty::VARIABLE,0,0); + cm->DefineProperty("CMAKE_<LANG>_ABI_FILES", + cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE_<LANG>_CREATE_ASSEMBLY_SOURCE", cmProperty::VARIABLE,0,0); cm->DefineProperty("CMAKE_<LANG>_CREATE_PREPROCESSED_SOURCE", 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 cd75d79..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 @@ -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<std::string> commands1; cmSystemTools::ExpandListArgument(linkRule, real_link_commands); if(this->Target->IsExecutableWithExports()) diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 31f7be5..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 @@ -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 8b91194..a3a832b 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1634,6 +1634,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 674cd13..8fba13f 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -120,6 +120,9 @@ protected: // Append link rule dependencies (objects, etc.). void AppendLinkDepends(std::vector<std::string>& 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 7e02a39..87f8c5e 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -972,6 +972,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 " @@ -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); @@ -3472,6 +3490,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); diff --git a/Tests/ExportImport/CMakeLists.txt b/Tests/ExportImport/CMakeLists.txt index 2e01c50..ccfb894 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 f920b1f..4893f70 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") |