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
This commit is contained in:
parent
a7cb9d1120
commit
5594ad4885
|
@ -121,6 +121,12 @@ SET(SRCS
|
|||
cmExprLexer.cxx
|
||||
cmExprParser.cxx
|
||||
cmExprParserHelper.cxx
|
||||
cmExportBuildFileGenerator.h
|
||||
cmExportBuildFileGenerator.cxx
|
||||
cmExportFileGenerator.h
|
||||
cmExportFileGenerator.cxx
|
||||
cmExportInstallFileGenerator.h
|
||||
cmExportInstallFileGenerator.cxx
|
||||
cmExtraEclipseCDT4Generator.cxx
|
||||
cmExtraEclipseCDT4Generator.h
|
||||
cmFileTimeComparison.cxx
|
||||
|
|
|
@ -32,7 +32,7 @@ bool cmAddDependenciesCommand
|
|||
|
||||
cmTarget* target =
|
||||
this->GetMakefile()->GetLocalGenerator()->
|
||||
GetGlobalGenerator()->FindTarget(0, target_name.c_str(), false);
|
||||
GetGlobalGenerator()->FindTarget(0, target_name.c_str());
|
||||
if(target)
|
||||
{
|
||||
std::vector<std::string>::const_iterator s = args.begin();
|
||||
|
|
|
@ -51,7 +51,7 @@ bool cmAddExecutableCommand
|
|||
++s;
|
||||
excludeFromAll = true;
|
||||
}
|
||||
else if(*s == "IMPORT")
|
||||
else if(*s == "IMPORTED")
|
||||
{
|
||||
++s;
|
||||
importTarget = true;
|
||||
|
@ -61,12 +61,60 @@ bool cmAddExecutableCommand
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (importTarget)
|
||||
|
||||
// Special modifiers are not allowed with IMPORTED signature.
|
||||
if(importTarget && (use_win32 || use_macbundle || excludeFromAll))
|
||||
{
|
||||
this->Makefile->AddNewTarget(cmTarget::EXECUTABLE, exename.c_str(), true);
|
||||
if(use_win32)
|
||||
{
|
||||
this->SetError("may not be given WIN32 for an IMPORTED target.");
|
||||
}
|
||||
else if(use_macbundle)
|
||||
{
|
||||
this->SetError(
|
||||
"may not be given MACOSX_BUNDLE for an IMPORTED target.");
|
||||
}
|
||||
else // if(excludeFromAll)
|
||||
{
|
||||
this->SetError(
|
||||
"may not be given EXCLUDE_FROM_ALL for an IMPORTED target.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for an existing target with this name.
|
||||
cmTarget* existing = this->Makefile->FindTargetToUse(exename.c_str());
|
||||
if(importTarget)
|
||||
{
|
||||
// Make sure the target does not already exist.
|
||||
if(existing)
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "cannot create imported target \"" << exename
|
||||
<< "\" because another target with the same name already exists.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the imported target.
|
||||
this->Makefile->AddImportedTarget(exename.c_str(), cmTarget::EXECUTABLE);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure the target does not conflict with an imported target.
|
||||
// This should really enforce global name uniqueness for targets
|
||||
// built within the project too, but that may break compatiblity
|
||||
// with projects in which it was accidentally working.
|
||||
if(existing && existing->IsImported())
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "cannot create target \"" << exename
|
||||
<< "\" because an imported target with the same name already exists.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (s == args.end())
|
||||
{
|
||||
|
|
|
@ -90,6 +90,24 @@ public:
|
|||
"If EXCLUDE_FROM_ALL is given the target will not be built by default. "
|
||||
"It will be built only if the user explicitly builds the target or "
|
||||
"another target that requires the target depends on it."
|
||||
"\n"
|
||||
"The add_executable command can also create IMPORTED executable "
|
||||
"targets using this signature:\n"
|
||||
" add_executable(<name> IMPORTED)\n"
|
||||
"An IMPORTED executable target references an executable file located "
|
||||
"outside the project. "
|
||||
"No rules are generated to build it. "
|
||||
"The target name has scope in the directory in which it is created "
|
||||
"and below. "
|
||||
"It may be referenced like any target built within the project. "
|
||||
"IMPORTED executables are useful for convenient reference from "
|
||||
"commands like add_custom_command. "
|
||||
"Details about the imported executable are specified by setting "
|
||||
"properties whose names begin in \"IMPORTED_\". "
|
||||
"The most important such property is IMPORTED_LOCATION "
|
||||
"(and its per-configuration version IMPORTED_LOCATION_<CONFIG>) "
|
||||
"which specifies the location of the main executable file on disk. "
|
||||
"See documentation of the IMPORTED_* properties for more information."
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ bool cmAddLibraryCommand
|
|||
// If the second argument is "SHARED" or "STATIC", then it controls
|
||||
// the type of library. Otherwise, it is treated as a source or
|
||||
// source list name. There may be two keyword arguments, check for them
|
||||
bool haveSpecifiedType = false;
|
||||
while ( s != args.end() )
|
||||
{
|
||||
std::string libType = *s;
|
||||
|
@ -53,23 +54,26 @@ bool cmAddLibraryCommand
|
|||
{
|
||||
++s;
|
||||
type = cmTarget::STATIC_LIBRARY;
|
||||
haveSpecifiedType = true;
|
||||
}
|
||||
else if(libType == "SHARED")
|
||||
{
|
||||
++s;
|
||||
type = cmTarget::SHARED_LIBRARY;
|
||||
haveSpecifiedType = true;
|
||||
}
|
||||
else if(libType == "MODULE")
|
||||
{
|
||||
++s;
|
||||
type = cmTarget::MODULE_LIBRARY;
|
||||
haveSpecifiedType = true;
|
||||
}
|
||||
else if(*s == "EXCLUDE_FROM_ALL")
|
||||
{
|
||||
++s;
|
||||
excludeFromAll = true;
|
||||
}
|
||||
else if(*s == "IMPORT")
|
||||
else if(*s == "IMPORTED")
|
||||
{
|
||||
++s;
|
||||
importTarget = true;
|
||||
|
@ -98,11 +102,46 @@ bool cmAddLibraryCommand
|
|||
type = cmTarget::STATIC_LIBRARY;
|
||||
}
|
||||
|
||||
if (importTarget)
|
||||
// The IMPORTED signature requires a type to be specified explicitly.
|
||||
if(importTarget && !haveSpecifiedType)
|
||||
{
|
||||
this->Makefile->AddNewTarget(type, libName.c_str(), true);
|
||||
this->SetError("called with IMPORTED argument but no library type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for an existing target with this name.
|
||||
cmTarget* existing = this->Makefile->FindTargetToUse(libName.c_str());
|
||||
if(importTarget)
|
||||
{
|
||||
// Make sure the target does not already exist.
|
||||
if(existing)
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "cannot create imported target \"" << libName
|
||||
<< "\" because another target with the same name already exists.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the imported target.
|
||||
this->Makefile->AddImportedTarget(libName.c_str(), type);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure the target does not conflict with an imported target.
|
||||
// This should really enforce global name uniqueness for targets
|
||||
// built within the project too, but that may break compatiblity
|
||||
// with projects in which it was accidentally working.
|
||||
if(existing && existing->IsImported())
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "cannot create target \"" << libName
|
||||
<< "\" because an imported target with the same name already exists.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (s == args.end())
|
||||
{
|
||||
|
|
|
@ -73,7 +73,26 @@ public:
|
|||
"to STATIC.\n"
|
||||
"If EXCLUDE_FROM_ALL is given the target will not be built by default. "
|
||||
"It will be built only if the user explicitly builds the target or "
|
||||
"another target that requires the target depends on it.";
|
||||
"another target that requires the target depends on it."
|
||||
"\n"
|
||||
"The add_library command can also create IMPORTED library "
|
||||
"targets using this signature:\n"
|
||||
" add_library(<name> <SHARED|STATIC|MODULE> IMPORTED)\n"
|
||||
"An IMPORTED library target references a library file located "
|
||||
"outside the project. "
|
||||
"No rules are generated to build it. "
|
||||
"The target name has scope in the directory in which it is created "
|
||||
"and below. "
|
||||
"It may be referenced like any target built within the project. "
|
||||
"IMPORTED libraries are useful for convenient reference from "
|
||||
"commands like target_link_libraries. "
|
||||
"Details about the imported library are specified by setting "
|
||||
"properties whose names begin in \"IMPORTED_\". "
|
||||
"The most important such property is IMPORTED_LOCATION "
|
||||
"(and its per-configuration version IMPORTED_LOCATION_<CONFIG>) "
|
||||
"which specifies the location of the main library file on disk. "
|
||||
"See documentation of the IMPORTED_* properties for more information."
|
||||
;
|
||||
}
|
||||
|
||||
cmTypeMacro(cmAddLibraryCommand, cmCommand);
|
||||
|
|
|
@ -158,7 +158,7 @@ std::vector<cmComputeLinkDepends::LinkEntry> const&
|
|||
cmComputeLinkDepends::Compute()
|
||||
{
|
||||
// Follow the link dependencies of the target to be linked.
|
||||
this->AddLinkEntries(-1, this->Target->GetOriginalLinkLibraries());
|
||||
this->AddTargetLinkEntries(-1, this->Target->GetOriginalLinkLibraries());
|
||||
|
||||
// Complete the breadth-first search of dependencies.
|
||||
while(!this->BFSQueue.empty())
|
||||
|
@ -222,8 +222,7 @@ int cmComputeLinkDepends::AddLinkEntry(std::string const& item)
|
|||
int index = lei->second;
|
||||
LinkEntry& entry = this->EntryList[index];
|
||||
entry.Item = item;
|
||||
entry.Target =
|
||||
this->GlobalGenerator->FindTarget(0, entry.Item.c_str(), false);
|
||||
entry.Target = this->Makefile->FindTargetToUse(entry.Item.c_str());
|
||||
|
||||
// If the item has dependencies queue it to follow them.
|
||||
if(entry.Target)
|
||||
|
@ -264,8 +263,15 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
|
|||
if(entry.Target)
|
||||
{
|
||||
// Follow the target dependencies.
|
||||
this->AddLinkEntries(depender_index,
|
||||
entry.Target->GetOriginalLinkLibraries());
|
||||
if(entry.Target->IsImported())
|
||||
{
|
||||
this->AddImportedLinkEntries(depender_index, entry.Target);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->AddTargetLinkEntries(depender_index,
|
||||
entry.Target->GetOriginalLinkLibraries());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -274,6 +280,18 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
|
|||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmComputeLinkDepends::AddImportedLinkEntries(int depender_index,
|
||||
cmTarget* target)
|
||||
{
|
||||
if(std::vector<std::string> const* libs =
|
||||
target->GetImportedLinkLibraries(this->Config))
|
||||
{
|
||||
this->AddLinkEntries(depender_index, *libs);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
|
||||
const char* value)
|
||||
{
|
||||
|
@ -283,39 +301,49 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
|
|||
std::vector<std::string> deplist;
|
||||
cmSystemTools::ExpandListArgument(value, deplist);
|
||||
|
||||
// Construct the vector of type/value pairs from the variable.
|
||||
LinkLibraryVectorType libs;
|
||||
cmTarget::LinkLibraryType linkType = cmTarget::GENERAL;
|
||||
// Compute which library configuration to link.
|
||||
cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED;
|
||||
if(this->Config && cmSystemTools::UpperCase(this->Config) == "DEBUG")
|
||||
{
|
||||
linkType = cmTarget::DEBUG;
|
||||
}
|
||||
|
||||
// Look for entries meant for this configuration.
|
||||
std::vector<std::string> actual_libs;
|
||||
cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
|
||||
for(std::vector<std::string>::const_iterator di = deplist.begin();
|
||||
di != deplist.end(); ++di)
|
||||
{
|
||||
if(*di == "debug")
|
||||
{
|
||||
linkType = cmTarget::DEBUG;
|
||||
llt = cmTarget::DEBUG;
|
||||
}
|
||||
else if(*di == "optimized")
|
||||
{
|
||||
linkType = cmTarget::OPTIMIZED;
|
||||
llt = cmTarget::OPTIMIZED;
|
||||
}
|
||||
else if(*di == "general")
|
||||
{
|
||||
linkType = cmTarget::GENERAL;
|
||||
llt = cmTarget::GENERAL;
|
||||
}
|
||||
else if(!di->empty())
|
||||
{
|
||||
cmTarget::LibraryID lib(*di, linkType);
|
||||
libs.push_back(lib);
|
||||
if(llt == cmTarget::GENERAL || llt == linkType)
|
||||
{
|
||||
actual_libs.push_back(*di);
|
||||
}
|
||||
linkType = cmTarget::GENERAL;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the entries from this list.
|
||||
this->AddLinkEntries(depender_index, libs);
|
||||
this->AddLinkEntries(depender_index, actual_libs);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmComputeLinkDepends::AddLinkEntries(int depender_index,
|
||||
LinkLibraryVectorType const& libs)
|
||||
void
|
||||
cmComputeLinkDepends::AddTargetLinkEntries(int depender_index,
|
||||
LinkLibraryVectorType const& libs)
|
||||
{
|
||||
// Compute which library configuration to link.
|
||||
cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED;
|
||||
|
@ -324,23 +352,42 @@ void cmComputeLinkDepends::AddLinkEntries(int depender_index,
|
|||
linkType = cmTarget::DEBUG;
|
||||
}
|
||||
|
||||
// Track inferred dependency sets implied by this list.
|
||||
std::map<int, DependSet> dependSets;
|
||||
|
||||
// Loop over the libraries linked directly by the target.
|
||||
// Look for entries meant for this configuration.
|
||||
std::vector<std::string> actual_libs;
|
||||
for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
|
||||
li != libs.end(); ++li)
|
||||
{
|
||||
// Skip entries that will resolve to the target getting linked.
|
||||
// Skip libraries not meant for the current configuration.
|
||||
if(li->first == this->Target->GetName() || li->first.empty() ||
|
||||
!(li->second == cmTarget::GENERAL || li->second == linkType))
|
||||
if(li->second == cmTarget::GENERAL || li->second == linkType)
|
||||
{
|
||||
actual_libs.push_back(li->first);
|
||||
}
|
||||
}
|
||||
|
||||
// Add these entries.
|
||||
this->AddLinkEntries(depender_index, actual_libs);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmComputeLinkDepends::AddLinkEntries(int depender_index,
|
||||
std::vector<std::string> const& libs)
|
||||
{
|
||||
// Track inferred dependency sets implied by this list.
|
||||
std::map<int, DependSet> dependSets;
|
||||
|
||||
// Loop over the libraries linked directly by the depender.
|
||||
for(std::vector<std::string>::const_iterator li = libs.begin();
|
||||
li != libs.end(); ++li)
|
||||
{
|
||||
// Skip entries that will resolve to the target getting linked or
|
||||
// are empty.
|
||||
if(*li == this->Target->GetName() || li->empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add a link entry for this item.
|
||||
int dependee_index = this->AddLinkEntry(li->first);
|
||||
int dependee_index = this->AddLinkEntry(*li);
|
||||
|
||||
// The depender must come before the dependee.
|
||||
if(depender_index >= 0)
|
||||
|
|
|
@ -66,9 +66,12 @@ private:
|
|||
typedef cmTarget::LinkLibraryVectorType LinkLibraryVectorType;
|
||||
|
||||
int AddLinkEntry(std::string const& item);
|
||||
void AddImportedLinkEntries(int depender_index, cmTarget* target);
|
||||
void AddVarLinkEntries(int depender_index, const char* value);
|
||||
void AddTargetLinkEntries(int depender_index,
|
||||
LinkLibraryVectorType const& libs);
|
||||
void AddLinkEntries(int depender_index,
|
||||
LinkLibraryVectorType const& libs);
|
||||
std::vector<std::string> const& libs);
|
||||
|
||||
// One entry for each unique item.
|
||||
std::vector<LinkEntry> EntryList;
|
||||
|
|
|
@ -301,11 +301,8 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
|
|||
{
|
||||
// Compute the proper name to use to link this library.
|
||||
const char* config = this->Config;
|
||||
bool implib = this->UseImportLibrary;
|
||||
bool impexe = (tgt &&
|
||||
tgt->GetType() == cmTarget::EXECUTABLE &&
|
||||
tgt->GetPropertyAsBool("ENABLE_EXPORTS"));
|
||||
if(impexe && !implib && !this->LoaderFlag)
|
||||
bool impexe = (tgt && tgt->IsExecutableWithExports());
|
||||
if(impexe && !this->UseImportLibrary && !this->LoaderFlag)
|
||||
{
|
||||
// Skip linking to executables on platforms with no import
|
||||
// libraries or loader flags.
|
||||
|
@ -325,13 +322,18 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
|
|||
// platform. Add it now.
|
||||
std::string linkItem;
|
||||
linkItem = this->LoaderFlag;
|
||||
std::string exe = tgt->GetFullPath(config, implib);
|
||||
std::string exe = tgt->GetFullPath(config, this->UseImportLibrary);
|
||||
linkItem += exe;
|
||||
this->Items.push_back(Item(linkItem, true));
|
||||
this->Depends.push_back(exe);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Decide whether to use an import library.
|
||||
bool implib =
|
||||
(this->UseImportLibrary &&
|
||||
(impexe || tgt->GetType() == cmTarget::SHARED_LIBRARY));
|
||||
|
||||
// Pass the full path to the target file.
|
||||
std::string lib = tgt->GetFullPath(config, implib);
|
||||
this->Depends.push_back(lib);
|
||||
|
@ -950,18 +952,8 @@ cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath,
|
|||
|
||||
// Try to get the soname of the library. Only files with this name
|
||||
// could possibly conflict.
|
||||
std::string soName;
|
||||
const char* soname = 0;
|
||||
if(!target->IsImported())
|
||||
{
|
||||
std::string name;
|
||||
std::string realName;
|
||||
std::string impName;
|
||||
std::string pdbName;
|
||||
target->GetLibraryNames(name, soName, realName, impName, pdbName,
|
||||
this->Config);
|
||||
soname = soName.c_str();
|
||||
}
|
||||
std::string soName = target->GetSOName(this->Config);
|
||||
const char* soname = soName.empty()? 0 : soName.c_str();
|
||||
|
||||
// Add the library runtime entry.
|
||||
this->AddLibraryRuntimeInfo(fullPath, soname);
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#include "cmExportBuildFileGenerator.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
|
||||
{
|
||||
// Create all the imported targets.
|
||||
for(std::vector<cmTarget*>::const_iterator
|
||||
tei = this->Exports->begin();
|
||||
tei != this->Exports->end(); ++tei)
|
||||
{
|
||||
cmTarget* te = *tei;
|
||||
this->ExportedTargets.insert(te);
|
||||
this->GenerateImportTargetCode(os, te);
|
||||
}
|
||||
|
||||
// Generate import file content for each configuration.
|
||||
for(std::vector<std::string>::const_iterator
|
||||
ci = this->Configurations.begin();
|
||||
ci != this->Configurations.end(); ++ci)
|
||||
{
|
||||
this->GenerateImportConfig(os, ci->c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmExportBuildFileGenerator
|
||||
::GenerateImportTargetsConfig(std::ostream& os,
|
||||
const char* config, std::string const& suffix)
|
||||
{
|
||||
for(std::vector<cmTarget*>::const_iterator
|
||||
tei = this->Exports->begin();
|
||||
tei != this->Exports->end(); ++tei)
|
||||
{
|
||||
// Collect import properties for this target.
|
||||
cmTarget* target = *tei;
|
||||
ImportPropertyMap properties;
|
||||
this->SetImportLocationProperty(config, suffix, target, properties);
|
||||
if(!properties.empty())
|
||||
{
|
||||
// Get the rest of the target details.
|
||||
this->SetImportDetailProperties(config, suffix,
|
||||
target, properties);
|
||||
|
||||
// TOOD: PUBLIC_HEADER_LOCATION
|
||||
// this->GenerateImportProperty(config, te->HeaderGenerator,
|
||||
// properties);
|
||||
|
||||
// Generate code in the export file.
|
||||
this->GenerateImportPropertyCode(os, config, target, properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmExportBuildFileGenerator
|
||||
::SetImportLocationProperty(const char* config, std::string const& suffix,
|
||||
cmTarget* target, ImportPropertyMap& properties)
|
||||
{
|
||||
// Get the makefile in which to lookup target information.
|
||||
cmMakefile* mf = target->GetMakefile();
|
||||
|
||||
// Add the main target file.
|
||||
{
|
||||
std::string prop = "IMPORTED_LOCATION";
|
||||
prop += suffix;
|
||||
std::string value = target->GetFullPath(config, false);
|
||||
properties[prop] = value;
|
||||
}
|
||||
|
||||
// Check whether this is a DLL platform.
|
||||
bool dll_platform =
|
||||
(mf->IsOn("WIN32") || mf->IsOn("CYGWIN") || mf->IsOn("MINGW"));
|
||||
|
||||
// Add the import library for windows DLLs.
|
||||
if(dll_platform &&
|
||||
(target->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||
target->IsExecutableWithExports()) &&
|
||||
mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"))
|
||||
{
|
||||
std::string prop = "IMPORTED_IMPLIB";
|
||||
prop += suffix;
|
||||
std::string value = target->GetFullPath(config, true);
|
||||
properties[prop] = value;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmExportBuildFileGenerator
|
||||
::ComplainAboutMissingTarget(cmTarget* target, const char* dep)
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "WARNING: EXPORT(...) includes target " << target->GetName()
|
||||
<< " which links to target \"" << dep
|
||||
<< "\" that is not in the export set.";
|
||||
cmSystemTools::Message(e.str().c_str());
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#ifndef cmExportBuildFileGenerator_h
|
||||
#define cmExportBuildFileGenerator_h
|
||||
|
||||
#include "cmExportFileGenerator.h"
|
||||
|
||||
/** \class cmExportBuildFileGenerator
|
||||
* \brief Generate a file exporting targets from a build tree.
|
||||
*
|
||||
* cmExportBuildFileGenerator generates a file exporting targets from
|
||||
* a build tree. A single file exports information for all
|
||||
* configurations built.
|
||||
*
|
||||
* This is used to implement the EXPORT() command.
|
||||
*/
|
||||
class cmExportBuildFileGenerator: public cmExportFileGenerator
|
||||
{
|
||||
public:
|
||||
/** Set the list of targets to export. */
|
||||
void SetExports(std::vector<cmTarget*> const* exports)
|
||||
{ this->Exports = exports; }
|
||||
|
||||
protected:
|
||||
// Implement virtual methods from the superclass.
|
||||
virtual bool GenerateMainFile(std::ostream& os);
|
||||
virtual void GenerateImportTargetsConfig(std::ostream& os,
|
||||
const char* config,
|
||||
std::string const& suffix);
|
||||
virtual void ComplainAboutMissingTarget(cmTarget* target, const char* dep);
|
||||
|
||||
/** Fill in properties indicating built file locations. */
|
||||
void SetImportLocationProperty(const char* config,
|
||||
std::string const& suffix,
|
||||
cmTarget* target,
|
||||
ImportPropertyMap& properties);
|
||||
|
||||
std::vector<cmTarget*> const* Exports;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -20,14 +20,13 @@
|
|||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmake.h"
|
||||
|
||||
#include <cmsys/auto_ptr.hxx>
|
||||
#include "cmExportBuildFileGenerator.h"
|
||||
|
||||
cmExportCommand::cmExportCommand()
|
||||
:cmCommand()
|
||||
,ArgumentGroup()
|
||||
,Targets(&Helper, "TARGETS")
|
||||
,Append(&Helper, "APPEND", &ArgumentGroup)
|
||||
,Prefix(&Helper, "PREFIX", &ArgumentGroup)
|
||||
,Namespace(&Helper, "NAMESPACE", &ArgumentGroup)
|
||||
,Filename(&Helper, "FILE", &ArgumentGroup)
|
||||
{
|
||||
// at first TARGETS
|
||||
|
@ -53,151 +52,131 @@ bool cmExportCommand
|
|||
if (!unknownArgs.empty())
|
||||
{
|
||||
this->SetError("Unknown arguments.");
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this->Targets.WasFound() == false)
|
||||
{
|
||||
this->SetError("TARGETS option missing.");
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if ( !this->Makefile->CanIWriteThisFile(this->Filename.GetString().c_str()) )
|
||||
if(!this->Filename.WasFound())
|
||||
{
|
||||
std::string e = "attempted to write a file: " + this->Filename.GetString()
|
||||
+ " into a source directory.";
|
||||
this->SetError(e.c_str());
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
this->SetError("FILE <filename> option missing.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if((this->Targets.GetVector().empty())||(this->Filename.GetString().empty()))
|
||||
// Make sure the file has a .cmake extension.
|
||||
if(cmSystemTools::GetFilenameLastExtension(this->Filename.GetCString())
|
||||
!= ".cmake")
|
||||
{
|
||||
return true;
|
||||
cmOStringStream e;
|
||||
e << "FILE option given filename \"" << this->Filename.GetString()
|
||||
<< "\" which does not have an extension of \".cmake\".\n";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Use copy-if-different if not appending.
|
||||
cmsys::auto_ptr<std::ofstream> foutPtr;
|
||||
if(this->Append.IsEnabled())
|
||||
// Get the file to write.
|
||||
std::string fname = this->Filename.GetString();
|
||||
if(cmSystemTools::FileIsFullPath(fname.c_str()))
|
||||
{
|
||||
cmsys::auto_ptr<std::ofstream> ap(
|
||||
new std::ofstream(this->Filename.GetString().c_str(), std::ios::app));
|
||||
foutPtr = ap;
|
||||
if(!this->Makefile->CanIWriteThisFile(fname.c_str()))
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "FILE option given filename \"" << fname
|
||||
<< "\" which is in the source tree.\n";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cmsys::auto_ptr<cmGeneratedFileStream> ap(
|
||||
new cmGeneratedFileStream(this->Filename.GetString().c_str(), true));
|
||||
ap->SetCopyIfDifferent(true);
|
||||
foutPtr = ap;
|
||||
// Interpret relative paths with respect to the current build dir.
|
||||
fname = this->Makefile->GetCurrentOutputDirectory();
|
||||
fname += "/";
|
||||
fname += this->Filename.GetString();
|
||||
}
|
||||
std::ostream& fout = *foutPtr.get();
|
||||
|
||||
if (!fout)
|
||||
// If no targets are to be exported we are done.
|
||||
if(this->Targets.GetVector().empty())
|
||||
{
|
||||
cmSystemTools::Error("Error Writing ", this->Filename.GetString().c_str());
|
||||
cmSystemTools::ReportLastSystemError("");
|
||||
return true;
|
||||
}
|
||||
|
||||
// the following code may move into an "export generator"
|
||||
// Compute the set of configurations.
|
||||
std::vector<std::string> configurationTypes;
|
||||
if(const char* types =
|
||||
this->Makefile->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
|
||||
{
|
||||
cmSystemTools::ExpandListArgument(types, configurationTypes);
|
||||
}
|
||||
if(configurationTypes.empty())
|
||||
{
|
||||
const char* config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
|
||||
if (config!=0)
|
||||
{
|
||||
configurationTypes.push_back(config);
|
||||
}
|
||||
}
|
||||
|
||||
for(std::vector<std::string>::const_iterator
|
||||
// Collect the targets to be exported.
|
||||
std::vector<cmTarget*> targets;
|
||||
for(std::vector<std::string>::const_iterator
|
||||
currentTarget = this->Targets.GetVector().begin();
|
||||
currentTarget != this->Targets.GetVector().end();
|
||||
++currentTarget)
|
||||
{
|
||||
cmTarget* target = this->Makefile->GetLocalGenerator()->
|
||||
GetGlobalGenerator()->FindTarget(0, currentTarget->c_str(), true);
|
||||
if (target == 0)
|
||||
if(cmTarget* target =
|
||||
this->Makefile->GetLocalGenerator()->
|
||||
GetGlobalGenerator()->FindTarget(0, currentTarget->c_str()))
|
||||
{
|
||||
std::string e = "detected unknown target: " + *currentTarget;
|
||||
this->SetError(e.c_str());
|
||||
cmSystemTools::SetFatalErrorOccured();
|
||||
if((target->GetType() == cmTarget::EXECUTABLE) ||
|
||||
(target->GetType() == cmTarget::STATIC_LIBRARY) ||
|
||||
(target->GetType() == cmTarget::SHARED_LIBRARY) ||
|
||||
(target->GetType() == cmTarget::MODULE_LIBRARY))
|
||||
{
|
||||
targets.push_back(target);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "given target \"" << *currentTarget
|
||||
<< "\" which is not an executable or library.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "given target \"" << *currentTarget
|
||||
<< "\" which is not built by this project.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for(std::vector<std::string>::const_iterator
|
||||
currentTarget = this->Targets.GetVector().begin();
|
||||
currentTarget != this->Targets.GetVector().end();
|
||||
++currentTarget)
|
||||
{
|
||||
// Look for a CMake target with the given name, which is an executable
|
||||
// and which can be run
|
||||
cmTarget* target = this->Makefile->GetLocalGenerator()->
|
||||
GetGlobalGenerator()->FindTarget(0, currentTarget->c_str(), true);
|
||||
if ((target != 0)
|
||||
&& ((target->GetType() == cmTarget::EXECUTABLE)
|
||||
|| (target->GetType() == cmTarget::STATIC_LIBRARY)
|
||||
|| (target->GetType() == cmTarget::SHARED_LIBRARY)
|
||||
|| (target->GetType() == cmTarget::MODULE_LIBRARY)))
|
||||
{
|
||||
switch (target->GetType())
|
||||
{
|
||||
case cmTarget::EXECUTABLE:
|
||||
fout << "ADD_EXECUTABLE("
|
||||
<< this->Prefix.GetString().c_str() << currentTarget->c_str()
|
||||
<< " IMPORT )\n";
|
||||
break;
|
||||
case cmTarget::STATIC_LIBRARY:
|
||||
fout << "ADD_LIBRARY("
|
||||
<< this->Prefix.GetString().c_str() << currentTarget->c_str()
|
||||
<< " STATIC IMPORT )\n";
|
||||
break;
|
||||
case cmTarget::SHARED_LIBRARY:
|
||||
fout << "ADD_LIBRARY("
|
||||
<< this->Prefix.GetString().c_str() << currentTarget->c_str()
|
||||
<< " SHARED IMPORT )\n";
|
||||
break;
|
||||
case cmTarget::MODULE_LIBRARY:
|
||||
fout << "ADD_LIBRARY("
|
||||
<< this->Prefix.GetString().c_str() << currentTarget->c_str()
|
||||
<< " MODULE IMPORT )\n";
|
||||
break;
|
||||
default: // should never happen
|
||||
break;
|
||||
}
|
||||
// Setup export file generation.
|
||||
cmExportBuildFileGenerator ebfg;
|
||||
ebfg.SetExportFile(fname.c_str());
|
||||
ebfg.SetNamespace(this->Namespace.GetCString());
|
||||
ebfg.SetExports(&targets);
|
||||
|
||||
fout << "SET_TARGET_PROPERTIES(" << this->Prefix.GetString().c_str()
|
||||
<< currentTarget->c_str() << " PROPERTIES \n"
|
||||
<<" LOCATION \""<< target->GetLocation(0)<<"\"\n";
|
||||
for(std::vector<std::string>::const_iterator
|
||||
currentConfig = configurationTypes.begin();
|
||||
currentConfig != configurationTypes.end();
|
||||
++currentConfig)
|
||||
{
|
||||
if (!currentConfig->empty())
|
||||
{
|
||||
const char* loc = target->GetLocation(currentConfig->c_str());
|
||||
if (loc && *loc)
|
||||
{
|
||||
fout << " " << currentConfig->c_str()
|
||||
<< "_LOCATION \"" << loc << "\"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
fout << " )\n\n";
|
||||
// Compute the set of configurations exported.
|
||||
if(const char* types =
|
||||
this->Makefile->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
|
||||
{
|
||||
std::vector<std::string> configurationTypes;
|
||||
cmSystemTools::ExpandListArgument(types, configurationTypes);
|
||||
for(std::vector<std::string>::const_iterator
|
||||
ci = configurationTypes.begin();
|
||||
ci != configurationTypes.end(); ++ci)
|
||||
{
|
||||
ebfg.AddConfiguration(ci->c_str());
|
||||
}
|
||||
}
|
||||
else if(const char* config =
|
||||
this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"))
|
||||
{
|
||||
ebfg.AddConfiguration(config);
|
||||
}
|
||||
else
|
||||
{
|
||||
ebfg.AddConfiguration("");
|
||||
}
|
||||
|
||||
// Generate the import file.
|
||||
if(!ebfg.GenerateImportFile())
|
||||
{
|
||||
this->SetError("could not write export file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ public:
|
|||
virtual const char* GetTerseDocumentation()
|
||||
{
|
||||
return
|
||||
"Write out the dependency information for all targets of a project.";
|
||||
"Export targets from the build tree for use by outside projects.";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,15 +64,23 @@ public:
|
|||
virtual const char* GetFullDocumentation()
|
||||
{
|
||||
return
|
||||
" export(TARGETS tgt1 ... tgtN [PREFIX <prefix>] FILE <filename> "
|
||||
"[APPEND])\n"
|
||||
"Create a file that can be included into a CMake listfile with the "
|
||||
"INCLUDE command. The file will contain a number of SET commands "
|
||||
"that will set all the variables needed for library dependency "
|
||||
"information. This should be the last command in the top level "
|
||||
"CMakeLists.txt file of the project. If the APPEND option is "
|
||||
"specified, the SET commands will be appended to the given file "
|
||||
"instead of replacing it.";
|
||||
" export(TARGETS [target1 [target2 [...]]] [NAMESPACE <namespace>]\n"
|
||||
" FILE <filename>)\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 "
|
||||
"that can run on the host platform in one project and then import "
|
||||
"them into another project being compiled for the target platform. "
|
||||
"If the NAMESPACE option is given the <namespace> string will be "
|
||||
"prepended to all target names written to the file. "
|
||||
"If a library target is included in the export but "
|
||||
"a target to which it links is not included the behavior is "
|
||||
"unspecified."
|
||||
"\n"
|
||||
"The file created by this command is specific to the build tree and "
|
||||
"should never be installed. "
|
||||
"See the install(EXPORT) command to export targets from an "
|
||||
"installation tree.";
|
||||
}
|
||||
|
||||
cmTypeMacro(cmExportCommand, cmCommand);
|
||||
|
@ -80,8 +88,7 @@ public:
|
|||
private:
|
||||
cmCommandArgumentGroup ArgumentGroup;
|
||||
cmCAStringVector Targets;
|
||||
cmCAEnabler Append;
|
||||
cmCAString Prefix;
|
||||
cmCAString Namespace;
|
||||
cmCAString Filename;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,281 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#include "cmExportFileGenerator.h"
|
||||
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmSystemTools.h"
|
||||
#include "cmTarget.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmExportFileGenerator::AddConfiguration(const char* config)
|
||||
{
|
||||
this->Configurations.push_back(config);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmExportFileGenerator::SetExportFile(const char* mainFile)
|
||||
{
|
||||
this->MainImportFile = mainFile;
|
||||
this->FileDir =
|
||||
cmSystemTools::GetFilenamePath(this->MainImportFile);
|
||||
this->FileBase =
|
||||
cmSystemTools::GetFilenameWithoutLastExtension(this->MainImportFile);
|
||||
this->FileExt =
|
||||
cmSystemTools::GetFilenameLastExtension(this->MainImportFile);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmExportFileGenerator::GenerateImportFile()
|
||||
{
|
||||
// Open the output file to generate it.
|
||||
cmGeneratedFileStream exportFileStream(this->MainImportFile.c_str(), true);
|
||||
if(!exportFileStream)
|
||||
{
|
||||
std::string se = cmSystemTools::GetLastSystemError();
|
||||
cmOStringStream e;
|
||||
e << "cannot write to file \"" << this->MainImportFile
|
||||
<< "\": " << se;
|
||||
cmSystemTools::Error(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
std::ostream& os = exportFileStream;
|
||||
|
||||
// Start with the import file header.
|
||||
this->GenerateImportHeaderCode(os);
|
||||
|
||||
// Create all the imported targets.
|
||||
bool result = this->GenerateMainFile(os);
|
||||
|
||||
// End with the import file footer.
|
||||
this->GenerateImportFooterCode(os);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
|
||||
const char* config)
|
||||
{
|
||||
// Construct the property configuration suffix.
|
||||
std::string suffix = "_";
|
||||
if(config && *config)
|
||||
{
|
||||
suffix += cmSystemTools::UpperCase(config);
|
||||
}
|
||||
else
|
||||
{
|
||||
suffix += "NOCONFIG";
|
||||
}
|
||||
|
||||
// Generate the per-config target information.
|
||||
this->GenerateImportTargetsConfig(os, config, suffix);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmExportFileGenerator
|
||||
::SetImportDetailProperties(const char* config, std::string const& suffix,
|
||||
cmTarget* target, ImportPropertyMap& properties)
|
||||
{
|
||||
// Get the makefile in which to lookup target information.
|
||||
cmMakefile* mf = target->GetMakefile();
|
||||
|
||||
// Add the soname for unix shared libraries.
|
||||
if(target->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||
target->GetType() == cmTarget::MODULE_LIBRARY)
|
||||
{
|
||||
// Check whether this is a DLL platform.
|
||||
bool dll_platform =
|
||||
(mf->IsOn("WIN32") || mf->IsOn("CYGWIN") || mf->IsOn("MINGW"));
|
||||
if(!dll_platform)
|
||||
{
|
||||
std::string soname = target->GetSOName(config);
|
||||
std::string prop = "IMPORTED_SONAME";
|
||||
prop += suffix;
|
||||
properties[prop] = soname;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the transitive link dependencies for this configuration.
|
||||
{
|
||||
// Compute which library configuration to link.
|
||||
cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED;
|
||||
if(config && cmSystemTools::UpperCase(config) == "DEBUG")
|
||||
{
|
||||
linkType = cmTarget::DEBUG;
|
||||
}
|
||||
|
||||
// Construct the property value.
|
||||
cmTarget::LinkLibraryVectorType const& libs =
|
||||
target->GetOriginalLinkLibraries();
|
||||
std::string link_libs;
|
||||
const char* sep = "";
|
||||
for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin();
|
||||
li != libs.end(); ++li)
|
||||
{
|
||||
// Skip entries that will resolve to the target itself, are empty,
|
||||
// or are not meant for this configuration.
|
||||
if(li->first == target->GetName() || li->first.empty() ||
|
||||
!(li->second == cmTarget::GENERAL || li->second == linkType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Separate this from the previous entry.
|
||||
link_libs += sep;
|
||||
sep = ";";
|
||||
|
||||
// Append this entry.
|
||||
if(cmTarget* tgt = mf->FindTargetToUse(li->first.c_str()))
|
||||
{
|
||||
// This is a target. Make sure it is included in the export.
|
||||
if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
|
||||
{
|
||||
// The target is in the export. Append it with the export
|
||||
// namespace.
|
||||
link_libs += this->Namespace;
|
||||
link_libs += li->first;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The target is not in the export. This is probably
|
||||
// user-error. Warn but add it anyway.
|
||||
this->ComplainAboutMissingTarget(target, li->first.c_str());
|
||||
link_libs += li->first;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Append the raw name.
|
||||
link_libs += li->first;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the property.
|
||||
std::string prop = "IMPORTED_LINK_LIBRARIES";
|
||||
prop += suffix;
|
||||
properties[prop] = link_libs;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
|
||||
const char* config)
|
||||
{
|
||||
os << "#----------------------------------------------------------------\n"
|
||||
<< "# Generated CMake target import file";
|
||||
if(config)
|
||||
{
|
||||
os << " for configuration \"" << config << "\".\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
os << ".\n";
|
||||
}
|
||||
os << "#----------------------------------------------------------------\n"
|
||||
<< "\n";
|
||||
this->GenerateImportVersionCode(os);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmExportFileGenerator::GenerateImportFooterCode(std::ostream& os)
|
||||
{
|
||||
os << "# Commands beyond this point should not need to know the version.\n"
|
||||
<< "SET(CMAKE_IMPORT_FILE_VERSION)\n";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
|
||||
{
|
||||
// Store an import file format version. This will let us change the
|
||||
// format later while still allowing old import files to work.
|
||||
os << "# Commands may need to know the format version.\n"
|
||||
<< "SET(CMAKE_IMPORT_FILE_VERSION 1)\n"
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmExportFileGenerator
|
||||
::GenerateImportTargetCode(std::ostream& os, cmTarget* target)
|
||||
{
|
||||
// Construct the imported target name.
|
||||
std::string targetName = this->Namespace;
|
||||
targetName += target->GetName();
|
||||
|
||||
// Create the imported target.
|
||||
os << "# Create imported target " << targetName << "\n";
|
||||
switch(target->GetType())
|
||||
{
|
||||
case cmTarget::EXECUTABLE:
|
||||
os << "ADD_EXECUTABLE(" << targetName << " IMPORTED)\n";
|
||||
break;
|
||||
case cmTarget::STATIC_LIBRARY:
|
||||
os << "ADD_LIBRARY(" << targetName << " STATIC IMPORTED)\n";
|
||||
break;
|
||||
case cmTarget::SHARED_LIBRARY:
|
||||
os << "ADD_LIBRARY(" << targetName << " SHARED IMPORTED)\n";
|
||||
break;
|
||||
case cmTarget::MODULE_LIBRARY:
|
||||
os << "ADD_LIBRARY(" << targetName << " MODULE IMPORTED)\n";
|
||||
break;
|
||||
default: // should never happen
|
||||
break;
|
||||
}
|
||||
if(target->IsExecutableWithExports())
|
||||
{
|
||||
os << "SET_PROPERTY(TARGET " << targetName
|
||||
<< " PROPERTY IMPORTED_ENABLE_EXPORTS 1)\n";
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmExportFileGenerator
|
||||
::GenerateImportPropertyCode(std::ostream& os, const char* config,
|
||||
cmTarget* target,
|
||||
ImportPropertyMap const& properties)
|
||||
{
|
||||
// Construct the imported target name.
|
||||
std::string targetName = this->Namespace;
|
||||
targetName += target->GetName();
|
||||
|
||||
// Set the import properties.
|
||||
os << "# Import target \"" << targetName << "\" for configuration \""
|
||||
<< config << "\"\n";
|
||||
os << "SET_PROPERTY(TARGET " << targetName
|
||||
<< " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
|
||||
if(config && *config)
|
||||
{
|
||||
os << cmSystemTools::UpperCase(config);
|
||||
}
|
||||
else
|
||||
{
|
||||
os << "NOCONFIG";
|
||||
}
|
||||
os << ")\n";
|
||||
os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n";
|
||||
for(ImportPropertyMap::const_iterator pi = properties.begin();
|
||||
pi != properties.end(); ++pi)
|
||||
{
|
||||
os << " " << pi->first << " \"" << pi->second << "\"\n";
|
||||
}
|
||||
os << " )\n"
|
||||
<< "\n";
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#ifndef cmExportFileGenerator_h
|
||||
#define cmExportFileGenerator_h
|
||||
|
||||
#include "cmCommand.h"
|
||||
|
||||
/** \class cmExportFileGenerator
|
||||
* \brief Generate a file exporting targets from a build or install tree.
|
||||
*
|
||||
* cmExportFileGenerator is the superclass for
|
||||
* cmExportBuildFileGenerator and cmExportInstallFileGenerator. It
|
||||
* contains common code generation routines for the two kinds of
|
||||
* export implementations.
|
||||
*/
|
||||
class cmExportFileGenerator
|
||||
{
|
||||
public:
|
||||
/** Set the full path to the export file to generate. */
|
||||
void SetExportFile(const char* mainFile);
|
||||
|
||||
/** Set the namespace in which to place exported target names. */
|
||||
void SetNamespace(const char* ns) { this->Namespace = ns; }
|
||||
|
||||
/** Add a configuration to be exported. */
|
||||
void AddConfiguration(const char* config);
|
||||
|
||||
/** Actually generate the export file. Returns whether there was an
|
||||
error. */
|
||||
bool GenerateImportFile();
|
||||
protected:
|
||||
|
||||
typedef std::map<cmStdString, cmStdString> ImportPropertyMap;
|
||||
|
||||
// Generate per-configuration target information to the given output
|
||||
// stream.
|
||||
void GenerateImportConfig(std::ostream& os, const char* config);
|
||||
|
||||
// Methods to implement export file code generation.
|
||||
void GenerateImportHeaderCode(std::ostream& os, const char* config = 0);
|
||||
void GenerateImportFooterCode(std::ostream& os);
|
||||
void GenerateImportVersionCode(std::ostream& os);
|
||||
void GenerateImportTargetCode(std::ostream& os, cmTarget* target);
|
||||
void GenerateImportPropertyCode(std::ostream& os, const char* config,
|
||||
cmTarget* target,
|
||||
ImportPropertyMap const& properties);
|
||||
|
||||
// Collect properties with detailed information about targets beyond
|
||||
// their location on disk.
|
||||
void SetImportDetailProperties(const char* config,
|
||||
std::string const& suffix, cmTarget* target,
|
||||
ImportPropertyMap& properties);
|
||||
|
||||
/** Each subclass knows how to generate its kind of export file. */
|
||||
virtual bool GenerateMainFile(std::ostream& os) = 0;
|
||||
|
||||
/** Each subclass knows where the target files are located. */
|
||||
virtual void GenerateImportTargetsConfig(std::ostream& os,
|
||||
const char* config,
|
||||
std::string const& suffix) = 0;
|
||||
|
||||
/** Each subclass knows how to complain about a target that is
|
||||
missing from an export set. */
|
||||
virtual void ComplainAboutMissingTarget(cmTarget*, const char* dep) = 0;
|
||||
|
||||
// The namespace in which the exports are placed in the generated file.
|
||||
std::string Namespace;
|
||||
|
||||
// The set of configurations to export.
|
||||
std::vector<std::string> Configurations;
|
||||
|
||||
// The file to generate.
|
||||
std::string MainImportFile;
|
||||
std::string FileDir;
|
||||
std::string FileBase;
|
||||
std::string FileExt;
|
||||
|
||||
// The set of targets included in the export.
|
||||
std::set<cmTarget*> ExportedTargets;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,259 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#include "cmExportInstallFileGenerator.h"
|
||||
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmInstallExportGenerator.h"
|
||||
#include "cmInstallTargetGenerator.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmExportInstallFileGenerator
|
||||
::cmExportInstallFileGenerator(cmInstallExportGenerator* iegen):
|
||||
InstallExportGenerator(iegen)
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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;
|
||||
this->ExportedTargets.insert(te->Target);
|
||||
this->GenerateImportTargetCode(os, te->Target);
|
||||
}
|
||||
|
||||
// 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->FileBase << "-*" << this->FileExt << "\")\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;
|
||||
this->SetImportLocationProperty(config, suffix,
|
||||
te->ArchiveGenerator, properties);
|
||||
this->SetImportLocationProperty(config, suffix,
|
||||
te->LibraryGenerator, properties);
|
||||
this->SetImportLocationProperty(config, suffix,
|
||||
te->RuntimeGenerator, properties);
|
||||
|
||||
// TODO: Frameworks?
|
||||
// TODO: Bundles?
|
||||
|
||||
// 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->GenerateImportProperty(config, te->HeaderGenerator,
|
||||
// properties);
|
||||
|
||||
// Generate code in the export file.
|
||||
this->GenerateImportPropertyCode(os, config, te->Target, properties);
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
// Skip rules that do not match this configuration.
|
||||
if(!(itgen && itgen->InstallsForConfig(config)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
// Construct the property name.
|
||||
std::string prop = (itgen->IsImportLibrary()?
|
||||
"IMPORTED_IMPLIB" : "IMPORTED_LOCATION");
|
||||
prop += suffix;
|
||||
|
||||
// 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 += "/";
|
||||
|
||||
// Append the installed file name.
|
||||
value += itgen->GetInstallFilename(config);
|
||||
|
||||
// Store the property.
|
||||
properties[prop] = value;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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* target, const char* dep)
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "WARNING: INSTALL(EXPORT \"" << this->Name << "\" ...) "
|
||||
<< "includes target " << target->GetName()
|
||||
<< " which links to target \"" << dep
|
||||
<< "\" that is not in the export set.";
|
||||
cmSystemTools::Message(e.str().c_str());
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#ifndef cmExportInstallFileGenerator_h
|
||||
#define cmExportInstallFileGenerator_h
|
||||
|
||||
#include "cmExportFileGenerator.h"
|
||||
|
||||
class cmInstallExportGenerator;
|
||||
class cmInstallFilesGenerator;
|
||||
class cmInstallTargetGenerator;
|
||||
class cmTargetExport;
|
||||
|
||||
/** \class cmExportInstallFileGenerator
|
||||
* \brief Generate a file exporting targets from an install tree.
|
||||
*
|
||||
* cmExportInstallFileGenerator generates files exporting targets from
|
||||
* install an installation tree. The files are placed in a temporary
|
||||
* location for installation by cmInstallExportGenerator. One main
|
||||
* file is generated that creates the imported targets and loads
|
||||
* per-configuration files. Target locations and settings for each
|
||||
* configuration are written to these per-configuration files. After
|
||||
* installation the main file loads the configurations that have been
|
||||
* installed.
|
||||
*
|
||||
* This is used to implement the INSTALL(EXPORT) command.
|
||||
*/
|
||||
class cmExportInstallFileGenerator: public cmExportFileGenerator
|
||||
{
|
||||
public:
|
||||
/** Construct with the export installer that will install the
|
||||
files. */
|
||||
cmExportInstallFileGenerator(cmInstallExportGenerator* iegen);
|
||||
|
||||
/** Set the name of the export associated with the files. This is
|
||||
the name given to the install(EXPORT) command mode. */
|
||||
void SetName(const char* name) { this->Name = name; }
|
||||
|
||||
/** Set the set of targets to be exported. These are the targets
|
||||
associated with the export name. */
|
||||
void SetExportSet(std::vector<cmTargetExport*> const* eSet)
|
||||
{ this->ExportSet = eSet; }
|
||||
|
||||
/** Get the per-config file generated for each configuraiton. This
|
||||
maps from the configuration name to the file temporary location
|
||||
for installation. */
|
||||
std::map<cmStdString, cmStdString> const& GetConfigImportFiles()
|
||||
{ return this->ConfigImportFiles; }
|
||||
protected:
|
||||
|
||||
// Implement virtual methods from the superclass.
|
||||
virtual bool GenerateMainFile(std::ostream& os);
|
||||
virtual void GenerateImportTargetsConfig(std::ostream& os,
|
||||
const char* config,
|
||||
std::string const& suffix);
|
||||
virtual void ComplainAboutMissingTarget(cmTarget* target, const char* dep);
|
||||
|
||||
/** Generate a per-configuration file for the targets. */
|
||||
bool GenerateImportFileConfig(const char* config);
|
||||
|
||||
/** Fill in properties indicating installed file locations. */
|
||||
void SetImportLocationProperty(const char* config,
|
||||
std::string const& suffix,
|
||||
cmInstallTargetGenerator* itgen,
|
||||
ImportPropertyMap& properties);
|
||||
|
||||
void ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen);
|
||||
|
||||
cmInstallExportGenerator* InstallExportGenerator;
|
||||
std::string Name;
|
||||
std::vector<cmTargetExport*> const* ExportSet;
|
||||
|
||||
std::string ImportPrefix;
|
||||
|
||||
// The import file generated for each configuration.
|
||||
std::map<cmStdString, cmStdString> ConfigImportFiles;
|
||||
};
|
||||
|
||||
/*
|
||||
cmTargetExport is used in cmGlobalGenerator to collect the install
|
||||
generators for targets associated with an export.
|
||||
*/
|
||||
class cmTargetExport
|
||||
{
|
||||
public:
|
||||
cmTargetExport(cmTarget* tgt,
|
||||
cmInstallTargetGenerator* archive,
|
||||
cmInstallTargetGenerator* runtime,
|
||||
cmInstallTargetGenerator* library,
|
||||
cmInstallTargetGenerator* framework,
|
||||
cmInstallTargetGenerator* bundle,
|
||||
cmInstallFilesGenerator* headers
|
||||
) : Target(tgt), ArchiveGenerator(archive),
|
||||
RuntimeGenerator(runtime), LibraryGenerator(library),
|
||||
FrameworkGenerator(framework), BundleGenerator(bundle),
|
||||
HeaderGenerator(headers) {}
|
||||
|
||||
cmTarget* Target;
|
||||
cmInstallTargetGenerator* ArchiveGenerator;
|
||||
cmInstallTargetGenerator* RuntimeGenerator;
|
||||
cmInstallTargetGenerator* LibraryGenerator;
|
||||
cmInstallTargetGenerator* FrameworkGenerator;
|
||||
cmInstallTargetGenerator* BundleGenerator;
|
||||
cmInstallFilesGenerator* HeaderGenerator;
|
||||
private:
|
||||
cmTargetExport();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -260,9 +260,7 @@ bool cmGetPropertyCommand::HandleTargetMode()
|
|||
return false;
|
||||
}
|
||||
|
||||
if(cmTarget* target =
|
||||
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
|
||||
->FindTarget(0, this->Name.c_str(), true))
|
||||
if(cmTarget* target = this->Makefile->FindTargetToUse(this->Name.c_str()))
|
||||
{
|
||||
return this->StoreResult(target->GetProperty(this->PropertyName.c_str()));
|
||||
}
|
||||
|
|
|
@ -28,9 +28,7 @@ bool cmGetTargetPropertyCommand
|
|||
std::string var = args[0].c_str();
|
||||
const char* targetName = args[1].c_str();
|
||||
|
||||
cmTarget *tgt = this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
|
||||
->FindTarget(0, targetName, true);
|
||||
if (tgt)
|
||||
if(cmTarget* tgt = this->Makefile->FindTargetToUse(targetName))
|
||||
{
|
||||
cmTarget& target = *tgt;
|
||||
const char *prop = target.GetProperty(args[2].c_str());
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "cmMakefile.h"
|
||||
#include "cmSourceFile.h"
|
||||
#include "cmVersion.h"
|
||||
#include "cmInstallExportGenerator.h"
|
||||
#include "cmExportInstallFileGenerator.h"
|
||||
|
||||
#include <cmsys/Directory.hxx>
|
||||
|
||||
|
@ -693,7 +693,6 @@ void cmGlobalGenerator::Configure()
|
|||
this->LocalGenerators.clear();
|
||||
this->TargetDependencies.clear();
|
||||
this->TotalTargets.clear();
|
||||
this->ImportedTotalTargets.clear();
|
||||
this->LocalGeneratorToTargetMap.clear();
|
||||
this->ProjectMap.clear();
|
||||
|
||||
|
@ -1321,9 +1320,8 @@ cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const char* start_dir)
|
|||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmTarget* cmGlobalGenerator::FindTarget(const char* project,
|
||||
const char* name,
|
||||
bool useImportedTargets)
|
||||
cmTarget*
|
||||
cmGlobalGenerator::FindTarget(const char* project, const char* name)
|
||||
{
|
||||
// if project specific
|
||||
if(project)
|
||||
|
@ -1331,8 +1329,7 @@ cmTarget* cmGlobalGenerator::FindTarget(const char* project,
|
|||
std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
|
||||
for(unsigned int i = 0; i < gens->size(); ++i)
|
||||
{
|
||||
cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name,
|
||||
useImportedTargets);
|
||||
cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name);
|
||||
if(ret)
|
||||
{
|
||||
return ret;
|
||||
|
@ -1348,16 +1345,6 @@ cmTarget* cmGlobalGenerator::FindTarget(const char* project,
|
|||
{
|
||||
return i->second;
|
||||
}
|
||||
|
||||
if ( useImportedTargets )
|
||||
{
|
||||
std::map<cmStdString,cmTarget *>::iterator importedTarget =
|
||||
this->ImportedTotalTargets.find ( name );
|
||||
if ( importedTarget != this->ImportedTotalTargets.end() )
|
||||
{
|
||||
return importedTarget->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1370,7 +1357,7 @@ bool cmGlobalGenerator::NameResolvesToFramework(const std::string& libname)
|
|||
return true;
|
||||
}
|
||||
|
||||
if(cmTarget* tgt = this->FindTarget(0, libname.c_str(), true))
|
||||
if(cmTarget* tgt = this->FindTarget(0, libname.c_str()))
|
||||
{
|
||||
if(tgt->GetType() == cmTarget::SHARED_LIBRARY &&
|
||||
tgt->GetPropertyAsBool("FRAMEWORK"))
|
||||
|
@ -1758,12 +1745,12 @@ cmGlobalGenerator::ConsiderTargetDepends(cmTarget const* depender,
|
|||
{
|
||||
// Check the target's makefile first.
|
||||
cmTarget const* dependee =
|
||||
depender->GetMakefile()->FindTarget(dependee_name, false);
|
||||
depender->GetMakefile()->FindTarget(dependee_name);
|
||||
|
||||
// Then search globally.
|
||||
if(!dependee)
|
||||
{
|
||||
dependee = this->FindTarget(0, dependee_name, false);
|
||||
dependee = this->FindTarget(0, dependee_name);
|
||||
}
|
||||
|
||||
// If not found then skip then the dependee.
|
||||
|
@ -1842,14 +1829,8 @@ cmGlobalGenerator
|
|||
|
||||
void cmGlobalGenerator::AddTarget(cmTargets::value_type &v)
|
||||
{
|
||||
if (v.second.IsImported())
|
||||
{
|
||||
this->ImportedTotalTargets[v.first] = &v.second;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->TotalTargets[v.first] = &v.second;
|
||||
}
|
||||
assert(!v.second.IsImported());
|
||||
this->TotalTargets[v.first] = &v.second;
|
||||
}
|
||||
|
||||
void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
|
||||
|
|
|
@ -186,9 +186,7 @@ public:
|
|||
void FindMakeProgram(cmMakefile*);
|
||||
|
||||
///! Find a target by name by searching the local generators.
|
||||
cmTarget* FindTarget(const char* project,
|
||||
const char* name,
|
||||
bool useImportedTargets);
|
||||
cmTarget* FindTarget(const char* project, const char* name);
|
||||
|
||||
/** Determine if a name resolves to a framework on disk or a built target
|
||||
that is a framework. */
|
||||
|
@ -297,9 +295,8 @@ private:
|
|||
std::map<cmStdString, cmStdString> ExtensionToLanguage;
|
||||
std::map<cmStdString, int> LanguageToLinkerPreference;
|
||||
|
||||
// this is used to improve performance
|
||||
// this is used to improve performance
|
||||
std::map<cmStdString,cmTarget *> TotalTargets;
|
||||
std::map<cmStdString,cmTarget *> ImportedTotalTargets;
|
||||
|
||||
cmExternalMakefileProjectGenerator* ExtraGenerator;
|
||||
|
||||
|
|
|
@ -399,7 +399,7 @@ void cmGlobalVisualStudio6Generator::WriteProject(std::ostream& fout,
|
|||
if(j->first != dspname)
|
||||
{
|
||||
// is the library part of this DSW ? If so add dependency
|
||||
if(this->FindTarget(0, j->first.c_str(), false))
|
||||
if(this->FindTarget(0, j->first.c_str()))
|
||||
{
|
||||
fout << "Begin Project Dependency\n";
|
||||
fout << "Project_Dep_Name " << j->first.c_str() << "\n";
|
||||
|
|
|
@ -338,8 +338,7 @@ cmGlobalVisualStudio71Generator
|
|||
if(j->first != dspname)
|
||||
{
|
||||
// is the library part of this SLN ? If so add dependency
|
||||
if(this->FindTarget(this->CurrentProject.c_str(),
|
||||
j->first.c_str(), false))
|
||||
if(this->FindTarget(this->CurrentProject.c_str(), j->first.c_str()))
|
||||
{
|
||||
fout << "\t\t{" << this->GetGUID(j->first.c_str()) << "} = {"
|
||||
<< this->GetGUID(j->first.c_str()) << "}\n";
|
||||
|
|
|
@ -611,8 +611,7 @@ cmGlobalVisualStudio7Generator
|
|||
if(j->first != dspname)
|
||||
{
|
||||
// is the library part of this SLN ? If so add dependency
|
||||
if(this->FindTarget(this->CurrentProject.c_str(),
|
||||
j->first.c_str(), false))
|
||||
if(this->FindTarget(this->CurrentProject.c_str(), j->first.c_str()))
|
||||
{
|
||||
std::string guid = this->GetGUID(j->first.c_str());
|
||||
if(guid.size() == 0)
|
||||
|
|
|
@ -138,7 +138,7 @@ void cmGlobalVisualStudio8Generator::Generate()
|
|||
mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false,
|
||||
no_working_directory, no_depends,
|
||||
noCommandLines);
|
||||
cmTarget* tgt = mf->FindTarget(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false);
|
||||
cmTarget* tgt = mf->FindTarget(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
|
||||
if(!tgt)
|
||||
{
|
||||
cmSystemTools::Error("Error adding target "
|
||||
|
|
|
@ -270,7 +270,7 @@ cmGlobalVisualStudioGenerator::FixUtilityDependsForTarget(cmTarget& target)
|
|||
target.GetUtilities().begin();
|
||||
ui != target.GetUtilities().end(); ++ui)
|
||||
{
|
||||
if(cmTarget* depTarget = this->FindTarget(0, ui->c_str(), false))
|
||||
if(cmTarget* depTarget = this->FindTarget(0, ui->c_str()))
|
||||
{
|
||||
if(depTarget->GetType() == cmTarget::STATIC_LIBRARY ||
|
||||
depTarget->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||
|
@ -315,7 +315,7 @@ cmGlobalVisualStudioGenerator::CreateUtilityDependTarget(cmTarget& target)
|
|||
this->CreateGUID(altNameStr.c_str());
|
||||
|
||||
// The intermediate target should depend on the original target.
|
||||
if(cmTarget* alt = this->FindTarget(0, altNameStr.c_str(), false))
|
||||
if(cmTarget* alt = this->FindTarget(0, altNameStr.c_str()))
|
||||
{
|
||||
alt->AddUtility(target.GetName());
|
||||
}
|
||||
|
@ -371,7 +371,7 @@ cmGlobalVisualStudioGenerator::GetUtilityForTarget(cmTarget& target,
|
|||
{
|
||||
// The depender is a target that links. Lookup the dependee to
|
||||
// see if it provides an alternative dependency name.
|
||||
if(cmTarget* depTarget = this->FindTarget(0, name, false))
|
||||
if(cmTarget* depTarget = this->FindTarget(0, name))
|
||||
{
|
||||
// Check for an alternative name created by FixUtilityDepends.
|
||||
if(const char* altName =
|
||||
|
|
|
@ -279,7 +279,7 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
|
|||
mf->AddUtilityCommand("ALL_BUILD", true, no_depends,
|
||||
no_working_directory,
|
||||
"echo", "Build all projects");
|
||||
cmTarget* allbuild = mf->FindTarget("ALL_BUILD", false);
|
||||
cmTarget* allbuild = mf->FindTarget("ALL_BUILD");
|
||||
|
||||
// Add XCODE depend helper
|
||||
std::string dir = mf->GetCurrentOutputDirectory();
|
||||
|
@ -1346,7 +1346,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
|
|||
std::string pnprefix;
|
||||
std::string pnbase;
|
||||
std::string pnsuffix;
|
||||
target.GetFullName(pnprefix, pnbase, pnsuffix, configName);
|
||||
target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName);
|
||||
|
||||
// Store the product name for all target types.
|
||||
buildSettings->AddAttribute("PRODUCT_NAME",
|
||||
|
@ -2046,7 +2046,7 @@ void cmGlobalXCodeGenerator
|
|||
{
|
||||
// Add this dependency.
|
||||
cmTarget* t = this->FindTarget(this->CurrentProject.c_str(),
|
||||
lib->first.c_str(), false);
|
||||
lib->first.c_str());
|
||||
cmXCodeObject* dptarget = this->FindXCodeTarget(t);
|
||||
if(dptarget)
|
||||
{
|
||||
|
@ -2062,7 +2062,7 @@ void cmGlobalXCodeGenerator
|
|||
i != cmtarget->GetUtilities().end(); ++i)
|
||||
{
|
||||
cmTarget* t = this->FindTarget(this->CurrentProject.c_str(),
|
||||
i->c_str(), false);
|
||||
i->c_str());
|
||||
// if the target is in this project then make target depend
|
||||
// on it. It may not be in this project if this is a sub
|
||||
// project from the top.
|
||||
|
|
|
@ -51,8 +51,7 @@ bool cmIncludeExternalMSProjectCommand
|
|||
|
||||
// Create a target instance for this utility.
|
||||
cmTarget* target=this->Makefile->AddNewTarget(cmTarget::UTILITY,
|
||||
utility_name.c_str(),
|
||||
false);
|
||||
utility_name.c_str());
|
||||
target->SetProperty("EXCLUDE_FROM_ALL","FALSE");
|
||||
std::vector<std::string> no_outputs;
|
||||
cmCustomCommandLines commandLines;
|
||||
|
|
|
@ -300,7 +300,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
|
|||
++targetIt)
|
||||
{
|
||||
// Lookup this target in the current directory.
|
||||
if(cmTarget* target=this->Makefile->FindTarget(targetIt->c_str(), false))
|
||||
if(cmTarget* target=this->Makefile->FindTarget(targetIt->c_str()))
|
||||
{
|
||||
// Found the target. Check its type.
|
||||
if(target->GetType() != cmTarget::EXECUTABLE &&
|
||||
|
@ -489,7 +489,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
|
|||
// library. Install it to the archive destination if it
|
||||
// exists.
|
||||
if(dll_platform && !archiveArgs.GetDestination().empty() &&
|
||||
target.GetPropertyAsBool("ENABLE_EXPORTS"))
|
||||
target.IsExecutableWithExports())
|
||||
{
|
||||
// The import library uses the ARCHIVE properties.
|
||||
archiveGenerator = CreateInstallTargetGenerator(target,
|
||||
|
@ -1069,13 +1069,9 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Compute destination path.
|
||||
std::string dest;
|
||||
cmInstallCommandArguments::ComputeDestination(destination, dest);
|
||||
|
||||
// Create the directory install generator.
|
||||
this->Makefile->AddInstallGenerator(
|
||||
new cmInstallDirectoryGenerator(dirs, dest.c_str(),
|
||||
new cmInstallDirectoryGenerator(dirs, destination,
|
||||
permissions_file.c_str(),
|
||||
permissions_dir.c_str(),
|
||||
configurations,
|
||||
|
@ -1095,12 +1091,12 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
|
|||
{
|
||||
// This is the EXPORT mode.
|
||||
cmInstallCommandArguments ica;
|
||||
cmCAStringVector exports(&ica.Parser, "EXPORT");
|
||||
cmCAString prefix(&ica.Parser, "PREFIX", &ica.ArgumentGroup);
|
||||
cmCAString exp(&ica.Parser, "EXPORT");
|
||||
cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup);
|
||||
cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
|
||||
exports.Follows(0);
|
||||
exp.Follows(0);
|
||||
|
||||
ica.ArgumentGroup.Follows(&exports);
|
||||
ica.ArgumentGroup.Follows(&exp);
|
||||
std::vector<std::string> unknownArgs;
|
||||
ica.Parse(&args, &unknownArgs);
|
||||
|
||||
|
@ -1118,44 +1114,66 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
|
|||
return false;
|
||||
}
|
||||
|
||||
std::string cmakeDir = this->Makefile->GetHomeOutputDirectory();
|
||||
cmakeDir += cmake::GetCMakeFilesDirectory();
|
||||
for(std::vector<std::string>::const_iterator
|
||||
exportIt = exports.GetVector().begin();
|
||||
exportIt != exports.GetVector().end();
|
||||
++exportIt)
|
||||
// Make sure there is a destination.
|
||||
if(ica.GetDestination().empty())
|
||||
{
|
||||
const std::vector<cmTargetExport*>* exportSet = this->
|
||||
Makefile->GetLocalGenerator()->GetGlobalGenerator()->
|
||||
GetExportSet(exportIt->c_str());
|
||||
if (exportSet == 0)
|
||||
// A destination is required.
|
||||
cmOStringStream e;
|
||||
e << args[0] << " given no DESTINATION!";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the file name.
|
||||
std::string fname = filename.GetString();
|
||||
if(fname.find_first_of(":/\\") != fname.npos)
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << args[0] << " given invalid export file name \"" << fname << "\". "
|
||||
<< "The FILE argument may not contain a path. "
|
||||
<< "Specify the path in the DESTINATION argument.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the file extension.
|
||||
if(!fname.empty() &&
|
||||
cmSystemTools::GetFilenameLastExtension(fname) != ".cmake")
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << args[0] << " given invalid export file name \"" << fname << "\". "
|
||||
<< "The FILE argument must specify a name ending in \".cmake\".";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Construct the file name.
|
||||
if(fname.empty())
|
||||
{
|
||||
fname = exp.GetString();
|
||||
fname += ".cmake";
|
||||
|
||||
if(fname.find_first_of(":/\\") != fname.npos)
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "EXPORT given unknown export name \"" << exportIt->c_str() << "\".";
|
||||
e << args[0] << " given export name \"" << exp.GetString() << "\". "
|
||||
<< "This name cannot be safely converted to a file name. "
|
||||
<< "Specify a different export name or use the FILE option to set "
|
||||
<< "a file name explicitly.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the export install generator.
|
||||
cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator(
|
||||
ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
|
||||
ica.GetConfigurations(),0 , filename.GetCString(),
|
||||
prefix.GetCString(), cmakeDir.c_str());
|
||||
|
||||
if (exportGenerator->SetExportSet(exportIt->c_str(),exportSet))
|
||||
{
|
||||
this->Makefile->AddInstallGenerator(exportGenerator);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "EXPORT failed, maybe a target is exported more than once.";
|
||||
this->SetError(e.str().c_str());
|
||||
delete exportGenerator;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the export install generator.
|
||||
cmInstallExportGenerator* exportGenerator =
|
||||
new cmInstallExportGenerator(
|
||||
exp.GetCString(), ica.GetDestination().c_str(),
|
||||
ica.GetPermissions().c_str(), ica.GetConfigurations(),
|
||||
ica.GetComponent().c_str(), fname.c_str(),
|
||||
name_space.GetCString(), this->Makefile);
|
||||
this->Makefile->AddInstallGenerator(exportGenerator);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ public:
|
|||
"file to be installed does not exist. "
|
||||
"\n"
|
||||
"The TARGETS signature:\n"
|
||||
" install(TARGETS targets...\n"
|
||||
" install(TARGETS targets... [EXPORT <export-name>]\n"
|
||||
" [[ARCHIVE|LIBRARY|RUNTIME]\n"
|
||||
" [DESTINATION <dir>]\n"
|
||||
" [PERMISSIONS permissions...]\n"
|
||||
|
@ -145,6 +145,12 @@ public:
|
|||
"On non-DLL platforms mySharedLib will be installed to <prefix>/lib "
|
||||
"and /some/full/path."
|
||||
"\n"
|
||||
"The EXPORT option associates the installed target files with an "
|
||||
"export called <export-name>. "
|
||||
"It must appear before any RUNTIME, LIBRARY, or ARCHIVE options. "
|
||||
"See documentation of the install(EXPORT ...) signature below for "
|
||||
"details."
|
||||
"\n"
|
||||
"Installing a target with EXCLUDE_FROM_ALL set to true has "
|
||||
"undefined behavior."
|
||||
"\n"
|
||||
|
@ -248,6 +254,45 @@ public:
|
|||
"For example, the code\n"
|
||||
" install(CODE \"MESSAGE(\\\"Sample install message.\\\")\")\n"
|
||||
"will print a message during installation.\n"
|
||||
""
|
||||
"The EXPORT signature:\n"
|
||||
" install(EXPORT <export-name> DESTINATION <dir>\n"
|
||||
" [NAMESPACE <namespace>] [FILE <name>.cmake]\n"
|
||||
" [PERMISSIONS permissions...]\n"
|
||||
" [CONFIGURATIONS [Debug|Release|...]]\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. "
|
||||
"Target installations are associated with the export <export-name> "
|
||||
"using the EXPORT option of the install(TARGETS ...) signature "
|
||||
"documented above. The NAMESPACE option will prepend <namespace> to "
|
||||
"the target names as they are written to the import file. "
|
||||
"By default the generated file will be called <export-name>.cmake but "
|
||||
"the FILE option may be used to specify a different name. The value "
|
||||
"given to the FILE option must be a file name with the \".cmake\" "
|
||||
"extension. "
|
||||
"If a CONFIGURATIONS option is given then the file will only be "
|
||||
"installed when one of the named configurations is installed. "
|
||||
"Additionally, the generated import file will reference only the "
|
||||
"matching target configurations. "
|
||||
"If a COMPONENT option is specified that does not match that given "
|
||||
"to the targets associated with <export-name> the behavior is "
|
||||
"undefined. "
|
||||
"If a library target is included in the export but "
|
||||
"a target to which it links is not included the behavior is "
|
||||
"unspecified."
|
||||
"\n"
|
||||
"The EXPORT form is useful to help outside projects use targets built "
|
||||
"and installed by the current project. For example, the code\n"
|
||||
" install(TARGETS myexe EXPORT myproj DESTINATION bin)\n"
|
||||
" install(EXPORT myproj NAMESPACE mp_ DESTINATION lib/myproj)\n"
|
||||
"will install the executable myexe to <prefix>/bin and code to import "
|
||||
"it in the file \"<prefix>/lib/myproj/myproj.cmake\". "
|
||||
"An outside project may load this file with the include command "
|
||||
"and reference the myexe executable from the installation tree using "
|
||||
"the imported target name mp_myexe as if the target were built "
|
||||
"in its own tree."
|
||||
"\n"
|
||||
"NOTE: This command supercedes the INSTALL_TARGETS command and the "
|
||||
"target properties PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT. "
|
||||
"It also replaces the FILES forms of the INSTALL_FILES and "
|
||||
|
|
|
@ -44,9 +44,9 @@ cmInstallCommandArguments::cmInstallCommandArguments()
|
|||
|
||||
const std::string& cmInstallCommandArguments::GetDestination() const
|
||||
{
|
||||
if (!this->AbsDestination.empty())
|
||||
if (!this->DestinationString.empty())
|
||||
{
|
||||
return this->AbsDestination;
|
||||
return this->DestinationString;
|
||||
}
|
||||
if (this->GenericArguments!=0)
|
||||
{
|
||||
|
@ -128,8 +128,8 @@ bool cmInstallCommandArguments::Finalize()
|
|||
{
|
||||
return false;
|
||||
}
|
||||
this->ComputeDestination(this->Destination.GetString(),this->AbsDestination);
|
||||
|
||||
this->DestinationString = this->Destination.GetString();
|
||||
cmSystemTools::ConvertToUnixSlashes(this->DestinationString);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -174,23 +174,3 @@ bool cmInstallCommandArguments::CheckPermissions(
|
|||
// This is not a valid permission.
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmInstallCommandArguments::ComputeDestination(const std::string& inDest,
|
||||
std::string& absDest)
|
||||
{
|
||||
if((inDest.size()>0) && !(cmSystemTools::FileIsFullPath(inDest.c_str())))
|
||||
{
|
||||
// Relative paths are treated with respect to the installation prefix.
|
||||
absDest = "${CMAKE_INSTALL_PREFIX}/";
|
||||
absDest += inDest;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Full paths are absolute.
|
||||
absDest = inDest;
|
||||
}
|
||||
// Format the path nicely. Note this also removes trailing slashes.
|
||||
cmSystemTools::ConvertToUnixSlashes(absDest);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,8 +43,6 @@ class cmInstallCommandArguments
|
|||
// once HandleDirectoryMode() is also switched to using
|
||||
// cmInstallCommandArguments then these two functions can become non-static
|
||||
// private member functions without arguments
|
||||
static void ComputeDestination(const std::string& inDest,
|
||||
std::string& absDest);
|
||||
static bool CheckPermissions(const std::string& onePerm,
|
||||
std::string& perm);
|
||||
cmCommandArgumentsHelper Parser;
|
||||
|
@ -57,7 +55,7 @@ class cmInstallCommandArguments
|
|||
cmCAStringVector Configurations;
|
||||
cmCAEnabler Optional;
|
||||
|
||||
std::string AbsDestination;
|
||||
std::string DestinationString;
|
||||
std::string PermissionsString;
|
||||
|
||||
cmInstallCommandArguments* GenericArguments;
|
||||
|
|
|
@ -48,8 +48,7 @@ cmInstallDirectoryGenerator::GenerateScriptActions(std::ostream& os,
|
|||
bool not_optional = false;
|
||||
const char* no_properties = 0;
|
||||
const char* no_rename = 0;
|
||||
this->AddInstallRule(os, this->Destination.c_str(),
|
||||
cmTarget::INSTALL_DIRECTORY,
|
||||
this->AddInstallRule(os, cmTarget::INSTALL_DIRECTORY,
|
||||
this->Directories,
|
||||
not_optional, no_properties,
|
||||
this->FilePermissions.c_str(),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
//----------------------------------------------------------------------------
|
||||
cmInstallExportGenerator::~cmInstallExportGenerator()
|
||||
{
|
||||
if (generator == 0) // nothing to do
|
||||
delete this->EFGen;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmInstallExportGenerator::ComputeTempDir()
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->TempDir += "/";
|
||||
}
|
||||
|
||||
if (prefix == 0)
|
||||
// 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)
|
||||
{
|
||||
prefix = "";
|
||||
}
|
||||
|
||||
const std::vector<std::string>& configs = generator->GetConfigurations();
|
||||
if (configs.empty())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
useMD5 = true;
|
||||
}
|
||||
if(useMD5)
|
||||
{
|
||||
// Replace the destination path with a hash to keep it short.
|
||||
this->TempDir +=
|
||||
cmSystemTools::ComputeStringMD5(this->Destination.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
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 true;
|
||||
}
|
||||
|
||||
|
||||
bool cmInstallExportGenerator::AddInstallLocations(cmTargetWithProperties* twp,
|
||||
cmInstallFilesGenerator* generator,
|
||||
const char* propertyName)
|
||||
{
|
||||
if (generator == 0) // nothing to do
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((propertyName == 0) || (*propertyName == '\0'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// check that this property doesn't exist yet and add it then
|
||||
if (twp->Properties.find(propertyName) == twp->Properties.end())
|
||||
{
|
||||
twp->Properties[propertyName] = generator->GetDestination();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool cmInstallExportGenerator::SetExportSet(const char* name,
|
||||
const std::vector<cmTargetExport*>* set)
|
||||
{
|
||||
if ((name == 0) || (*name == 0) || (set==0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
targetWithProps = new cmTargetWithProperties((*it)->Target);
|
||||
this->Targets.push_back(targetWithProps);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this->AddInstallLocations(targetWithProps, (*it)->HeaderGenerator,
|
||||
"PUBLIC_HEADER_LOCATION") == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmInstallExportGenerator::GenerateScript(std::ostream& os)
|
||||
{
|
||||
// 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;
|
||||
// Get the export set requested.
|
||||
ExportSet const* exportSet =
|
||||
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
|
||||
->GetExportSet(this->Name.c_str());
|
||||
|
||||
cmGeneratedFileStream exportFileStream(this->ExportFilename.c_str());
|
||||
if(!exportFileStream)
|
||||
// Skip empty sets.
|
||||
if(!exportSet)
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "INSTALL(EXPORT) given unknown export \"" << this->Name << "\"";
|
||||
cmSystemTools::Error(e.str().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
// 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())
|
||||
{
|
||||
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";
|
||||
if(this->ConfigurationName && *this->ConfigurationName)
|
||||
{
|
||||
this->EFGen->AddConfiguration(this->ConfigurationName);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->EFGen->AddConfiguration("");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(std::vector<std::string>::const_iterator
|
||||
ci = this->ConfigurationTypes->begin();
|
||||
ci != this->ConfigurationTypes->end(); ++ci)
|
||||
{
|
||||
this->EFGen->AddConfiguration(ci->c_str());
|
||||
}
|
||||
}
|
||||
this->EFGen->GenerateImportFile();
|
||||
|
||||
// Perform the main install script generation.
|
||||
this->cmInstallGenerator::GenerateScript(os);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os,
|
||||
Indent const& indent)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -19,42 +19,12 @@
|
|||
|
||||
#include "cmInstallGenerator.h"
|
||||
|
||||
class cmTarget;
|
||||
|
||||
|
||||
class cmInstallTargetGenerator;
|
||||
class cmExportInstallFileGenerator;
|
||||
class cmInstallFilesGenerator;
|
||||
|
||||
/* cmInstallExportTarget is used in cmGlobalGenerator to collect the
|
||||
install generators for the exported targets. These are then used by the
|
||||
cmInstallExportGenerator.
|
||||
*/
|
||||
class cmTargetExport
|
||||
{
|
||||
public:
|
||||
cmTargetExport(cmTarget* tgt,
|
||||
cmInstallTargetGenerator* archive,
|
||||
cmInstallTargetGenerator* runtime,
|
||||
cmInstallTargetGenerator* library,
|
||||
cmInstallTargetGenerator* framework,
|
||||
cmInstallTargetGenerator* bundle,
|
||||
cmInstallFilesGenerator* headers
|
||||
) : Target(tgt), ArchiveGenerator(archive),
|
||||
RuntimeGenerator(runtime), LibraryGenerator(library),
|
||||
FrameworkGenerator(framework), BundleGenerator(bundle),
|
||||
HeaderGenerator(headers) {}
|
||||
|
||||
cmTarget* Target;
|
||||
cmInstallTargetGenerator* ArchiveGenerator;
|
||||
cmInstallTargetGenerator* RuntimeGenerator;
|
||||
cmInstallTargetGenerator* LibraryGenerator;
|
||||
cmInstallTargetGenerator* FrameworkGenerator;
|
||||
cmInstallTargetGenerator* BundleGenerator;
|
||||
cmInstallFilesGenerator* HeaderGenerator;
|
||||
private:
|
||||
cmTargetExport();
|
||||
};
|
||||
|
||||
class cmInstallTargetGenerator;
|
||||
class cmTarget;
|
||||
class cmTargetExport;
|
||||
class cmMakefile;
|
||||
|
||||
/** \class cmInstallExportGenerator
|
||||
* \brief Generate rules for creating an export files.
|
||||
|
@ -62,45 +32,33 @@ private:
|
|||
class cmInstallExportGenerator: public cmInstallGenerator
|
||||
{
|
||||
public:
|
||||
cmInstallExportGenerator(const char* dest, const char* file_permissions,
|
||||
cmInstallExportGenerator(const char* name,
|
||||
const char* dest, const char* file_permissions,
|
||||
const std::vector<std::string>& configurations,
|
||||
const char* component,
|
||||
const char* filename, const char* prefix,
|
||||
const char* tempOutputDir);
|
||||
|
||||
bool SetExportSet(const char* name,
|
||||
const std::vector<cmTargetExport*>* exportSet);
|
||||
const char* filename, const char* name_space,
|
||||
cmMakefile* mf);
|
||||
~cmInstallExportGenerator();
|
||||
protected:
|
||||
// internal class which collects all the properties which will be set
|
||||
// in the export file for the target
|
||||
class cmTargetWithProperties
|
||||
{
|
||||
public:
|
||||
cmTargetWithProperties(cmTarget* target):Target(target) {}
|
||||
cmTarget* Target;
|
||||
std::map<std::string, std::string> Properties;
|
||||
private:
|
||||
cmTargetWithProperties();
|
||||
};
|
||||
typedef std::vector<cmTargetExport*> ExportSet;
|
||||
|
||||
typedef cmInstallGeneratorIndent Indent;
|
||||
virtual void GenerateScript(std::ostream& os);
|
||||
virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);
|
||||
virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
|
||||
static bool AddInstallLocations(cmTargetWithProperties *twp,
|
||||
cmInstallTargetGenerator* generator,
|
||||
const char* prefix);
|
||||
static bool AddInstallLocations(cmTargetWithProperties* twp,
|
||||
cmInstallFilesGenerator* generator,
|
||||
const char* propertyName);
|
||||
void GenerateImportFile(ExportSet const* exportSet);
|
||||
void GenerateImportFile(const char* config, ExportSet const* exportSet);
|
||||
void ComputeTempDir();
|
||||
|
||||
std::string Name;
|
||||
std::string FilePermissions;
|
||||
std::string Filename;
|
||||
std::string Prefix;
|
||||
std::string TempOutputDir;
|
||||
std::string ExportFilename;
|
||||
std::string FileName;
|
||||
std::string Namespace;
|
||||
cmMakefile* Makefile;
|
||||
|
||||
std::vector<cmTargetWithProperties*> Targets;
|
||||
std::string TempDir;
|
||||
std::string MainImportFile;
|
||||
cmExportInstallFileGenerator* EFGen;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -119,9 +119,8 @@ void cmInstallFilesCommand::FinalPass()
|
|||
void cmInstallFilesCommand::CreateInstallGenerator() const
|
||||
{
|
||||
// Construct the destination. This command always installs under
|
||||
// the prefix.
|
||||
std::string destination = "${CMAKE_INSTALL_PREFIX}";
|
||||
destination += this->Destination;
|
||||
// the prefix. We skip the leading slash given by the user.
|
||||
std::string destination = this->Destination.substr(1);
|
||||
cmSystemTools::ConvertToUnixSlashes(destination);
|
||||
|
||||
// Use a file install generator.
|
||||
|
|
|
@ -47,7 +47,7 @@ void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os,
|
|||
// Write code to install the files.
|
||||
const char* no_properties = 0;
|
||||
const char* no_dir_permissions = 0;
|
||||
this->AddInstallRule(os, this->Destination.c_str(),
|
||||
this->AddInstallRule(os,
|
||||
(this->Programs
|
||||
? cmTarget::INSTALL_PROGRAMS
|
||||
: cmTarget::INSTALL_FILES),
|
||||
|
|
|
@ -55,7 +55,6 @@ cmInstallGenerator
|
|||
void cmInstallGenerator
|
||||
::AddInstallRule(
|
||||
std::ostream& os,
|
||||
const char* dest,
|
||||
int type,
|
||||
std::vector<std::string> const& files,
|
||||
bool optional /* = false */,
|
||||
|
@ -81,6 +80,7 @@ void cmInstallGenerator
|
|||
default: stype = "FILE"; break;
|
||||
}
|
||||
os << indent;
|
||||
std::string dest = this->GetInstallDestination();
|
||||
os << "FILE(INSTALL DESTINATION \"" << dest << "\" TYPE " << stype.c_str();
|
||||
if(optional)
|
||||
{
|
||||
|
@ -238,3 +238,40 @@ void cmInstallGenerator::GenerateScriptActions(std::ostream&, Indent const&)
|
|||
{
|
||||
// No actions for this generator.
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmInstallGenerator::InstallsForConfig(const char* config)
|
||||
{
|
||||
// If this is not a configuration-specific rule then we install.
|
||||
if(this->Configurations.empty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is a configuration-specific rule. Check if the config
|
||||
// matches this rule.
|
||||
std::string config_upper = cmSystemTools::UpperCase(config?config:"");
|
||||
for(std::vector<std::string>::const_iterator i =
|
||||
this->Configurations.begin();
|
||||
i != this->Configurations.end(); ++i)
|
||||
{
|
||||
if(cmSystemTools::UpperCase(*i) == config_upper)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmInstallGenerator::GetInstallDestination() const
|
||||
{
|
||||
std::string result;
|
||||
if(!this->Destination.empty() &&
|
||||
!cmSystemTools::FileIsFullPath(this->Destination.c_str()))
|
||||
{
|
||||
result = "${CMAKE_INSTALL_PREFIX}/";
|
||||
}
|
||||
result += this->Destination;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -62,8 +62,8 @@ public:
|
|||
void Generate(std::ostream& os, const char* config,
|
||||
std::vector<std::string> const& configurationTypes);
|
||||
|
||||
static void AddInstallRule(
|
||||
std::ostream& os, const char* dest, int type,
|
||||
void AddInstallRule(
|
||||
std::ostream& os, int type,
|
||||
std::vector<std::string> const& files,
|
||||
bool optional = false,
|
||||
const char* properties = 0,
|
||||
|
@ -78,6 +78,14 @@ public:
|
|||
{ return this->Destination.c_str(); }
|
||||
const std::vector<std::string>& GetConfigurations() const
|
||||
{ return this->Configurations; }
|
||||
|
||||
/** Get the install destination as it should appear in the
|
||||
installation script. */
|
||||
std::string GetInstallDestination() const;
|
||||
|
||||
/** Test if this generator installs something for a given configuration. */
|
||||
bool InstallsForConfig(const char*);
|
||||
|
||||
protected:
|
||||
typedef cmInstallGeneratorIndent Indent;
|
||||
virtual void GenerateScript(std::ostream& os);
|
||||
|
|
|
@ -80,9 +80,8 @@ void cmInstallProgramsCommand::FinalPass()
|
|||
}
|
||||
|
||||
// Construct the destination. This command always installs under
|
||||
// the prefix.
|
||||
std::string destination = "${CMAKE_INSTALL_PREFIX}";
|
||||
destination += this->Destination;
|
||||
// the prefix. We skip the leading slash given by the user.
|
||||
std::string destination = this->Destination.substr(1);
|
||||
cmSystemTools::ConvertToUnixSlashes(destination);
|
||||
|
||||
// Use a file install generator.
|
||||
|
|
|
@ -113,22 +113,11 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
|
|||
|
||||
if(config && *config)
|
||||
{
|
||||
std::string config_upper = cmSystemTools::UpperCase(config);
|
||||
// Skip this configuration for config-specific installation that
|
||||
// does not match it.
|
||||
if(!this->Configurations.empty())
|
||||
if(!this->InstallsForConfig(config))
|
||||
{
|
||||
bool found = false;
|
||||
for(std::vector<std::string>::const_iterator i =
|
||||
this->Configurations.begin();
|
||||
!found && i != this->Configurations.end(); ++i)
|
||||
{
|
||||
found = found || (cmSystemTools::UpperCase(*i) == config_upper);
|
||||
}
|
||||
if(!found)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Generate a per-configuration block.
|
||||
|
@ -154,7 +143,7 @@ cmInstallTargetGenerator
|
|||
Indent const& indent)
|
||||
{
|
||||
// Compute the full path to the main installed file for this target.
|
||||
std::string toInstallPath = this->Destination;
|
||||
std::string toInstallPath = this->GetInstallDestination();
|
||||
toInstallPath += "/";
|
||||
toInstallPath += this->GetInstallFilename(this->Target, config,
|
||||
this->ImportLibrary, false);
|
||||
|
@ -279,7 +268,7 @@ cmInstallTargetGenerator
|
|||
const char* no_rename = 0;
|
||||
const char* no_properties = 0;
|
||||
bool optional = this->Optional || this->ImportLibrary;
|
||||
this->AddInstallRule(os, this->Destination.c_str(), type, files,
|
||||
this->AddInstallRule(os, type, files,
|
||||
optional, no_properties,
|
||||
this->FilePermissions.c_str(), no_dir_permissions,
|
||||
no_rename, literal_args.c_str(),
|
||||
|
@ -412,7 +401,7 @@ cmInstallTargetGenerator
|
|||
{
|
||||
if(cmTarget* tgt = this->Target->GetMakefile()->
|
||||
GetLocalGenerator()->GetGlobalGenerator()->
|
||||
FindTarget(0, lib.c_str(), false))
|
||||
FindTarget(0, lib.c_str()))
|
||||
{
|
||||
if(tgt->GetType() == cmTarget::SHARED_LIBRARY)
|
||||
{
|
||||
|
|
|
@ -40,6 +40,9 @@ public:
|
|||
static std::string GetInstallFilename(cmTarget*target, const char* config,
|
||||
bool implib, bool useSOName);
|
||||
|
||||
cmTarget* GetTarget() const { return this->Target; }
|
||||
bool IsImportLibrary() const { return this->ImportLibrary; }
|
||||
|
||||
protected:
|
||||
typedef cmInstallGeneratorIndent Indent;
|
||||
virtual void GenerateScript(std::ostream& os);
|
||||
|
|
|
@ -1809,7 +1809,7 @@ std::string cmLocalGenerator::GetRealDependency(const char* inName,
|
|||
}
|
||||
|
||||
// Look for a CMake target with the given name.
|
||||
if(cmTarget* target = this->GlobalGenerator->FindTarget(0,name.c_str(),true))
|
||||
if(cmTarget* target = this->Makefile->FindTargetToUse(name.c_str()))
|
||||
{
|
||||
// make sure it is not just a coincidence that the target name
|
||||
// found is part of the inName
|
||||
|
@ -1876,7 +1876,7 @@ std::string cmLocalGenerator::GetRealLocation(const char* inName,
|
|||
std::string outName=inName;
|
||||
// Look for a CMake target with the given name, which is an executable
|
||||
// and which can be run
|
||||
cmTarget* target = this->GlobalGenerator->FindTarget(0, inName, true);
|
||||
cmTarget* target = this->Makefile->FindTargetToUse(inName);
|
||||
if ((target != 0)
|
||||
&& (target->GetType() == cmTarget::EXECUTABLE)
|
||||
&& ((this->Makefile->IsOn("CMAKE_CROSSCOMPILING") == false)
|
||||
|
@ -2348,8 +2348,8 @@ cmLocalGenerator
|
|||
{
|
||||
// Compute the full install destination. Note that converting
|
||||
// to unix slashes also removes any trailing slash.
|
||||
std::string destination = "${CMAKE_INSTALL_PREFIX}";
|
||||
destination += l->second.GetInstallPath();
|
||||
// We also skip over the leading slash given by the user.
|
||||
std::string destination = l->second.GetInstallPath().substr(1);
|
||||
cmSystemTools::ConvertToUnixSlashes(destination);
|
||||
|
||||
// Generate the proper install generator for this target type.
|
||||
|
@ -2372,8 +2372,8 @@ cmLocalGenerator
|
|||
// destination.
|
||||
cmInstallTargetGenerator g1(l->second, destination.c_str(), true);
|
||||
g1.Generate(os, config, configurationTypes);
|
||||
destination = "${CMAKE_INSTALL_PREFIX}";
|
||||
destination += l->second.GetRuntimeInstallPath();
|
||||
// We also skip over the leading slash given by the user.
|
||||
destination = l->second.GetRuntimeInstallPath().substr(1);
|
||||
cmSystemTools::ConvertToUnixSlashes(destination);
|
||||
cmInstallTargetGenerator g2(l->second, destination.c_str(), false);
|
||||
g2.Generate(os, config, configurationTypes);
|
||||
|
|
|
@ -1061,8 +1061,7 @@ void cmLocalVisualStudio6Generator
|
|||
// Compute the proper name to use to link this library.
|
||||
std::string lib;
|
||||
std::string libDebug;
|
||||
cmTarget* tgt = this->GlobalGenerator->FindTarget(0, j->first.c_str(),
|
||||
false);
|
||||
cmTarget* tgt = this->GlobalGenerator->FindTarget(0, j->first.c_str());
|
||||
if(tgt)
|
||||
{
|
||||
lib = cmSystemTools::GetFilenameWithoutExtension
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
#include <cmsys/RegularExpression.hxx>
|
||||
|
||||
#include <cmsys/auto_ptr.hxx>
|
||||
|
||||
#include <ctype.h> // for isspace
|
||||
|
||||
// default is not to be building executables
|
||||
|
@ -176,6 +178,12 @@ cmMakefile::~cmMakefile()
|
|||
{
|
||||
delete *i;
|
||||
}
|
||||
for(std::vector<cmTarget*>::iterator
|
||||
i = this->ImportedTargetsOwned.begin();
|
||||
i != this->ImportedTargetsOwned.end(); ++i)
|
||||
{
|
||||
delete *i;
|
||||
}
|
||||
for(unsigned int i=0; i < this->UsedCommands.size(); i++)
|
||||
{
|
||||
delete this->UsedCommands[i];
|
||||
|
@ -824,7 +832,7 @@ void cmMakefile::AddUtilityCommand(const char* utilityName,
|
|||
bool escapeOldStyle, const char* comment)
|
||||
{
|
||||
// Create a target instance for this utility.
|
||||
cmTarget* target = this->AddNewTarget(cmTarget::UTILITY, utilityName, false);
|
||||
cmTarget* target = this->AddNewTarget(cmTarget::UTILITY, utilityName);
|
||||
if (excludeFromAll)
|
||||
{
|
||||
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
|
||||
|
@ -1005,7 +1013,7 @@ void cmMakefile::AddLinkLibraryForTarget(const char *target,
|
|||
if ( i != this->Targets.end())
|
||||
{
|
||||
cmTarget* tgt =
|
||||
this->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(0,lib,false);
|
||||
this->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(0,lib);
|
||||
if(tgt)
|
||||
{
|
||||
bool allowModules = true;
|
||||
|
@ -1018,8 +1026,7 @@ 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::EXECUTABLE &&
|
||||
tgt->GetPropertyAsBool("ENABLE_EXPORTS"))))
|
||||
tgt->IsExecutableWithExports()))
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "Attempt to add link target " << lib << " of type: "
|
||||
|
@ -1162,6 +1169,9 @@ void cmMakefile::InitializeFromParent()
|
|||
// Copy include regular expressions.
|
||||
this->IncludeFileRegularExpression = parent->IncludeFileRegularExpression;
|
||||
this->ComplainFileRegularExpression = parent->ComplainFileRegularExpression;
|
||||
|
||||
// Imported targets.
|
||||
this->ImportedTargets = parent->ImportedTargets;
|
||||
}
|
||||
|
||||
void cmMakefile::ConfigureSubDirectory(cmLocalGenerator *lg2)
|
||||
|
@ -1467,7 +1477,7 @@ void cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type,
|
|||
type = cmTarget::STATIC_LIBRARY;
|
||||
}
|
||||
|
||||
cmTarget* target = this->AddNewTarget(type, lname, false);
|
||||
cmTarget* target = this->AddNewTarget(type, lname);
|
||||
// Clear its dependencies. Otherwise, dependencies might persist
|
||||
// over changes in CMakeLists.txt, making the information stale and
|
||||
// hence useless.
|
||||
|
@ -1484,7 +1494,7 @@ cmTarget* cmMakefile::AddExecutable(const char *exeName,
|
|||
const std::vector<std::string> &srcs,
|
||||
bool excludeFromAll)
|
||||
{
|
||||
cmTarget* target = this->AddNewTarget(cmTarget::EXECUTABLE, exeName, false);
|
||||
cmTarget* target = this->AddNewTarget(cmTarget::EXECUTABLE, exeName);
|
||||
if(excludeFromAll)
|
||||
{
|
||||
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
|
||||
|
@ -1494,26 +1504,16 @@ cmTarget* cmMakefile::AddExecutable(const char *exeName,
|
|||
return target;
|
||||
}
|
||||
|
||||
|
||||
cmTarget* cmMakefile::AddNewTarget(cmTarget::TargetType type,
|
||||
const char* name,
|
||||
bool isImported)
|
||||
//----------------------------------------------------------------------------
|
||||
cmTarget*
|
||||
cmMakefile::AddNewTarget(cmTarget::TargetType type, const char* name)
|
||||
{
|
||||
cmTargets::iterator it;
|
||||
cmTarget target;
|
||||
target.SetType(type, name);
|
||||
target.SetMakefile(this);
|
||||
if (isImported)
|
||||
{
|
||||
target.MarkAsImported();
|
||||
it=this->ImportedTargets.insert(
|
||||
cmTargets::value_type(target.GetName(), target)).first;
|
||||
}
|
||||
else
|
||||
{
|
||||
it=this->Targets.insert(
|
||||
cmTargets::value_type(target.GetName(), target)).first;
|
||||
}
|
||||
it=this->Targets.insert(
|
||||
cmTargets::value_type(target.GetName(), target)).first;
|
||||
this->LocalGenerator->GetGlobalGenerator()->AddTarget(*it);
|
||||
return &it->second;
|
||||
}
|
||||
|
@ -2869,7 +2869,7 @@ bool cmMakefile::GetPropertyAsBool(const char* prop)
|
|||
}
|
||||
|
||||
|
||||
cmTarget* cmMakefile::FindTarget(const char* name, bool useImportedTargets)
|
||||
cmTarget* cmMakefile::FindTarget(const char* name)
|
||||
{
|
||||
cmTargets& tgts = this->GetTargets();
|
||||
|
||||
|
@ -2879,15 +2879,6 @@ cmTarget* cmMakefile::FindTarget(const char* name, bool useImportedTargets)
|
|||
return &i->second;
|
||||
}
|
||||
|
||||
if (useImportedTargets)
|
||||
{
|
||||
cmTargets::iterator impTarget = this->ImportedTargets.find(name);
|
||||
if (impTarget != this->ImportedTargets.end())
|
||||
{
|
||||
return &impTarget->second;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3091,3 +3082,37 @@ void cmMakefile::DefineProperties(cmake *cm)
|
|||
"The same concept applies to the default build of other generators.",
|
||||
false);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmTarget*
|
||||
cmMakefile::AddImportedTarget(const char* name, cmTarget::TargetType type)
|
||||
{
|
||||
// Create the target.
|
||||
cmsys::auto_ptr<cmTarget> target(new cmTarget);
|
||||
target->SetType(type, name);
|
||||
target->SetMakefile(this);
|
||||
target->MarkAsImported();
|
||||
|
||||
// Add to the set of available imported targets.
|
||||
this->ImportedTargets[name] = target.get();
|
||||
|
||||
// Transfer ownership to this cmMakefile object.
|
||||
this->ImportedTargetsOwned.push_back(target.get());
|
||||
return target.release();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmTarget* cmMakefile::FindTargetToUse(const char* name)
|
||||
{
|
||||
// Look for an imported target. These take priority because they
|
||||
// are more local in scope and do not have to be globally unique.
|
||||
std::map<cmStdString, cmTarget*>::const_iterator
|
||||
imported = this->ImportedTargets.find(name);
|
||||
if(imported != this->ImportedTargets.end())
|
||||
{
|
||||
return imported->second;
|
||||
}
|
||||
|
||||
// Look for a target built in this project.
|
||||
return this->LocalGenerator->GetGlobalGenerator()->FindTarget(0, name);
|
||||
}
|
||||
|
|
|
@ -172,9 +172,10 @@ public:
|
|||
void AddDefineFlag(const char* definition);
|
||||
void RemoveDefineFlag(const char* definition);
|
||||
|
||||
cmTarget* AddNewTarget(cmTarget::TargetType type,
|
||||
const char* name,
|
||||
bool isImported);
|
||||
/** Create a new imported target with the name and type given. */
|
||||
cmTarget* AddImportedTarget(const char* name, cmTarget::TargetType type);
|
||||
|
||||
cmTarget* AddNewTarget(cmTarget::TargetType type, const char* name);
|
||||
|
||||
/**
|
||||
* Add an executable to the build.
|
||||
|
@ -436,10 +437,12 @@ public:
|
|||
* Get the list of targets, const version
|
||||
*/
|
||||
const cmTargets &GetTargets() const { return this->Targets; }
|
||||
const cmTargets &GetImportedTargets() const { return this->ImportedTargets; }
|
||||
|
||||
cmTarget* FindTarget(const char* name, bool useImportedTargets);
|
||||
cmTarget* FindTarget(const char* name);
|
||||
|
||||
/** Find a target to use in place of the given name. The target
|
||||
returned may be imported or built within the project. */
|
||||
cmTarget* FindTargetToUse(const char* name);
|
||||
|
||||
/**
|
||||
* Get a list of include directories in the build.
|
||||
|
@ -766,7 +769,6 @@ protected:
|
|||
|
||||
// libraries, classes, and executables
|
||||
cmTargets Targets;
|
||||
cmTargets ImportedTargets;
|
||||
std::vector<cmSourceFile*> SourceFiles;
|
||||
|
||||
// Tests
|
||||
|
@ -842,6 +844,10 @@ private:
|
|||
|
||||
// stack of list files being read
|
||||
std::deque<cmStdString> ListFileStack;
|
||||
|
||||
cmTarget* FindBasicTarget(const char* name);
|
||||
std::vector<cmTarget*> ImportedTargetsOwned;
|
||||
std::map<cmStdString, cmTarget*> ImportedTargets;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
|||
}
|
||||
|
||||
// Add symbol export flags if necessary.
|
||||
if(this->Target->GetPropertyAsBool("ENABLE_EXPORTS"))
|
||||
if(this->Target->IsExecutableWithExports())
|
||||
{
|
||||
std::string export_flag_var = "CMAKE_EXE_EXPORTS_";
|
||||
export_flag_var += linkLanguage;
|
||||
|
@ -351,7 +351,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
|||
this->Makefile->GetRequiredDefinition(linkRuleVar.c_str());
|
||||
std::vector<std::string> commands1;
|
||||
cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
|
||||
if(this->Target->GetPropertyAsBool("ENABLE_EXPORTS"))
|
||||
if(this->Target->IsExecutableWithExports())
|
||||
{
|
||||
// If a separate rule for creating an import library is specified
|
||||
// add it now.
|
||||
|
|
|
@ -869,7 +869,7 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
|
|||
for(cmTarget::LinkLibraryVectorType::const_iterator j = libs.begin();
|
||||
j != libs.end(); ++j)
|
||||
{
|
||||
if(cmTarget const* linkee = gg->FindTarget(0, j->first.c_str(), false))
|
||||
if(cmTarget const* linkee = gg->FindTarget(0, j->first.c_str()))
|
||||
{
|
||||
if(emitted.insert(linkee).second)
|
||||
{
|
||||
|
@ -1371,7 +1371,7 @@ void cmMakefileTargetGenerator
|
|||
{
|
||||
// Depend on other CMake targets.
|
||||
if(cmTarget* tgt =
|
||||
this->GlobalGenerator->FindTarget(0, lib->first.c_str(), false))
|
||||
this->GlobalGenerator->FindTarget(0, lib->first.c_str()))
|
||||
{
|
||||
if(const char* location =
|
||||
tgt->GetLocation(this->LocalGenerator->ConfigurationName.c_str()))
|
||||
|
|
|
@ -220,9 +220,7 @@ bool cmSetPropertyCommand::HandleTargetMode()
|
|||
for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
|
||||
ni != this->Names.end(); ++ni)
|
||||
{
|
||||
if(cmTarget* target =
|
||||
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
|
||||
->FindTarget(0, ni->c_str(), true))
|
||||
if(cmTarget* target = this->Makefile->FindTargetToUse(ni->c_str()))
|
||||
{
|
||||
// Handle the current target.
|
||||
if(!this->HandleTarget(target))
|
||||
|
|
|
@ -95,9 +95,7 @@ bool cmSetTargetPropertiesCommand
|
|||
std::vector<std::string> &propertyPairs,
|
||||
cmMakefile *mf)
|
||||
{
|
||||
cmTarget* target =
|
||||
mf->GetLocalGenerator()->GetGlobalGenerator()->FindTarget(0, tname, true);
|
||||
if ( target)
|
||||
if(cmTarget* target = mf->FindTargetToUse(tname))
|
||||
{
|
||||
// now loop through all the props and set them
|
||||
unsigned int k;
|
||||
|
|
|
@ -153,6 +153,96 @@ void cmTarget::DefineProperties(cmake *cm)
|
|||
"A target property that can be set to override the suffix "
|
||||
"(such as \".lib\") on an import library name.");
|
||||
|
||||
cm->DefineProperty
|
||||
("IMPORTED", cmProperty::TARGET,
|
||||
"Read-only indication of whether a target is IMPORTED.",
|
||||
"The boolean value of this property is true for targets created with "
|
||||
"the IMPORTED option to add_executable or add_library. "
|
||||
"It is false for targets built within the project.");
|
||||
|
||||
cm->DefineProperty
|
||||
("IMPORTED_CONFIGURATIONS", cmProperty::TARGET,
|
||||
"Configurations provided for an IMPORTED target.",
|
||||
"Lists configuration names available for an IMPORTED target. "
|
||||
"The names correspond to configurations defined in the project from "
|
||||
"which the target is imported. "
|
||||
"If the importing project uses a different set of configurations "
|
||||
"the names may be mapped using the MAP_IMPORTED_CONFIG_<CONFIG> "
|
||||
"property. "
|
||||
"Ignored for non-imported targets.");
|
||||
|
||||
cm->DefineProperty
|
||||
("IMPORTED_ENABLE_EXPORTS", cmProperty::TARGET,
|
||||
"Enable linking to an IMPORTED executable target.",
|
||||
"Indicates that an IMPORTED executable target exports symbols for "
|
||||
"use by plugin modules. "
|
||||
"This is the imported target equivalent of the ENABLE_EXPORTS "
|
||||
"property.");
|
||||
|
||||
cm->DefineProperty
|
||||
("IMPORTED_IMPLIB", cmProperty::TARGET,
|
||||
"Full path to the import library for an IMPORTED target.",
|
||||
"Specifies the location of the \".lib\" part of a windows DLL. "
|
||||
"Ignored for non-imported targets.");
|
||||
|
||||
cm->DefineProperty
|
||||
("IMPORTED_IMPLIB_<CONFIG>", cmProperty::TARGET,
|
||||
"Per-configuration version of IMPORTED_IMPLIB property.",
|
||||
"This property is used when loading settings for the <CONFIG> "
|
||||
"configuration of an imported target. "
|
||||
"Configuration names correspond to those provided by the project "
|
||||
"from which the target is imported.");
|
||||
|
||||
cm->DefineProperty
|
||||
("IMPORTED_LINK_LIBRARIES", cmProperty::TARGET,
|
||||
"Transitive link dependencies of an IMPORTED target.",
|
||||
"Lists dependencies that must be linked when an IMPORTED library "
|
||||
"target is linked to another target. "
|
||||
"Ignored for non-imported targets.");
|
||||
|
||||
cm->DefineProperty
|
||||
("IMPORTED_LINK_LIBRARIES_<CONFIG>", cmProperty::TARGET,
|
||||
"Per-configuration version of IMPORTED_LINK_LIBRARIES property.",
|
||||
"This property is used when loading settings for the <CONFIG> "
|
||||
"configuration of an imported target. "
|
||||
"Configuration names correspond to those provided by the project "
|
||||
"from which the target is imported.");
|
||||
|
||||
cm->DefineProperty
|
||||
("IMPORTED_LOCATION", cmProperty::TARGET,
|
||||
"Full path to the main file on disk for an IMPORTED target.",
|
||||
"Specifies the location of an IMPORTED target file on disk. "
|
||||
"For executables this is the location of the executable file. "
|
||||
"For static libraries and modules this is the location of the "
|
||||
"library or module. "
|
||||
"For shared libraries on non-DLL platforms this is the location of "
|
||||
"the shared library. "
|
||||
"For DLLs this is the location of the \".dll\" part of the library. "
|
||||
"Ignored for non-imported targets.");
|
||||
|
||||
cm->DefineProperty
|
||||
("IMPORTED_LOCATION_<CONFIG>", cmProperty::TARGET,
|
||||
"Per-configuration version of IMPORTED_LOCATION property.",
|
||||
"This property is used when loading settings for the <CONFIG> "
|
||||
"configuration of an imported target. "
|
||||
"Configuration names correspond to those provided by the project "
|
||||
"from which the target is imported.");
|
||||
|
||||
cm->DefineProperty
|
||||
("IMPORTED_SONAME", cmProperty::TARGET,
|
||||
"The \"soname\" of an IMPORTED target of shared library type.",
|
||||
"Specifies the \"soname\" embedded in an imported shared library. "
|
||||
"This is meaningful only on platforms supporting the feature. "
|
||||
"Ignored for non-imported targets.");
|
||||
|
||||
cm->DefineProperty
|
||||
("IMPORTED_SONAME_<CONFIG>", cmProperty::TARGET,
|
||||
"Per-configuration version of IMPORTED_SONAME property.",
|
||||
"This property is used when loading settings for the <CONFIG> "
|
||||
"configuration of an imported target. "
|
||||
"Configuration names correspond to those provided by the project "
|
||||
"from which the target is imported.");
|
||||
|
||||
cm->DefineProperty
|
||||
("EXCLUDE_FROM_ALL", cmProperty::TARGET,
|
||||
"Exclude the target from the all target.",
|
||||
|
@ -206,11 +296,37 @@ void cmTarget::DefineProperties(cmake *cm)
|
|||
|
||||
cm->DefineProperty
|
||||
("LOCATION", cmProperty::TARGET,
|
||||
"Where a target will be written on disk.",
|
||||
"A read only property on a target that indicates where that target "
|
||||
"will be written. For libraries and executables this will be where "
|
||||
"the file is written on disk. This property is computed based on a "
|
||||
"number of other settings.");
|
||||
"Deprecated. Use LOCATION_<CONFIG> or avoid altogether.",
|
||||
"This property is provided for compatibility with CMake 2.4 and below. "
|
||||
"It was meant to get the location of an executable target's output file "
|
||||
"for use in add_custom_command. "
|
||||
"In CMake 2.6 and above add_custom_command automatically recognizes a "
|
||||
"target name in its COMMAND and DEPENDS options and computes the "
|
||||
"target location. Therefore this property need not be used. "
|
||||
"This property is not defined for IMPORTED targets because they "
|
||||
"were not available in CMake 2.4 or below anyway.");
|
||||
|
||||
cm->DefineProperty
|
||||
("LOCATION_<CONFIG>", cmProperty::TARGET,
|
||||
"Read-only property providing a target location on disk.",
|
||||
"A read-only property that indicates where a target's main file is "
|
||||
"located on disk for the configuration <CONFIG>. "
|
||||
"The property is defined only for library and executable targets.");
|
||||
|
||||
cm->DefineProperty
|
||||
("MAP_IMPORTED_CONFIG_<CONFIG>", cmProperty::TARGET,
|
||||
"Map from project configuration to IMPORTED target's configuration.",
|
||||
"List configurations of an imported target that may be used for "
|
||||
"the current project's <CONFIG> configuration. "
|
||||
"Targets imported from another project may not provide the same set "
|
||||
"of configuration names available in the current project. "
|
||||
"Setting this property tells CMake what imported configurations are "
|
||||
"suitable for use when building the <CONFIG> configuration. "
|
||||
"The first configuration in the list found to be provided by the "
|
||||
"imported target is selected. If no matching configurations are "
|
||||
"available the imported target is considered to be not found. "
|
||||
"This property is ignored for non-imported targets.",
|
||||
false /* TODO: make this chained */ );
|
||||
|
||||
cm->DefineProperty
|
||||
("OUTPUT_NAME", cmProperty::TARGET,
|
||||
|
@ -480,6 +596,25 @@ void cmTarget::SetMakefile(cmMakefile* mf)
|
|||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmTarget::IsExecutableWithExports()
|
||||
{
|
||||
if(this->GetType() == cmTarget::EXECUTABLE)
|
||||
{
|
||||
if(this->IsImported())
|
||||
{
|
||||
// The "IMPORTED_" namespace is used for properties exported
|
||||
// from the project providing imported targets.
|
||||
return this->GetPropertyAsBool("IMPORTED_ENABLE_EXPORTS");
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->GetPropertyAsBool("ENABLE_EXPORTS");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class cmTargetTraceDependencies
|
||||
{
|
||||
|
@ -603,8 +738,7 @@ bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
|
|||
}
|
||||
|
||||
// Check for a non-imported target with this name.
|
||||
if(cmTarget* t =
|
||||
this->GlobalGenerator->FindTarget(0, util.c_str(), false))
|
||||
if(cmTarget* t = this->GlobalGenerator->FindTarget(0, util.c_str()))
|
||||
{
|
||||
// If we find the target and the dep was given as a full path,
|
||||
// then make sure it was not a full path to something else, and
|
||||
|
@ -671,8 +805,7 @@ cmTargetTraceDependencies
|
|||
{
|
||||
std::string const& command = *cit->begin();
|
||||
// Look for a non-imported target with this name.
|
||||
if(cmTarget* t =
|
||||
this->GlobalGenerator->FindTarget(0, command.c_str(), false))
|
||||
if(cmTarget* t = this->GlobalGenerator->FindTarget(0, command.c_str()))
|
||||
{
|
||||
if(t->GetType() == cmTarget::EXECUTABLE)
|
||||
{
|
||||
|
@ -1287,6 +1420,13 @@ void cmTarget::SetProperty(const char* prop, const char* value)
|
|||
}
|
||||
|
||||
this->Properties.SetProperty(prop, value, cmProperty::TARGET);
|
||||
|
||||
// If imported information is being set, wipe out cached
|
||||
// information.
|
||||
if(this->IsImported() && strncmp(prop, "IMPORTED", 8) == 0)
|
||||
{
|
||||
this->ImportInfoMap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -1297,6 +1437,13 @@ void cmTarget::AppendProperty(const char* prop, const char* value)
|
|||
return;
|
||||
}
|
||||
this->Properties.AppendProperty(prop, value, cmProperty::TARGET);
|
||||
|
||||
// If imported information is being set, wipe out cached
|
||||
// information.
|
||||
if(this->IsImported() && strncmp(prop, "IMPORTED", 8) == 0)
|
||||
{
|
||||
this->ImportInfoMap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -1319,10 +1466,11 @@ const char* cmTarget::GetDirectory(const char* config, bool implib)
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
const char* cmTarget::ImportedGetDirectory(const char* config, bool)
|
||||
const char* cmTarget::ImportedGetDirectory(const char* config, bool implib)
|
||||
{
|
||||
const char* location=this->GetLocation(config);
|
||||
this->Directory = cmSystemTools::GetFilenamePath(location);
|
||||
this->Directory =
|
||||
cmSystemTools::GetFilenamePath(
|
||||
this->ImportedGetFullPath(config, implib));
|
||||
return this->Directory.c_str();
|
||||
}
|
||||
|
||||
|
@ -1360,18 +1508,8 @@ const char* cmTarget::GetLocation(const char* config)
|
|||
//----------------------------------------------------------------------------
|
||||
const char* cmTarget::ImportedGetLocation(const char* config)
|
||||
{
|
||||
if ((config) && (strlen(config)))
|
||||
{
|
||||
std::string propertyName=cmSystemTools::UpperCase(config);
|
||||
propertyName+="_LOCATION";
|
||||
const char* configLocation=this->GetProperty(propertyName.c_str());
|
||||
if ((configLocation) && (strlen(configLocation)))
|
||||
{
|
||||
return configLocation;
|
||||
}
|
||||
}
|
||||
|
||||
return this->GetProperty("LOCATION");
|
||||
this->Location = this->ImportedGetFullPath(config, false);
|
||||
return this->Location.c_str();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -1484,38 +1622,41 @@ const char *cmTarget::GetProperty(const char* prop,
|
|||
return 0;
|
||||
}
|
||||
|
||||
// don't use GetLocation() for imported targets, because there this
|
||||
// calls GetProperty() to get the location...
|
||||
if (!this->IsImported())
|
||||
// Watch for special "computed" properties that are dependent on
|
||||
// other properties or variables. Always recompute them.
|
||||
if(this->GetType() == cmTarget::EXECUTABLE ||
|
||||
this->GetType() == cmTarget::STATIC_LIBRARY ||
|
||||
this->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||
this->GetType() == cmTarget::MODULE_LIBRARY)
|
||||
{
|
||||
// watch for special "computed" properties that are dependent on other
|
||||
// properties or variables, always recompute them
|
||||
if (!strcmp(prop,"LOCATION"))
|
||||
if(!this->IsImported() && strcmp(prop,"LOCATION") == 0)
|
||||
{
|
||||
// Set the LOCATION property of the target. Note that this
|
||||
// cannot take into account the per-configuration name of the
|
||||
// target because the configuration type may not be known at
|
||||
// CMake time. We should deprecate this feature and instead
|
||||
// support transforming an executable target name given as the
|
||||
// command part of custom commands into the proper path at
|
||||
// build time. Alternatively we could put environment
|
||||
// variable settings in all custom commands that hold the name
|
||||
// of the target for each configuration and then give a
|
||||
// reference to the variable in the location.
|
||||
// CMake time. It is now deprecated as described in the
|
||||
// documentation.
|
||||
this->SetProperty("LOCATION", this->GetLocation(0));
|
||||
}
|
||||
|
||||
// Per-configuration location can be computed.
|
||||
int len = static_cast<int>(strlen(prop));
|
||||
if(len > 9 && strcmp(prop+len-9, "_LOCATION") == 0)
|
||||
// Support "LOCATION_<CONFIG>".
|
||||
if(strncmp(prop, "LOCATION_", 9) == 0)
|
||||
{
|
||||
std::string configName(prop, len-9);
|
||||
std::string configName = prop+9;
|
||||
this->SetProperty(prop, this->GetLocation(configName.c_str()));
|
||||
}
|
||||
|
||||
if(strcmp(prop, "OBJECT_FILES") == 0)
|
||||
else
|
||||
{
|
||||
this->ComputeObjectFiles();
|
||||
// Support "<CONFIG>_LOCATION" for compatiblity.
|
||||
int len = static_cast<int>(strlen(prop));
|
||||
if(len > 9 && strcmp(prop+len-9, "_LOCATION") == 0)
|
||||
{
|
||||
std::string configName(prop, len-9);
|
||||
if(configName != "IMPORTED")
|
||||
{
|
||||
this->SetProperty(prop, this->GetLocation(configName.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1750,15 +1891,57 @@ std::string cmTarget::GetPDBName(const char* config)
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmTarget::GetFullName(const char* config, bool implib)
|
||||
std::string cmTarget::GetSOName(const char* config)
|
||||
{
|
||||
return this->GetFullNameInternal(this->GetType(), config, implib);
|
||||
if(this->IsImported())
|
||||
{
|
||||
// Lookup the imported soname.
|
||||
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
|
||||
{
|
||||
return info->SOName;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compute the soname that will be built.
|
||||
std::string name;
|
||||
std::string soName;
|
||||
std::string realName;
|
||||
std::string impName;
|
||||
std::string pdbName;
|
||||
this->GetLibraryNames(name, soName, realName, impName, pdbName, config);
|
||||
return soName;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTarget::GetFullName(std::string& prefix, std::string& base,
|
||||
std::string& suffix, const char* config,
|
||||
bool implib)
|
||||
std::string cmTarget::GetFullName(const char* config, bool implib)
|
||||
{
|
||||
if(this->IsImported())
|
||||
{
|
||||
return this->GetFullNameImported(config, implib);
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->GetFullNameInternal(this->GetType(), config, implib);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmTarget::GetFullNameImported(const char* config, bool implib)
|
||||
{
|
||||
return cmSystemTools::GetFilenameName(
|
||||
this->ImportedGetFullPath(config, implib));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTarget::GetFullNameComponents(std::string& prefix, std::string& base,
|
||||
std::string& suffix, const char* config,
|
||||
bool implib)
|
||||
{
|
||||
this->GetFullNameInternal(this->GetType(), config, implib,
|
||||
prefix, base, suffix);
|
||||
|
@ -1766,6 +1949,19 @@ void cmTarget::GetFullName(std::string& prefix, std::string& base,
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmTarget::GetFullPath(const char* config, bool implib)
|
||||
{
|
||||
if(this->IsImported())
|
||||
{
|
||||
return this->ImportedGetFullPath(config, implib);
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->NormalGetFullPath(config, implib);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmTarget::NormalGetFullPath(const char* config, bool implib)
|
||||
{
|
||||
// Start with the output directory for the target.
|
||||
std::string fpath = this->GetDirectory(config, implib);
|
||||
|
@ -1777,8 +1973,31 @@ std::string cmTarget::GetFullPath(const char* config, bool implib)
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmTarget::GetFullNameInternal(TargetType type, const char* config,
|
||||
bool implib)
|
||||
std::string cmTarget::ImportedGetFullPath(const char* config, bool implib)
|
||||
{
|
||||
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
|
||||
{
|
||||
if(implib)
|
||||
{
|
||||
return info->ImportLibrary;
|
||||
}
|
||||
else
|
||||
{
|
||||
return info->Location;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string result = this->GetName();
|
||||
result += "-NOTFOUND";
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string
|
||||
cmTarget::GetFullNameInternal(TargetType type, const char* config,
|
||||
bool implib)
|
||||
{
|
||||
std::string prefix;
|
||||
std::string base;
|
||||
|
@ -1794,43 +2013,6 @@ void cmTarget::GetFullNameInternal(TargetType type,
|
|||
std::string& outPrefix,
|
||||
std::string& outBase,
|
||||
std::string& outSuffix)
|
||||
{
|
||||
if (this->IsImported())
|
||||
{
|
||||
this->ImportedGetFullNameInternal(type, config, implib,
|
||||
outPrefix, outBase, outSuffix);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->NormalGetFullNameInternal(type, config, implib,
|
||||
outPrefix, outBase, outSuffix);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTarget::ImportedGetFullNameInternal(TargetType ,
|
||||
const char* config,
|
||||
bool ,
|
||||
std::string& outPrefix,
|
||||
std::string& outBase,
|
||||
std::string& outSuffix)
|
||||
{
|
||||
// find the basename, suffix and prefix from getLocation()
|
||||
// implib ?
|
||||
std::string location=this->GetLocation(config);
|
||||
outBase=cmSystemTools::GetFilenameWithoutExtension(location);
|
||||
outSuffix = cmSystemTools::GetFilenameExtension(location);
|
||||
outPrefix = "";
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTarget::NormalGetFullNameInternal(TargetType type,
|
||||
const char* config,
|
||||
bool implib,
|
||||
std::string& outPrefix,
|
||||
std::string& outBase,
|
||||
std::string& outSuffix)
|
||||
{
|
||||
// Use just the target name for non-main target types.
|
||||
if(type != cmTarget::STATIC_LIBRARY &&
|
||||
|
@ -2019,6 +2201,14 @@ void cmTarget::GetLibraryNamesInternal(std::string& name,
|
|||
TargetType type,
|
||||
const char* config)
|
||||
{
|
||||
// This should not be called for imported targets.
|
||||
// TODO: Split cmTarget into a class hierarchy to get compile-time
|
||||
// enforcement of the limited imported target API.
|
||||
if(this->IsImported())
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
// Construct the name of the soname flag variable for this language.
|
||||
const char* ll =
|
||||
this->GetLinkerLanguage(
|
||||
|
@ -2140,6 +2330,14 @@ void cmTarget::GetExecutableNamesInternal(std::string& name,
|
|||
TargetType type,
|
||||
const char* config)
|
||||
{
|
||||
// This should not be called for imported targets.
|
||||
// TODO: Split cmTarget into a class hierarchy to get compile-time
|
||||
// enforcement of the limited imported target API.
|
||||
if(this->IsImported())
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
// This versioning is supported only for executables and then only
|
||||
// when the platform supports symbolic links.
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
|
@ -2554,8 +2752,7 @@ const char* cmTarget::GetExportMacro()
|
|||
// Define the symbol for targets that export symbols.
|
||||
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||
this->GetType() == cmTarget::MODULE_LIBRARY ||
|
||||
this->GetType() == cmTarget::EXECUTABLE &&
|
||||
this->GetPropertyAsBool("ENABLE_EXPORTS"))
|
||||
this->IsExecutableWithExports())
|
||||
{
|
||||
if(const char* custom_export_name = this->GetProperty("DEFINE_SYMBOL"))
|
||||
{
|
||||
|
@ -2618,3 +2815,208 @@ bool cmTarget::IsChrpathAvailable()
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmTarget::ImportInfo const*
|
||||
cmTarget::GetImportInfo(const char* config)
|
||||
{
|
||||
// There is no imported information for non-imported targets.
|
||||
if(!this->IsImported())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Lookup/compute/cache the import information for this
|
||||
// configuration.
|
||||
std::string config_upper;
|
||||
if(config && *config)
|
||||
{
|
||||
config_upper = cmSystemTools::UpperCase(config);
|
||||
}
|
||||
else
|
||||
{
|
||||
config_upper = "NOCONFIG";
|
||||
}
|
||||
ImportInfoMapType::const_iterator i =
|
||||
this->ImportInfoMap.find(config_upper);
|
||||
if(i == this->ImportInfoMap.end())
|
||||
{
|
||||
ImportInfo info;
|
||||
this->ComputeImportInfo(config_upper, info);
|
||||
ImportInfoMapType::value_type entry(config_upper, info);
|
||||
i = this->ImportInfoMap.insert(entry).first;
|
||||
}
|
||||
|
||||
// If the location is empty then the target is not available for
|
||||
// this configuration.
|
||||
if(i->second.Location.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Return the import information.
|
||||
return &i->second;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmTarget::ComputeImportInfo(std::string const& desired_config,
|
||||
ImportInfo& info)
|
||||
{
|
||||
// This method finds information about an imported target from its
|
||||
// properties. The "IMPORTED_" namespace is reserved for properties
|
||||
// defined by the project exporting the target.
|
||||
|
||||
// Track the configuration-specific property suffix.
|
||||
std::string suffix = "_";
|
||||
suffix += desired_config;
|
||||
|
||||
// Look for a mapping from the current project's configuration to
|
||||
// the imported project's configuration.
|
||||
std::vector<std::string> mappedConfigs;
|
||||
{
|
||||
std::string mapProp = "MAP_IMPORTED_CONFIG_";
|
||||
mapProp += desired_config;
|
||||
if(const char* mapValue = this->GetProperty(mapProp.c_str()))
|
||||
{
|
||||
cmSystemTools::ExpandListArgument(mapValue, mappedConfigs);
|
||||
}
|
||||
}
|
||||
|
||||
// If a mapping was found, check its configurations.
|
||||
const char* loc = 0;
|
||||
for(std::vector<std::string>::const_iterator mci = mappedConfigs.begin();
|
||||
!loc && mci != mappedConfigs.end(); ++mci)
|
||||
{
|
||||
// Look for this configuration.
|
||||
std::string mcUpper = cmSystemTools::UpperCase(mci->c_str());
|
||||
std::string locProp = "IMPORTED_LOCATION_";
|
||||
locProp += mcUpper;
|
||||
loc = this->GetProperty(locProp.c_str());
|
||||
|
||||
// If it was found, use it for all properties below.
|
||||
if(loc)
|
||||
{
|
||||
suffix = "_";
|
||||
suffix += mcUpper;
|
||||
}
|
||||
}
|
||||
|
||||
// If we needed to find one of the mapped configurations but did not
|
||||
// then the target is not found. The project does not want any
|
||||
// other configuration.
|
||||
if(!mappedConfigs.empty() && !loc)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have not yet found it then there are no mapped
|
||||
// configurations. Look for an exact-match.
|
||||
if(!loc)
|
||||
{
|
||||
std::string locProp = "IMPORTED_LOCATION";
|
||||
locProp += suffix;
|
||||
loc = this->GetProperty(locProp.c_str());
|
||||
}
|
||||
|
||||
// If we have not yet found it then there are no mapped
|
||||
// configurations and no exact match.
|
||||
if(!loc)
|
||||
{
|
||||
// The suffix computed above is not useful.
|
||||
suffix = "";
|
||||
|
||||
// Look for a configuration-less location. This may be set by
|
||||
// manually-written code.
|
||||
loc = this->GetProperty("IMPORTED_LOCATION");
|
||||
}
|
||||
|
||||
// If we have not yet found it then the project is willing to try
|
||||
// any available configuration.
|
||||
if(!loc)
|
||||
{
|
||||
std::vector<std::string> availableConfigs;
|
||||
if(const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS"))
|
||||
{
|
||||
cmSystemTools::ExpandListArgument(iconfigs, availableConfigs);
|
||||
}
|
||||
for(std::vector<std::string>::const_iterator
|
||||
aci = availableConfigs.begin();
|
||||
!loc && aci != availableConfigs.end(); ++aci)
|
||||
{
|
||||
suffix = "_";
|
||||
suffix += cmSystemTools::UpperCase(availableConfigs[0]);
|
||||
std::string locProp = "IMPORTED_LOCATION";
|
||||
locProp += suffix;
|
||||
loc = this->GetProperty(locProp.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// If we have not yet found it then the target is not available.
|
||||
if(!loc)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// A provided configuration has been chosen. Load the
|
||||
// configuration's properties.
|
||||
info.Location = loc;
|
||||
|
||||
// Get the soname.
|
||||
if(this->GetType() == cmTarget::SHARED_LIBRARY)
|
||||
{
|
||||
std::string soProp = "IMPORTED_SONAME";
|
||||
soProp += suffix;
|
||||
if(const char* config_soname = this->GetProperty(soProp.c_str()))
|
||||
{
|
||||
info.SOName = config_soname;
|
||||
}
|
||||
else if(const char* soname = this->GetProperty("IMPORTED_SONAME"))
|
||||
{
|
||||
info.SOName = soname;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the import library.
|
||||
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
|
||||
this->IsExecutableWithExports())
|
||||
{
|
||||
std::string impProp = "IMPORTED_IMPLIB";
|
||||
impProp += suffix;
|
||||
if(const char* config_implib = this->GetProperty(impProp.c_str()))
|
||||
{
|
||||
info.ImportLibrary = config_implib;
|
||||
}
|
||||
else if(const char* implib = this->GetProperty("IMPORTED_IMPLIB"))
|
||||
{
|
||||
info.ImportLibrary = implib;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the link dependencies.
|
||||
{
|
||||
std::string linkProp = "IMPORTED_LINK_LIBRARIES";
|
||||
linkProp += suffix;
|
||||
if(const char* config_libs = this->GetProperty(linkProp.c_str()))
|
||||
{
|
||||
cmSystemTools::ExpandListArgument(config_libs, info.LinkLibraries);
|
||||
}
|
||||
else if(const char* libs = this->GetProperty("IMPORTED_LINK_LIBRARIES"))
|
||||
{
|
||||
cmSystemTools::ExpandListArgument(libs, info.LinkLibraries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::vector<std::string> const*
|
||||
cmTarget::GetImportedLinkLibraries(const char* config)
|
||||
{
|
||||
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config))
|
||||
{
|
||||
return &info->LinkLibraries;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -194,6 +194,11 @@ public:
|
|||
|
||||
bool IsImported() const {return this->IsImportedTarget;}
|
||||
|
||||
/** Get link libraries for the given configuration of an imported
|
||||
target. */
|
||||
std::vector<std::string> const*
|
||||
GetImportedLinkLibraries(const char* config);
|
||||
|
||||
/** Get the directory in which this target will be built. If the
|
||||
configuration name is given then the generator will add its
|
||||
subdirectory for that configuration. Otherwise just the canonical
|
||||
|
@ -226,13 +231,16 @@ public:
|
|||
/** Get the full name of the target according to the settings in its
|
||||
makefile. */
|
||||
std::string GetFullName(const char* config=0, bool implib = false);
|
||||
void GetFullName(std::string& prefix,
|
||||
std::string& base, std::string& suffix,
|
||||
const char* config=0, bool implib = false);
|
||||
void GetFullNameComponents(std::string& prefix,
|
||||
std::string& base, std::string& suffix,
|
||||
const char* config=0, bool implib = false);
|
||||
|
||||
/** Get the name of the pdb file for the target. */
|
||||
std::string GetPDBName(const char* config=0);
|
||||
|
||||
/** Get the soname of the target. Allowed only for a shared library. */
|
||||
std::string GetSOName(const char* config);
|
||||
|
||||
/** Get the full path to the target according to the settings in its
|
||||
makefile and the configuration type. */
|
||||
std::string GetFullPath(const char* config=0, bool implib = false);
|
||||
|
@ -308,6 +316,10 @@ public:
|
|||
// until we have per-target object file properties.
|
||||
void GetLanguages(std::set<cmStdString>& languages) const;
|
||||
|
||||
/** Return whether this target is an executable with symbol exports
|
||||
enabled. */
|
||||
bool IsExecutableWithExports();
|
||||
|
||||
private:
|
||||
/**
|
||||
* A list of direct dependencies. Use in conjunction with DependencyMap.
|
||||
|
@ -393,20 +405,14 @@ private:
|
|||
const char* ImportedGetLocation(const char* config);
|
||||
const char* NormalGetLocation(const char* config);
|
||||
|
||||
void NormalGetFullNameInternal(TargetType type, const char* config,
|
||||
bool implib,
|
||||
std::string& outPrefix,
|
||||
std::string& outBase,
|
||||
std::string& outSuffix);
|
||||
void ImportedGetFullNameInternal(TargetType type, const char* config,
|
||||
bool implib,
|
||||
std::string& outPrefix,
|
||||
std::string& outBase,
|
||||
std::string& outSuffix);
|
||||
std::string GetFullNameImported(const char* config, bool implib);
|
||||
|
||||
const char* ImportedGetDirectory(const char* config, bool implib);
|
||||
const char* NormalGetDirectory(const char* config, bool implib);
|
||||
|
||||
std::string ImportedGetFullPath(const char* config, bool implib);
|
||||
std::string NormalGetFullPath(const char* config, bool implib);
|
||||
|
||||
private:
|
||||
std::string Name;
|
||||
std::vector<cmCustomCommand> PreBuildCommands;
|
||||
|
@ -436,6 +442,19 @@ private:
|
|||
bool DLLPlatform;
|
||||
bool IsImportedTarget;
|
||||
|
||||
// Cache import information from properties for each configuration.
|
||||
struct ImportInfo
|
||||
{
|
||||
std::string Location;
|
||||
std::string SOName;
|
||||
std::string ImportLibrary;
|
||||
std::vector<std::string> LinkLibraries;
|
||||
};
|
||||
typedef std::map<cmStdString, ImportInfo> ImportInfoMapType;
|
||||
ImportInfoMapType ImportInfoMap;
|
||||
ImportInfo const* GetImportInfo(const char* config);
|
||||
void ComputeImportInfo(std::string const& desired_config, ImportInfo& info);
|
||||
|
||||
// The cmMakefile instance that owns this target. This should
|
||||
// always be set.
|
||||
cmMakefile* Makefile;
|
||||
|
|
Loading…
Reference in New Issue