From 9e64d5b272e0279d4a6d5e595118f34bc3c1f6c9 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 6 Feb 2008 14:20:36 -0500 Subject: ENH: Improve exporting/importing of targets - Use real name instead of link for location of versioned targets - Error when a target is exported multiple times --- Source/cmExportBuildFileGenerator.cxx | 29 +++++++++++-- Source/cmExportCommand.cxx | 2 +- Source/cmExportInstallFileGenerator.cxx | 74 ++++++++++++++++++++++---------- Source/cmInstallCommand.cxx | 13 +++++- Source/cmInstallTargetGenerator.cxx | 37 ++++++++++------ Source/cmInstallTargetGenerator.h | 14 +++++- Tests/ExportImport/Export/CMakeLists.txt | 5 ++- 7 files changed, 128 insertions(+), 46 deletions(-) diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 6506254..429bb53 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -33,8 +33,20 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) tei != this->Exports->end(); ++tei) { cmTarget* te = *tei; - this->ExportedTargets.insert(te); - this->GenerateImportTargetCode(os, te); + if(this->ExportedTargets.insert(te).second) + { + this->GenerateImportTargetCode(os, te); + } + else + { + if(this->ExportCommand && this->ExportCommand->ErrorMessage.empty()) + { + cmOStringStream e; + e << "given target \"" << te->GetName() << "\" more than once."; + this->ExportCommand->ErrorMessage = e.str(); + } + return false; + } } // Generate import file content for each configuration. @@ -93,12 +105,21 @@ cmExportBuildFileGenerator { std::string prop = "IMPORTED_LOCATION"; prop += suffix; - std::string value = target->GetFullPath(config, false); - if(target->IsAppBundleOnApple()) + std::string value; + if(target->IsFrameworkOnApple()) { + value = target->GetFullPath(config, false); + } + else if(target->IsAppBundleOnApple()) + { + value = target->GetFullPath(config, false); value += ".app/Contents/MacOS/"; value += target->GetFullName(config, false); } + else + { + value = target->GetFullPath(config, false, true); + } properties[prop] = value; } diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index ba47637..8dfb623 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -169,7 +169,7 @@ bool cmExportCommand } // Generate the import file. - if(!ebfg.GenerateImportFile()) + if(!ebfg.GenerateImportFile() && this->ErrorMessage.empty()) { this->SetError("could not write export file."); return false; diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 07f99cf..c71336a 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -36,8 +36,19 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) tei != this->ExportSet->end(); ++tei) { cmTargetExport* te = *tei; - this->ExportedTargets.insert(te->Target); - this->GenerateImportTargetCode(os, te->Target); + if(this->ExportedTargets.insert(te->Target).second) + { + this->GenerateImportTargetCode(os, te->Target); + } + else + { + cmOStringStream e; + e << "INSTALL(EXPORT \"" << this->Name << "\" ...) " + << "includes target \"" << te->Target->GetName() + << "\" more than once in the export set."; + cmSystemTools::Error(e.str().c_str()); + return false; + } } // Now load per-configuration properties for them. @@ -204,11 +215,8 @@ cmExportInstallFileGenerator return; } - { - // Construct the property name. - std::string prop = (itgen->IsImportLibrary()? - "IMPORTED_IMPLIB" : "IMPORTED_LOCATION"); - prop += suffix; + // Get the target to be installed. + cmTarget* target = itgen->GetTarget(); // Construct the installed location of the target. std::string dest = itgen->GetDestination(); @@ -225,25 +233,47 @@ cmExportInstallFileGenerator value += dest; value += "/"; - // Append the installed file name. - std::string fname = itgen->GetInstallFilename(config); - value += fname; - - // Fix name for frameworks and bundles. - if(itgen->GetTarget()->IsFrameworkOnApple()) + if(itgen->IsImportLibrary()) { - value += ".framework/"; - value += fname; + // Construct the property name. + std::string prop = "IMPORTED_IMPLIB"; + prop += suffix; + + // Append the installed file name. + value += itgen->GetInstallFilename(target, config, + cmInstallTargetGenerator::NameImplib); + + // Store the property. + properties[prop] = value; } - else if(itgen->GetTarget()->IsAppBundleOnApple()) + else { - value += ".app/Contents/MacOS/"; - value += fname; - } + // Construct the property name. + std::string prop = "IMPORTED_LOCATION"; + prop += suffix; - // Store the property. - properties[prop] = value; - } + // Append the installed file name. + if(target->IsFrameworkOnApple()) + { + value += itgen->GetInstallFilename(target, config); + value += ".framework/"; + value += itgen->GetInstallFilename(target, config); + } + else if(target->IsAppBundleOnApple()) + { + value += itgen->GetInstallFilename(target, config); + value += ".app/Contents/MacOS/"; + value += itgen->GetInstallFilename(target, config); + } + else + { + value += itgen->GetInstallFilename(target, config, + cmInstallTargetGenerator::NameReal); + } + + // Store the property. + properties[prop] = value; + } } //---------------------------------------------------------------------------- diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 868fb75..8fc77d1 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -394,6 +394,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) cmInstallFilesGenerator* publicHeaderGenerator = 0; cmInstallFilesGenerator* resourceGenerator = 0; + // Track whether this is a namelink-only rule. + bool namelinkOnly = false; + switch(target.GetType()) { case cmTarget::SHARED_LIBRARY: @@ -464,6 +467,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) libraryGenerator = CreateInstallTargetGenerator(target, libraryArgs, false); libraryGenerator->SetNamelinkMode(namelinkMode); + namelinkOnly = + (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly); } else { @@ -503,6 +508,8 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) libraryGenerator = CreateInstallTargetGenerator(target, libraryArgs, false); libraryGenerator->SetNamelinkMode(namelinkMode); + namelinkOnly = + (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly); } else { @@ -583,7 +590,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) createInstallGeneratorsForTargetFileSets = false; } - if(createInstallGeneratorsForTargetFileSets) + if(createInstallGeneratorsForTargetFileSets && !namelinkOnly) { const char* files = target.GetProperty("PRIVATE_HEADER"); if ((files) && (*files)) @@ -673,7 +680,9 @@ bool cmInstallCommand::HandleTargetsMode(std::vector const& args) this->Makefile->AddInstallGenerator(publicHeaderGenerator); this->Makefile->AddInstallGenerator(resourceGenerator); - if (!exports.GetString().empty()) + // Add this install rule to an export if one was specified and + // this is not a namelink-only rule. + if(!exports.GetString().empty() && !namelinkOnly) { this->Makefile->GetLocalGenerator()->GetGlobalGenerator() ->AddTargetToExports(exports.GetCString(), &target, diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index c1aa413..c8e00d5 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -144,10 +144,10 @@ cmInstallTargetGenerator Indent const& indent) { // Compute the full path to the main installed file for this target. + NameType nameType = this->ImportLibrary? NameImplib : NameNormal; std::string toInstallPath = this->GetInstallDestination(); toInstallPath += "/"; - toInstallPath += this->GetInstallFilename(this->Target, config, - this->ImportLibrary, false); + toInstallPath += this->GetInstallFilename(this->Target, config, nameType); // Track whether post-install operations should be added to the // script. @@ -194,8 +194,8 @@ cmInstallTargetGenerator // Need to apply install_name_tool and stripping to binary // inside bundle. toInstallPath += ".app/Contents/MacOS/"; - toInstallPath += this->GetInstallFilename(this->Target, config, - this->ImportLibrary, false); + toInstallPath += + this->GetInstallFilename(this->Target, config, nameType); literal_args += " USE_SOURCE_PERMISSIONS"; } else @@ -250,7 +250,7 @@ cmInstallTargetGenerator // inside framework. toInstallPath += ".framework/"; toInstallPath += this->GetInstallFilename(this->Target, config, - this->ImportLibrary, false); + NameNormal); literal_args += " USE_SOURCE_PERMISSIONS"; } @@ -369,16 +369,16 @@ cmInstallTargetGenerator std::string cmInstallTargetGenerator::GetInstallFilename(const char* config) const { + NameType nameType = this->ImportLibrary? NameImplib : NameNormal; return cmInstallTargetGenerator::GetInstallFilename(this->Target, config, - this->ImportLibrary, false); + nameType); } //---------------------------------------------------------------------------- std::string cmInstallTargetGenerator::GetInstallFilename(cmTarget* target, const char* config, - bool implib, - bool useSOName) + NameType nameType) { std::string fname; // Compute the name of the library. @@ -391,11 +391,16 @@ std::string cmInstallTargetGenerator::GetInstallFilename(cmTarget* target, target->GetExecutableNames(targetName, targetNameReal, targetNameImport, targetNamePDB, config); - if(implib) + if(nameType == NameImplib) { // Use the import library name. fname = targetNameImport; } + else if(nameType == NameReal) + { + // Use the canonical name. + fname = targetNameReal; + } else { // Use the canonical name. @@ -411,16 +416,21 @@ std::string cmInstallTargetGenerator::GetInstallFilename(cmTarget* target, std::string targetNamePDB; target->GetLibraryNames(targetName, targetNameSO, targetNameReal, targetNameImport, targetNamePDB, config); - if(implib) + if(nameType == NameImplib) { // Use the import library name. fname = targetNameImport; } - else if(useSOName) + else if(nameType == NameSO) { // Use the soname. fname = targetNameSO; } + else if(nameType == NameReal) + { + // Use the real name. + fname = targetNameReal; + } else { // Use the canonical name. @@ -474,7 +484,7 @@ cmInstallTargetGenerator // The directory portions differ. Append the filename to // create the mapping. std::string fname = - this->GetInstallFilename(tgt, config, false, true); + this->GetInstallFilename(tgt, config, NameSO); // Map from the build-tree install_name. for_build += fname; @@ -511,8 +521,7 @@ cmInstallTargetGenerator { // Prepare to refer to the install-tree install_name. new_id = for_install; - new_id += this->GetInstallFilename(this->Target, config, - this->ImportLibrary, true); + new_id += this->GetInstallFilename(this->Target, config, NameSO); } } diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h index 3b5dbb8..95c255d 100644 --- a/Source/cmInstallTargetGenerator.h +++ b/Source/cmInstallTargetGenerator.h @@ -45,10 +45,20 @@ public: NamelinkModeSkip }; void SetNamelinkMode(NamelinkModeType mode) { this->NamelinkMode = mode; } + NamelinkModeType GetNamelinkMode() const { return this->NamelinkMode; } std::string GetInstallFilename(const char* config) const; - static std::string GetInstallFilename(cmTarget*target, const char* config, - bool implib, bool useSOName); + + enum NameType + { + NameNormal, + NameImplib, + NameSO, + NameReal + }; + + static std::string GetInstallFilename(cmTarget*target, const char* config, + NameType nameType = NameNormal); cmTarget* GetTarget() const { return this->Target; } bool IsImportLibrary() const { return this->ImportLibrary; } diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index b90330b..74ff8ed 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -8,6 +8,7 @@ endif(CMAKE_ANSI_CFLAGS) add_library(testExe1lib STATIC testExe1lib.c) # not exported add_executable(testExe1 testExe1.c) target_link_libraries(testExe1 testExe1lib) +set_property(TARGET testExe1 PROPERTY VERSION 4) add_library(testExe2libImp SHARED testExe2libImp.c) set_property(TARGET testExe2libImp PROPERTY LIBRARY_OUTPUT_DIRECTORY impl) @@ -27,6 +28,8 @@ set_property(TARGET testLib3Imp PROPERTY LIBRARY_OUTPUT_DIRECTORY impl) add_library(testLib3 SHARED testLib3.c) target_link_libraries(testLib3 testLib3Imp) set_property(TARGET testLib3 PROPERTY LINK_INTERFACE_LIBRARIES "") +set_property(TARGET testLib3 PROPERTY VERSION 1.2) +set_property(TARGET testLib3 PROPERTY SOVERSION 3) add_library(testLib4 SHARED testLib4.c) set_property(TARGET testLib4 PROPERTY FRAMEWORK 1) @@ -41,7 +44,7 @@ install( testExe2lib EXPORT exp RUNTIME DESTINATION bin - LIBRARY DESTINATION lib + LIBRARY DESTINATION lib NAMELINK_SKIP ARCHIVE DESTINATION lib FRAMEWORK DESTINATION Frameworks BUNDLE DESTINATION Applications -- cgit v0.12