diff --git a/Modules/Platform/Windows-bcc32.cmake b/Modules/Platform/Windows-bcc32.cmake index 82fa064f9..382bf2d25 100644 --- a/Modules/Platform/Windows-bcc32.cmake +++ b/Modules/Platform/Windows-bcc32.cmake @@ -26,6 +26,11 @@ SET(CMAKE_FIND_LIBRARY_SUFFIXES "-bcc.lib" ".lib") # Borland cannot handle + in the file name, so mangle object file name SET (CMAKE_MANGLE_OBJECT_FILE_NAMES "ON") +# Create an import library for another target. +SET(CMAKE_CXX_CREATE_IMPORT_LIBRARY + "implib -c -w " + ) + # Create a C++ module library. SET(CMAKE_CXX_CREATE_SHARED_MODULE " ${CMAKE_START_TEMP_FILE}-e -tWD -tWR ${CMAKE_END_TEMP_FILE}" @@ -33,9 +38,12 @@ SET(CMAKE_CXX_CREATE_SHARED_MODULE # Create a C++ shared library. # First create a module and then its import library. -SET(CMAKE_CXX_CREATE_SHARED_LIBRARY ${CMAKE_CXX_CREATE_SHARED_MODULE} - "implib -c -w " - ) +SET(CMAKE_CXX_CREATE_SHARED_LIBRARY + ${CMAKE_CXX_CREATE_SHARED_MODULE} + ${CMAKE_CXX_CREATE_IMPORT_LIBRARY}) + +# Create an import library for another target. +SET(CMAKE_C_CREATE_IMPORT_LIBRARY ${CMAKE_CXX_CREATE_IMPORT_LIBRARY}) # Create a C module library. SET(CMAKE_C_CREATE_SHARED_MODULE @@ -44,9 +52,9 @@ SET(CMAKE_C_CREATE_SHARED_MODULE # Create a C shared library. # First create a module and then its import library. -SET(CMAKE_C_CREATE_SHARED_LIBRARY ${CMAKE_C_CREATE_SHARED_MODULE} - "implib -c -w " - ) +SET(CMAKE_C_CREATE_SHARED_LIBRARY + ${CMAKE_C_CREATE_SHARED_MODULE} + ${CMAKE_C_CREATE_IMPORT_LIBRARY}) # create a C++ static library SET(CMAKE_CXX_CREATE_STATIC_LIBRARY "tlib ${CMAKE_START_TEMP_FILE}/p512 /a ${CMAKE_END_TEMP_FILE}") diff --git a/Modules/Platform/Windows-wcl386.cmake b/Modules/Platform/Windows-wcl386.cmake index f56e148aa..acec459dd 100644 --- a/Modules/Platform/Windows-wcl386.cmake +++ b/Modules/Platform/Windows-wcl386.cmake @@ -25,6 +25,10 @@ SET (CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-br -bm -ot -dNDEBUG") SET (CMAKE_C_STANDARD_LIBRARIES_INIT "library clbrdll.lib library plbrdll.lib library kernel32.lib library user32.lib library gdi32.lib library winspool.lib library comdlg32.lib library advapi32.lib library shell32.lib library ole32.lib library oleaut32.lib library uuid.lib library odbc32.lib library odbccp32.lib") SET (CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}") +SET(CMAKE_C_CREATE_IMPORT_LIBRARY + "wlib -q -n -b +") +SET(CMAKE_CXX_CREATE_IMPORT_LIBRARY ${CMAKE_C_CREATE_IMPORT_LIBRARY}) + SET(CMAKE_C_LINK_EXECUTABLE "wlink ${CMAKE_START_TEMP_FILE} ${CMAKE_WLINK_QUIET} name option caseexact file {} ${CMAKE_END_TEMP_FILE}") @@ -39,9 +43,10 @@ SET(CMAKE_C_COMPILE_OBJECT " ${CMAKE_START_TEMP_FILE} ${CMAKE_WCL_QUIET} -dWIN32 -fo -c -cc ${CMAKE_END_TEMP_FILE}") SET(CMAKE_CXX_CREATE_SHARED_MODULE - "wlink ${CMAKE_START_TEMP_FILE} system nt_dll ${CMAKE_WLINK_QUIET} name option caseexact file {} ") -SET(CMAKE_CXX_CREATE_SHARED_LIBRARY ${CMAKE_CXX_CREATE_SHARED_MODULE} - "wlib -q -n -b + ${CMAKE_END_TEMP_FILE}") + "wlink ${CMAKE_START_TEMP_FILE} system nt_dll ${CMAKE_WLINK_QUIET} name option caseexact file {} ${CMAKE_END_TEMP_FILE}") +SET(CMAKE_CXX_CREATE_SHARED_LIBRARY + ${CMAKE_CXX_CREATE_SHARED_MODULE} + ${CMAKE_CXX_CREATE_IMPORT_LIBRARY}) # create a C shared library SET(CMAKE_C_CREATE_SHARED_LIBRARY ${CMAKE_CXX_CREATE_SHARED_LIBRARY}) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 71d3c51b9..c7f50f6e3 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1659,9 +1659,19 @@ void cmLocalGenerator { // Compute the proper name to use to link this library. cmTarget* tgt = this->GlobalGenerator->FindTarget(0, lib.c_str()); - if(tgt && (tgt->GetType() == cmTarget::STATIC_LIBRARY || - tgt->GetType() == cmTarget::SHARED_LIBRARY || - tgt->GetType() == cmTarget::MODULE_LIBRARY)) + bool impexe = (tgt && + tgt->GetType() == cmTarget::EXECUTABLE && + tgt->GetPropertyAsBool("ENABLE_EXPORTS")); + if(impexe && !implib) + { + // Skip linking to executables on platforms with no import + // libraries. + continue; + } + else if(tgt && (tgt->GetType() == cmTarget::STATIC_LIBRARY || + tgt->GetType() == cmTarget::SHARED_LIBRARY || + tgt->GetType() == cmTarget::MODULE_LIBRARY || + impexe)) { // This is a CMake target. Ask the target for its real name. // Pass the full path to the target file but purposely leave diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 78b44a407..e5dc29b60 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -944,13 +944,16 @@ void cmMakefile::AddLinkLibraryForTarget(const char *target, } // if it is not a static or shared library then you can not link to it if(!((tgt->GetType() == cmTarget::STATIC_LIBRARY) || - (tgt->GetType() == cmTarget::SHARED_LIBRARY))) + (tgt->GetType() == cmTarget::SHARED_LIBRARY) || + (tgt->GetType() == cmTarget::EXECUTABLE && + tgt->GetPropertyAsBool("ENABLE_EXPORTS")))) { cmOStringStream e; e << "Attempt to add link target " << lib << " of type: " << cmTarget::TargetTypeNames[static_cast(tgt->GetType())] << "\nto target " << target - << ". You can only link to STATIC or SHARED libraries."; + << ". One can only link to STATIC or SHARED libraries, or " + << "to executables with the ENABLE_EXPORTS property set."; // in older versions of cmake linking to modules was allowed if( tgt->GetType() == cmTarget::MODULE_LIBRARY ) { diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 241445800..48aa2849d 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -347,6 +347,19 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar.c_str()); cmSystemTools::ExpandListArgument(linkRule, commands1); + if(this->Target->GetPropertyAsBool("ENABLE_EXPORTS")) + { + // If a separate rule for creating an import library is specified + // add it now. + std::string implibRuleVar = "CMAKE_"; + implibRuleVar += linkLanguage; + implibRuleVar += "_CREATE_IMPORT_LIBRARY"; + if(const char* rule = + this->Makefile->GetDefinition(implibRuleVar.c_str())) + { + cmSystemTools::ExpandListArgument(rule, commands1); + } + } this->LocalGenerator->CreateCDCommand (commands1, this->Makefile->GetStartOutputDirectory(), diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index ef4a07ee0..441269c7b 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -258,6 +258,23 @@ void cmTarget::DefineProperties(cmake *cm) "in contrast to a console application for example. This changes " "how the executable will be linked."); + cm->DefineProperty + ("ENABLE_EXPORTS", cmProperty::TARGET, + "Specify whether an executable exports symbols for loadable modules.", + "Normally an executable does not export any symbols because it is " + "the final program. It is possible for an executable to export " + "symbols to be used by loadable modules. When this property is " + "set to true CMake will allow other targets to \"link\" to the " + "executable with the TARGET_LINK_LIBRARIES command. " + "On all platforms a target-level dependency on the executable is " + "created for targets that link to it. " + "For non-DLL platforms the link rule is simply ignored since " + "the dynamic loader will automatically bind symbols when the " + "module is loaded. " + "For DLL platforms an import library will be created for the " + "exported symbols and then used for linking. " + "All Windows-based systems including Cygwin are DLL platforms."); + cm->DefineProperty ("OBJECT_FILES", cmProperty::TARGET, "Used to get the resulting list of object files that make up a "