From 5a32aa5919bd9dab272748c0e0ea12fbcd36436b Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 22 Mar 2007 09:45:25 -0400 Subject: [PATCH] ENH: Added target property ENABLE_EXPORTS for executable targets. It enables the executables for linking by loadable modules that import symbols from the executable. This finishes the executable import library support mentioned in bug #4210. --- Modules/Platform/Windows-bcc32.cmake | 20 +++++++++++++------ Modules/Platform/Windows-wcl386.cmake | 11 +++++++--- Source/cmLocalGenerator.cxx | 16 ++++++++++++--- Source/cmMakefile.cxx | 7 +++++-- .../cmMakefileExecutableTargetGenerator.cxx | 13 ++++++++++++ Source/cmTarget.cxx | 17 ++++++++++++++++ 6 files changed, 70 insertions(+), 14 deletions(-) diff --git a/Modules/Platform/Windows-bcc32.cmake b/Modules/Platform/Windows-bcc32.cmake index 82fa064f93..382bf2d253 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 f56e148aab..acec459dd8 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 71d3c51b92..c7f50f6e37 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 78b44a4076..e5dc29b60c 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 2414458005..48aa2849dc 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 ef4a07ee07..441269c7b1 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 "