diff options
author | Stephen Kelly <steveire@gmail.com> | 2013-06-04 14:47:57 (GMT) |
---|---|---|
committer | Stephen Kelly <steveire@gmail.com> | 2013-07-08 20:39:57 (GMT) |
commit | 574fec97fd011ea2899abdd05d97ea66f0faa063 (patch) | |
tree | 82de4bacc4771ff4f6ce085cccec04d99b28d35b /Source | |
parent | d0a76ea07cfc2a73900a9539e940e1e60dbba120 (diff) | |
download | CMake-574fec97fd011ea2899abdd05d97ea66f0faa063.zip CMake-574fec97fd011ea2899abdd05d97ea66f0faa063.tar.gz CMake-574fec97fd011ea2899abdd05d97ea66f0faa063.tar.bz2 |
Export: Generate INTERFACE_LINK_LIBRARIES property on targets.
This property is generated only for targets which have recorded
policy CMP0022 as NEW, and a compatibility mode is added to
additionally export the old interfaces in that case too.
If the old interfaces are not exported, the generated export files
require CMake 2.8.12. Because the unit tests use a version which
is not yet called 2.8.12, temporarily require a lower version.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/cmExportBuildFileGenerator.cxx | 9 | ||||
-rw-r--r-- | Source/cmExportCommand.cxx | 2 | ||||
-rw-r--r-- | Source/cmExportCommand.h | 7 | ||||
-rw-r--r-- | Source/cmExportFileGenerator.cxx | 50 | ||||
-rw-r--r-- | Source/cmExportFileGenerator.h | 11 | ||||
-rw-r--r-- | Source/cmExportInstallFileGenerator.cxx | 19 | ||||
-rw-r--r-- | Source/cmInstallCommand.cxx | 33 | ||||
-rw-r--r-- | Source/cmInstallCommand.h | 5 | ||||
-rw-r--r-- | Source/cmInstallExportGenerator.cxx | 3 | ||||
-rw-r--r-- | Source/cmInstallExportGenerator.h | 3 | ||||
-rw-r--r-- | Source/cmPolicies.cxx | 5 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 11 |
12 files changed, 150 insertions, 8 deletions
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 326663c..cdc3316 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -77,6 +77,15 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) properties, missingTargets); this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", te, properties); + const bool newCMP0022Behavior = + te->GetPolicyStatusCMP0022() != cmPolicies::WARN + && te->GetPolicyStatusCMP0022() != cmPolicies::OLD; + if (newCMP0022Behavior) + { + this->PopulateInterfaceLinkLibrariesProperty(te, + cmGeneratorExpression::BuildInterface, + properties, missingTargets); + } this->PopulateCompatibleInterfaceProperties(te, properties); this->GenerateInterfaceProperties(te, os, properties); diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index ffa8b51..9c3f314 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -30,6 +30,7 @@ cmExportCommand::cmExportCommand() ,Append(&Helper, "APPEND", &ArgumentGroup) ,Namespace(&Helper, "NAMESPACE", &ArgumentGroup) ,Filename(&Helper, "FILE", &ArgumentGroup) +,ExportOld(&Helper, "EXPORT_LINK_INTERFACE_LIBRARIES", &ArgumentGroup) { // at first TARGETS this->Targets.Follows(0); @@ -158,6 +159,7 @@ bool cmExportCommand ebfg.SetAppendMode(this->Append.IsEnabled()); ebfg.SetExports(&targets); ebfg.SetCommand(this); + ebfg.SetExportOld(this->ExportOld.IsEnabled()); // Compute the set of configurations exported. std::vector<std::string> configurationTypes; diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h index ae67b47..87c3452 100644 --- a/Source/cmExportCommand.h +++ b/Source/cmExportCommand.h @@ -63,7 +63,7 @@ public: { return " export(TARGETS [target1 [target2 [...]]] [NAMESPACE <namespace>]\n" - " [APPEND] FILE <filename>)\n" + " [APPEND] FILE <filename> [EXPORT_LINK_INTERFACE_LIBRARIES])\n" "Create a file <filename> that may be included by outside projects to " "import targets from the current project's build tree. " "This is useful during cross-compiling to build utility executables " @@ -73,6 +73,10 @@ public: "prepended to all target names written to the file. " "If the APPEND option is given the generated code will be appended " "to the file instead of overwriting it. " + "The EXPORT_LINK_INTERFACE_LIBRARIES keyword, if present, causes the " + "contents of the properties matching " + "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? to be exported, when " + "policy CMP0022 is NEW. " "If a library target is included in the export but " "a target to which it links is not included the behavior is " "unspecified." @@ -104,6 +108,7 @@ private: cmCAEnabler Append; cmCAString Namespace; cmCAString Filename; + cmCAEnabler ExportOld; friend class cmExportBuildFileGenerator; std::string ErrorMessage; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 6bef017..b4e6e81 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -30,6 +30,7 @@ cmExportFileGenerator::cmExportFileGenerator() { this->AppendMode = false; + this->ExportOld = false; } //---------------------------------------------------------------------------- @@ -168,6 +169,39 @@ void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName, } } +void cmExportFileGenerator::GenerateRequiredCMakeVersion(std::ostream& os, + const char *versionString) +{ + os << "if(CMAKE_VERSION VERSION_LESS " << versionString << ")\n" + " message(FATAL_ERROR \"This file relies on consumers using " + "CMake " << versionString << " or greater.\")\n" + "endif()\n\n"; +} + +//---------------------------------------------------------------------------- +bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty( + cmTarget *target, + cmGeneratorExpression::PreprocessContext preprocessRule, + ImportPropertyMap &properties, + std::vector<std::string> &missingTargets) +{ + const char *input = target->GetProperty("INTERFACE_LINK_LIBRARIES"); + if (input) + { + std::string prepro = cmGeneratorExpression::Preprocess(input, + preprocessRule); + if (!prepro.empty()) + { + this->ResolveTargetsInGeneratorExpressions(prepro, target, + missingTargets, + ReplaceFreeTargets); + properties["INTERFACE_LINK_LIBRARIES"] = prepro; + return true; + } + } + return false; +} + //---------------------------------------------------------------------------- static bool isSubDirectory(const char* a, const char* b) { @@ -583,6 +617,22 @@ cmExportFileGenerator return; } + const bool newCMP0022Behavior = + target->GetPolicyStatusCMP0022() != cmPolicies::WARN + && target->GetPolicyStatusCMP0022() != cmPolicies::OLD; + + if(newCMP0022Behavior && !this->ExportOld) + { + cmMakefile *mf = target->GetMakefile(); + cmOStringStream e; + e << "Target \"" << target->GetName() << "\" has policy CMP0022 enabled, " + "but also has old-style INTERFACE_LINK_LIBRARIES properties " + "populated, but it was exported without the " + "EXPORT_LINK_INTERFACE_LIBRARIES to export the old-style properties"; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + if (!*propContent) { properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = ""; diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index ed2d93b..a624ba6 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -35,6 +35,8 @@ public: /** Set the namespace in which to place exported target names. */ void SetNamespace(const char* ns) { this->Namespace = ns; } + void SetExportOld(bool exportOld) { this->ExportOld = exportOld; } + /** Add a configuration to be exported. */ void AddConfiguration(const char* config); @@ -101,6 +103,10 @@ protected: cmGeneratorExpression::PreprocessContext, ImportPropertyMap &properties, std::vector<std::string> &missingTargets); + bool PopulateInterfaceLinkLibrariesProperty(cmTarget *target, + cmGeneratorExpression::PreprocessContext, + ImportPropertyMap &properties, + std::vector<std::string> &missingTargets); void PopulateInterfaceProperty(const char *propName, cmTarget *target, ImportPropertyMap &properties); void PopulateCompatibleInterfaceProperties(cmTarget *target, @@ -128,9 +134,14 @@ protected: std::vector<std::string> &missingTargets, FreeTargetsReplace replace = NoReplaceFreeTargets); + void GenerateRequiredCMakeVersion(std::ostream& os, + const char *versionString); + // The namespace in which the exports are placed in the generated file. std::string Namespace; + bool ExportOld; + // The set of configurations to export. std::vector<std::string> Configurations; diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index a966b16..560882e 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -113,6 +113,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) std::vector<std::string> missingTargets; + bool require2_8_12 = false; // Create all the imported targets. for(std::vector<cmTarget*>::const_iterator tei = allTargets.begin(); @@ -134,6 +135,20 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) te, cmGeneratorExpression::InstallInterface, properties, missingTargets); + + const bool newCMP0022Behavior = + te->GetPolicyStatusCMP0022() != cmPolicies::WARN + && te->GetPolicyStatusCMP0022() != cmPolicies::OLD; + if (newCMP0022Behavior) + { + if (this->PopulateInterfaceLinkLibrariesProperty(te, + cmGeneratorExpression::InstallInterface, + properties, missingTargets) + && !this->ExportOld) + { + require2_8_12 = true; + } + } this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", te, properties); this->PopulateCompatibleInterfaceProperties(te, properties); @@ -141,6 +156,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) this->GenerateInterfaceProperties(te, os, properties); } + if (require2_8_12) + { + this->GenerateRequiredCMakeVersion(os, "2.8.11.20130626"); + } // Now load per-configuration properties for them. os << "# Load information for each installed configuration.\n" diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index dcd418b..d3a8037 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -1196,6 +1196,8 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) cmInstallCommandArguments ica(this->DefaultComponentName); cmCAString exp(&ica.Parser, "EXPORT"); cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup); + cmCAEnabler exportOld(&ica.Parser, "EXPORT_LINK_INTERFACE_LIBRARIES", + &ica.ArgumentGroup); cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup); exp.Follows(0); @@ -1268,15 +1270,40 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) } } + cmExportSet *exportSet = this->Makefile->GetLocalGenerator() + ->GetGlobalGenerator()->GetExportSets()[exp.GetString()]; + if (exportOld.IsEnabled()) + { + for(std::vector<cmTargetExport*>::const_iterator + tei = exportSet->GetTargetExports()->begin(); + tei != exportSet->GetTargetExports()->end(); ++tei) + { + cmTargetExport const* te = *tei; + const bool newCMP0022Behavior = + te->Target->GetPolicyStatusCMP0022() != cmPolicies::WARN + && te->Target->GetPolicyStatusCMP0022() != cmPolicies::OLD; + + if(!newCMP0022Behavior) + { + cmOStringStream e; + e << "INSTALL(EXPORT) given keyword \"" + << "EXPORT_LINK_INTERFACE_LIBRARIES" << "\", but target \"" + << te->Target->GetName() + << "\" does not have policy CMP0022 set to NEW."; + this->SetError(e.str().c_str()); + return false; + } + } + } + // Create the export install generator. cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator( - this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator()->GetExportSets()[exp.GetString()], + exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(), ica.GetConfigurations(), ica.GetComponent().c_str(), fname.c_str(), - name_space.GetCString(), this->Makefile); + name_space.GetCString(), exportOld.IsEnabled(), this->Makefile); this->Makefile->AddInstallGenerator(exportGenerator); return true; diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h index 7c06009..39acd23 100644 --- a/Source/cmInstallCommand.h +++ b/Source/cmInstallCommand.h @@ -291,6 +291,7 @@ public: " [NAMESPACE <namespace>] [FILE <name>.cmake]\n" " [PERMISSIONS permissions...]\n" " [CONFIGURATIONS [Debug|Release|...]]\n" + " [EXPORT_LINK_INTERFACE_LIBRARIES]\n" " [COMPONENT <component>])\n" "The EXPORT form generates and installs a CMake file containing code " "to import targets from the installation tree into another project. " @@ -306,6 +307,10 @@ public: "installed when one of the named configurations is installed. " "Additionally, the generated import file will reference only the " "matching target configurations. " + "The EXPORT_LINK_INTERFACE_LIBRARIES keyword, if present, causes the " + "contents of the properties matching " + "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? to be exported, when " + "policy CMP0022 is NEW. " "If a COMPONENT option is specified that does not match that given " "to the targets associated with <export-name> the behavior is " "undefined. " diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index 0a645a8..3e9e6ac 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -33,12 +33,14 @@ cmInstallExportGenerator::cmInstallExportGenerator( std::vector<std::string> const& configurations, const char* component, const char* filename, const char* name_space, + bool exportOld, cmMakefile* mf) :cmInstallGenerator(destination, configurations, component) ,ExportSet(exportSet) ,FilePermissions(file_permissions) ,FileName(filename) ,Namespace(name_space) + ,ExportOld(exportOld) ,Makefile(mf) { this->EFGen = new cmExportInstallFileGenerator(this); @@ -137,6 +139,7 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os) // Generate the import file for this export set. this->EFGen->SetExportFile(this->MainImportFile.c_str()); this->EFGen->SetNamespace(this->Namespace.c_str()); + this->EFGen->SetExportOld(this->ExportOld); if(this->ConfigurationTypes->empty()) { if(this->ConfigurationName && *this->ConfigurationName) diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h index 7aff731..37b5593 100644 --- a/Source/cmInstallExportGenerator.h +++ b/Source/cmInstallExportGenerator.h @@ -31,7 +31,7 @@ public: const std::vector<std::string>& configurations, const char* component, const char* filename, const char* name_space, - cmMakefile* mf); + bool exportOld, cmMakefile* mf); ~cmInstallExportGenerator(); cmExportSet* GetExportSet() {return this->ExportSet;} @@ -52,6 +52,7 @@ protected: std::string FilePermissions; std::string FileName; std::string Namespace; + bool ExportOld; cmMakefile* Makefile; std::string TempDir; diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 20c3058..15303c8 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -559,6 +559,11 @@ cmPolicies::cmPolicies() "and INTERFACE_COMPILE_OPTIONS properties. For in-build targets, CMake " "will use the INTERFACE_LINK_LIBRARIES property as the source of the " "link interface only if policy CMP0022 is NEW. " + "When exporting a target which has this policy set to NEW, only the " + "INTERFACE_LINK_LIBRARIES property will be processed and generated for " + "the IMPORTED target by default. A new option to the install(EXPORT) " + "and export commands allows export of the old-style properties for " + "compatibility with downstream users of CMake versions older than 2.8.12." "\n" "The OLD behavior for this policy is to ignore the " "INTERFACE_LINK_LIBRARIES property for in-build targets. " diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 3bad407..f08399f 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -5938,11 +5938,16 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config, // Get the link interface. { - std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES"; - linkProp += suffix; - + std::string linkProp = "INTERFACE_LINK_LIBRARIES"; const char *propertyLibs = this->GetProperty(linkProp.c_str()); + if (!propertyLibs) + { + linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES"; + linkProp += suffix; + propertyLibs = this->GetProperty(linkProp.c_str()); + } + if(!propertyLibs) { linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES"; |