summaryrefslogtreecommitdiff
path: root/Source/cmExportInstallFileGenerator.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmExportInstallFileGenerator.cxx')
-rw-r--r--Source/cmExportInstallFileGenerator.cxx333
1 files changed, 333 insertions, 0 deletions
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
new file mode 100644
index 000000000..da14dd787
--- /dev/null
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -0,0 +1,333 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmExportInstallFileGenerator.h"
+
+#include "cmGeneratedFileStream.h"
+#include "cmInstallExportGenerator.h"
+#include "cmInstallTargetGenerator.h"
+
+//----------------------------------------------------------------------------
+cmExportInstallFileGenerator
+::cmExportInstallFileGenerator(cmInstallExportGenerator* iegen):
+ InstallExportGenerator(iegen)
+{
+}
+
+//----------------------------------------------------------------------------
+std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
+{
+ std::string glob = this->FileBase;
+ glob += "-*";
+ glob += this->FileExt;
+ return glob;
+}
+
+//----------------------------------------------------------------------------
+bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
+{
+ // Create all the imported targets.
+ for(std::vector<cmTargetExport*>::const_iterator
+ tei = this->ExportSet->begin();
+ tei != this->ExportSet->end(); ++tei)
+ {
+ cmTargetExport* te = *tei;
+ 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.
+ os << "# Load information for each installed configuration.\n"
+ << "GET_FILENAME_COMPONENT(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"
+ << "FILE(GLOB CONFIG_FILES \"${_DIR}/"
+ << this->GetConfigImportFileGlob() << "\")\n"
+ << "FOREACH(f ${CONFIG_FILES})\n"
+ << " INCLUDE(${f})\n"
+ << "ENDFOREACH(f)\n"
+ << "\n";
+
+ // Generate an import file for each configuration.
+ bool result = true;
+ for(std::vector<std::string>::const_iterator
+ ci = this->Configurations.begin();
+ ci != this->Configurations.end(); ++ci)
+ {
+ if(!this->GenerateImportFileConfig(ci->c_str()))
+ {
+ result = false;
+ }
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------
+bool
+cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
+{
+ // Skip configurations not enabled for this export.
+ if(!this->InstallExportGenerator->InstallsForConfig(config))
+ {
+ return true;
+ }
+
+ // Construct the name of the file to generate.
+ std::string fileName = this->FileDir;
+ fileName += "/";
+ fileName += this->FileBase;
+ fileName += "-";
+ if(config && *config)
+ {
+ fileName += cmSystemTools::LowerCase(config);
+ }
+ else
+ {
+ fileName += "noconfig";
+ }
+ fileName += this->FileExt;
+
+ // Open the output file to generate it.
+ cmGeneratedFileStream exportFileStream(fileName.c_str(), true);
+ if(!exportFileStream)
+ {
+ std::string se = cmSystemTools::GetLastSystemError();
+ cmOStringStream e;
+ e << "cannot write to file \"" << fileName.c_str()
+ << "\": " << se;
+ cmSystemTools::Error(e.str().c_str());
+ return false;
+ }
+ std::ostream& os = exportFileStream;
+
+ // Start with the import file header.
+ this->GenerateImportHeaderCode(os, config);
+
+ // Generate the per-config target information.
+ this->GenerateImportConfig(os, config);
+
+ // End with the import file footer.
+ this->GenerateImportFooterCode(os);
+
+ // Record this per-config import file.
+ this->ConfigImportFiles[config] = fileName;
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportInstallFileGenerator
+::GenerateImportTargetsConfig(std::ostream& os,
+ const char* config, std::string const& suffix)
+{
+ // Add code to compute the installation prefix relative to the
+ // import file location.
+ const char* installDest = this->InstallExportGenerator->GetDestination();
+ if(!cmSystemTools::FileIsFullPath(installDest))
+ {
+ std::string dest = installDest;
+ os << "# Compute the installation prefix relative to this file.\n"
+ << "GET_FILENAME_COMPONENT(_IMPORT_PREFIX "
+ << "\"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
+ while(!dest.empty())
+ {
+ os <<
+ "GET_FILENAME_COMPONENT(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n";
+ dest = cmSystemTools::GetFilenamePath(dest);
+ }
+ os << "\n";
+
+ // Import location properties may reference this variable.
+ this->ImportPrefix = "${_IMPORT_PREFIX}/";
+ }
+
+ // Add each target in the set to the export.
+ for(std::vector<cmTargetExport*>::const_iterator
+ tei = this->ExportSet->begin();
+ tei != this->ExportSet->end(); ++tei)
+ {
+ // Collect import properties for this target.
+ cmTargetExport* te = *tei;
+ ImportPropertyMap properties;
+ std::set<std::string> importedLocations;
+ this->SetImportLocationProperty(config, suffix, te->ArchiveGenerator,
+ properties, importedLocations);
+ this->SetImportLocationProperty(config, suffix, te->LibraryGenerator,
+ properties, importedLocations);
+ this->SetImportLocationProperty(config, suffix,
+ te->RuntimeGenerator, properties,
+ importedLocations);
+ this->SetImportLocationProperty(config, suffix, te->FrameworkGenerator,
+ properties, importedLocations);
+ this->SetImportLocationProperty(config, suffix, te->BundleGenerator,
+ properties, importedLocations);
+
+ // If any file location was set for the target add it to the
+ // import file.
+ if(!properties.empty())
+ {
+ // Get the rest of the target details.
+ this->SetImportDetailProperties(config, suffix,
+ te->Target, properties);
+
+ // TOOD: PUBLIC_HEADER_LOCATION
+ // This should wait until the build feature propagation stuff
+ // is done. Then this can be a propagated include directory.
+ // this->GenerateImportProperty(config, te->HeaderGenerator,
+ // properties);
+
+ // Generate code in the export file.
+ this->GenerateImportPropertyCode(os, config, te->Target, properties);
+ this->GenerateImportedFileChecksCode(os, te->Target, properties,
+ importedLocations);
+ }
+ }
+
+ this->GenerateImportedFileCheckLoop(os);
+
+ // Cleanup the import prefix variable.
+ if(!this->ImportPrefix.empty())
+ {
+ os << "# Cleanup temporary variables.\n"
+ << "SET(_IMPORT_PREFIX)\n"
+ << "\n";
+ }
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportInstallFileGenerator
+::SetImportLocationProperty(const char* config, std::string const& suffix,
+ cmInstallTargetGenerator* itgen,
+ ImportPropertyMap& properties,
+ std::set<std::string>& importedLocations
+ )
+{
+ // Skip rules that do not match this configuration.
+ if(!(itgen && itgen->InstallsForConfig(config)))
+ {
+ return;
+ }
+
+ // Get the target to be installed.
+ cmTarget* target = itgen->GetTarget();
+
+ // Construct the installed location of the target.
+ std::string dest = itgen->GetDestination();
+ std::string value;
+ if(!cmSystemTools::FileIsFullPath(dest.c_str()))
+ {
+ // The target is installed relative to the installation prefix.
+ if(this->ImportPrefix.empty())
+ {
+ this->ComplainAboutImportPrefix(itgen);
+ }
+ value = this->ImportPrefix;
+ }
+ value += dest;
+ value += "/";
+
+ if(itgen->IsImportLibrary())
+ {
+ // 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;
+ importedLocations.insert(prop);
+ }
+ else
+ {
+ // Construct the property name.
+ std::string prop = "IMPORTED_LOCATION";
+ prop += suffix;
+
+ // Append the installed file name.
+ if(target->IsFrameworkOnApple())
+ {
+ value += itgen->GetInstallFilename(target, config);
+ value += ".framework/";
+ value += itgen->GetInstallFilename(target, config);
+ }
+ else if(target->IsCFBundleOnApple())
+ {
+ const char *ext = target->GetProperty("BUNDLE_EXTENSION");
+ if (!ext)
+ {
+ ext = "bundle";
+ }
+
+ value += itgen->GetInstallFilename(target, config);
+ value += ".";
+ value += ext;
+ value += "/";
+ 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;
+ importedLocations.insert(prop);
+ }
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportInstallFileGenerator
+::ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen)
+{
+ const char* installDest = this->InstallExportGenerator->GetDestination();
+ cmOStringStream e;
+ e << "INSTALL(EXPORT \"" << this->Name << "\") given absolute "
+ << "DESTINATION \"" << installDest << "\" but the export "
+ << "references an installation of target \""
+ << itgen->GetTarget()->GetName() << "\" which has relative "
+ << "DESTINATION \"" << itgen->GetDestination() << "\".";
+ cmSystemTools::Error(e.str().c_str());
+}
+
+//----------------------------------------------------------------------------
+void
+cmExportInstallFileGenerator
+::ComplainAboutMissingTarget(cmTarget* depender, cmTarget* dependee)
+{
+ cmOStringStream e;
+ e << "INSTALL(EXPORT \"" << this->Name << "\" ...) "
+ << "includes target \"" << depender->GetName()
+ << "\" which requires target \"" << dependee->GetName()
+ << "\" that is not in the export set.";
+ cmSystemTools::Error(e.str().c_str());
+}