diff options
author | Brad King <brad.king@kitware.com> | 2008-01-28 13:38:36 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2008-01-28 13:38:36 (GMT) |
commit | 5594ad488576a77d9c6b8c3c1999a04fb4e6867d (patch) | |
tree | f22726476b6eaaf3832e48c185fe3c112601db17 /Source/cmInstallExportGenerator.cxx | |
parent | a7cb9d1120c0555f1da67dd585bd1b4fd16d389d (diff) | |
download | CMake-5594ad488576a77d9c6b8c3c1999a04fb4e6867d.zip CMake-5594ad488576a77d9c6b8c3c1999a04fb4e6867d.tar.gz CMake-5594ad488576a77d9c6b8c3c1999a04fb4e6867d.tar.bz2 |
ENH: Updated exporting and importing of targets to support libraries and configurations.
- Created cmExportFileGenerator hierarchy to implement export file generation
- Installed exports use per-config import files loaded by a central one.
- Include soname of shared libraries in import information
- Renamed PREFIX to NAMESPACE in INSTALL(EXPORT) and EXPORT() commands
- Move addition of CMAKE_INSTALL_PREFIX to destinations to install generators
- Import files compute the installation prefix relative to their location when loaded
- Add mapping of importer configurations to importee configurations
- Rename IMPORT targets to IMPORTED targets to distinguish from windows import libraries
- Scope IMPORTED targets within directories to isolate them
- Place all properties created by import files in the IMPORTED namespace
- Document INSTALL(EXPORT) and EXPORT() commands.
- Document IMPORTED signature of add_executable and add_library
- Enable finding of imported targets in cmComputeLinkDepends
Diffstat (limited to 'Source/cmInstallExportGenerator.cxx')
-rw-r--r-- | Source/cmInstallExportGenerator.cxx | 325 |
1 files changed, 132 insertions, 193 deletions
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index ed04ebc..81971aa 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -14,259 +14,198 @@ PURPOSE. See the above copyright notices for more information. =========================================================================*/ +#include "cmInstallExportGenerator.h" #include <stdio.h> +#include "cmake.h" #include "cmInstallTargetGenerator.h" #include "cmGeneratedFileStream.h" #include "cmTarget.h" +#include "cmMakefile.h" +#include "cmLocalGenerator.h" +#include "cmGlobalGenerator.h" -#include "cmInstallExportGenerator.h" #include "cmInstallFilesGenerator.h" +#include "cmExportInstallFileGenerator.h" + +//---------------------------------------------------------------------------- cmInstallExportGenerator::cmInstallExportGenerator( + const char* name, const char* destination, const char* file_permissions, std::vector<std::string> const& configurations, const char* component, - const char* filename, const char* prefix, const char* tempOutputDir) + const char* filename, const char* name_space, + cmMakefile* mf) :cmInstallGenerator(destination, configurations, component) + ,Name(name) ,FilePermissions(file_permissions) - ,Filename(filename) - ,Prefix(prefix) - ,TempOutputDir(tempOutputDir) + ,FileName(filename) + ,Namespace(name_space) + ,Makefile(mf) +{ + this->EFGen = new cmExportInstallFileGenerator(this); +} + +//---------------------------------------------------------------------------- +cmInstallExportGenerator::~cmInstallExportGenerator() { + delete this->EFGen; } -/* Helper function which adds the install locations from the generator -to the properties for this target. -*/ -bool cmInstallExportGenerator::AddInstallLocations(cmTargetWithProperties* twp, - cmInstallTargetGenerator* generator, - const char* prefix) +//---------------------------------------------------------------------------- +void cmInstallExportGenerator::ComputeTempDir() { - if (generator == 0) // nothing to do + // Choose a temporary directory in which to generate the import + // files to be installed. + this->TempDir = this->Makefile->GetCurrentOutputDirectory(); + this->TempDir += cmake::GetCMakeFilesDirectory(); + this->TempDir += "/Export"; + if(this->Destination.empty()) { - return true; + return; } - - if (prefix == 0) + else { - prefix = ""; + this->TempDir += "/"; } - const std::vector<std::string>& configs = generator->GetConfigurations(); - if (configs.empty()) + // Enforce a maximum length. + bool useMD5 = false; +#if defined(_WIN32) || defined(__CYGWIN__) + std::string::size_type const max_total_len = 250; +#else + std::string::size_type const max_total_len = 1000; +#endif + if(this->TempDir.size() < max_total_len) { - std::string propertyName = prefix; - propertyName += "LOCATION"; - // check that this property doesn't exist yet and add it then - if (twp->Properties.find(propertyName.c_str()) == twp->Properties.end()) + // Keep the total path length below the limit. + std::string::size_type max_len = max_total_len - this->TempDir.size(); + if(this->Destination.size() > max_len) { - std::string destinationFilename = generator->GetDestination(); - destinationFilename += "/"; - destinationFilename += generator->GetInstallFilename(0); - twp->Properties[propertyName.c_str()] = destinationFilename; - } - else - { - return false; + useMD5 = true; } } else { - for(std::vector<std::string>::const_iterator configIt = configs.begin(); - configIt != configs.end(); - ++configIt) - { - std::string propertyName = configIt->c_str(); - propertyName += "_"; - propertyName += prefix; - propertyName += "LOCATION"; - // check that this property doesn't exist yet and add it then - if (twp->Properties.find(propertyName.c_str()) == twp->Properties.end()) - { - std::string destinationFilename = generator->GetDestination(); - destinationFilename += "/"; - destinationFilename +=generator->GetInstallFilename(configIt->c_str()); - twp->Properties[propertyName.c_str()] = destinationFilename; - } - else - { - return false; - } - } - } - return true; -} - - -bool cmInstallExportGenerator::AddInstallLocations(cmTargetWithProperties* twp, - cmInstallFilesGenerator* generator, - const char* propertyName) -{ - if (generator == 0) // nothing to do - { - return true; + useMD5 = true; } - - if ((propertyName == 0) || (*propertyName == '\0')) + if(useMD5) { - return false; + // Replace the destination path with a hash to keep it short. + this->TempDir += + cmSystemTools::ComputeStringMD5(this->Destination.c_str()); } - - // check that this property doesn't exist yet and add it then - if (twp->Properties.find(propertyName) == twp->Properties.end()) + else { - twp->Properties[propertyName] = generator->GetDestination(); - return true; + std::string dest = this->Destination; + // Avoid unix full paths. + if(dest[0] == '/') + { + dest[0] = '_'; + } + // Avoid windows full paths by removing colons. + cmSystemTools::ReplaceString(dest, ":", "_"); + // Avoid relative paths that go up the tree. + cmSystemTools::ReplaceString(dest, "../", "__/"); + // Avoid spaces. + cmSystemTools::ReplaceString(dest, " ", "_"); + this->TempDir += dest; } - - return false; } - -bool cmInstallExportGenerator::SetExportSet(const char* name, - const std::vector<cmTargetExport*>* set) +//---------------------------------------------------------------------------- +void cmInstallExportGenerator::GenerateScript(std::ostream& os) { - if ((name == 0) || (*name == 0) || (set==0)) + // Get the export set requested. + ExportSet const* exportSet = + this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + ->GetExportSet(this->Name.c_str()); + + // Skip empty sets. + if(!exportSet) { - return false; + cmOStringStream e; + e << "INSTALL(EXPORT) given unknown export \"" << this->Name << "\""; + cmSystemTools::Error(e.str().c_str()); + return; } - this->Name = name; - - /* iterate over all targets in the set. - If a cmTargetWithProperties with the same name already exists in this - generator, add the new properties to it. If the property already exists, - fail with an error. - If no cmTargetWithProperties exists, create a new one. - */ - for(std::vector<cmTargetExport*>::const_iterator it=set->begin(); - it != set->end(); - ++it) + // Create the temporary directory in which to store the files. + this->ComputeTempDir(); + cmSystemTools::MakeDirectory(this->TempDir.c_str()); + + // Construct a temporary location for the file. + this->MainImportFile = this->TempDir; + this->MainImportFile += "/"; + this->MainImportFile += this->FileName; + + // Generate the import file for this export set. + this->EFGen->SetName(this->Name.c_str()); + this->EFGen->SetExportSet(exportSet); + this->EFGen->SetExportFile(this->MainImportFile.c_str()); + this->EFGen->SetNamespace(this->Namespace.c_str()); + if(this->ConfigurationTypes->empty()) { - std::string targetName = (*it)->Target->GetName(); - - cmTargetWithProperties* targetWithProps = 0; - for(unsigned int i=0; i<this->Targets.size(); i++) - { - if (targetName == this->Targets[i]->Target->GetName()) - { - targetWithProps = this->Targets[i]; - break; - } - } - - if (targetWithProps == 0) + if(this->ConfigurationName && *this->ConfigurationName) { - targetWithProps = new cmTargetWithProperties((*it)->Target); - this->Targets.push_back(targetWithProps); + this->EFGen->AddConfiguration(this->ConfigurationName); } - - if (this->AddInstallLocations(targetWithProps, (*it)->ArchiveGenerator, - "ARCHIVE_") == false) - { - return false; - } - if (this->AddInstallLocations(targetWithProps, (*it)->RuntimeGenerator, - "") == false) - { - return false; - } - if (this->AddInstallLocations(targetWithProps, (*it)->LibraryGenerator, - "LIBRARY_") == false) + else { - return false; + this->EFGen->AddConfiguration(""); } - if (this->AddInstallLocations(targetWithProps, (*it)->HeaderGenerator, - "PUBLIC_HEADER_LOCATION") == false) + } + else + { + for(std::vector<std::string>::const_iterator + ci = this->ConfigurationTypes->begin(); + ci != this->ConfigurationTypes->end(); ++ci) { - return false; + this->EFGen->AddConfiguration(ci->c_str()); } } + this->EFGen->GenerateImportFile(); - return true; + // Perform the main install script generation. + this->cmInstallGenerator::GenerateScript(os); } -void cmInstallExportGenerator::GenerateScript(std::ostream& os) +//---------------------------------------------------------------------------- +void +cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os, + Indent const& indent) { - // for the case that somebody exports the same set with the same file name - // to different locations make the temp filename unique - char buf[64]; - sprintf(buf, "%p", this); - this->ExportFilename = this->TempOutputDir; - this->ExportFilename += "/"; - this->ExportFilename += this->Filename; - this->ExportFilename += "."; - this->ExportFilename += buf; - - cmGeneratedFileStream exportFileStream(this->ExportFilename.c_str()); - if(!exportFileStream) + // Create the main install rules first. + this->cmInstallGenerator::GenerateScriptConfigs(os, indent); + + // Now create a configuration-specific install rule for the import + // file of each configuration. + std::vector<std::string> files; + for(std::map<cmStdString, cmStdString>::const_iterator + i = this->EFGen->GetConfigImportFiles().begin(); + i != this->EFGen->GetConfigImportFiles().end(); ++i) { - return; + files.push_back(i->second); + std::string config_test = this->CreateConfigTest(i->first.c_str()); + os << indent << "IF(" << config_test << ")\n"; + this->AddInstallRule(os, cmTarget::INSTALL_FILES, files, false, 0, + this->FilePermissions.c_str(), 0, 0, 0, + indent.Next()); + os << indent << "ENDIF(" << config_test << ")\n"; + files.clear(); } - - /* for every target add the IMPORT statements and set the properties - of the target. */ - for(std::vector<cmTargetWithProperties*>::const_iterator - targetIt = this->Targets.begin(); - targetIt != this->Targets.end(); - ++targetIt) - { - switch ((*targetIt)->Target->GetType()) - { - case cmTarget::EXECUTABLE: - exportFileStream << "ADD_EXECUTABLE(" << this->Prefix.c_str() - << (*targetIt)->Target->GetName() - << " IMPORT )\n"; - break; - case cmTarget::STATIC_LIBRARY: - exportFileStream << "ADD_LIBRARY(" << this->Prefix.c_str() - << (*targetIt)->Target->GetName() - << " STATIC IMPORT )\n"; - break; - case cmTarget::SHARED_LIBRARY: - exportFileStream << "ADD_LIBRARY(" << this->Prefix.c_str() - << (*targetIt)->Target->GetName() - << " SHARED IMPORT )\n"; - break; - case cmTarget::MODULE_LIBRARY: - exportFileStream << "ADD_LIBRARY(" << this->Prefix.c_str() - << (*targetIt)->Target->GetName() - << " MODULE IMPORT )\n"; - break; - default: // should never happen - break; - } - - exportFileStream << "SET_TARGET_PROPERTIES ( " << this->Prefix.c_str() - << (*targetIt)->Target->GetName() << " PROPERTIES \n"; - - for (std::map<std::string, std::string>::const_iterator - propIt = (*targetIt)->Properties.begin(); - propIt != (*targetIt)->Properties.end(); - ++propIt) - { - exportFileStream << " " << propIt->first - << " \"" << propIt->second << "\"\n"; - } - exportFileStream << " )\n\n"; - } - - // Perform the main install script generation. - this->cmInstallGenerator::GenerateScript(os); } //---------------------------------------------------------------------------- void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os, Indent const& indent) { - // install rule for the file created above - std::vector<std::string> exportFile; - exportFile.push_back(this->ExportFilename); - this->AddInstallRule(os, this->Destination.c_str(), cmTarget::INSTALL_FILES, - exportFile, false, 0, - this->FilePermissions.c_str(), - 0, this->Filename.c_str(), 0, indent); + // Install the main export file. + std::vector<std::string> files; + files.push_back(this->MainImportFile); + this->AddInstallRule(os, cmTarget::INSTALL_FILES, files, false, 0, + this->FilePermissions.c_str(), 0, 0, 0, indent); } |