summaryrefslogtreecommitdiffstats
path: root/Source/cmTarget.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmTarget.cxx')
-rw-r--r--Source/cmTarget.cxx733
1 files changed, 630 insertions, 103 deletions
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index d14bfca..b14db43 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -130,31 +130,35 @@ public:
typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType;
SourceEntriesType SourceEntries;
- struct IncludeDirectoriesEntry {
- IncludeDirectoriesEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
+ struct TargetPropertyEntry {
+ TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
const std::string &targetName = std::string())
: ge(cge), TargetName(targetName)
{}
const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
- std::vector<std::string> CachedIncludes;
+ std::vector<std::string> CachedEntries;
const std::string TargetName;
};
- std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries;
- std::vector<cmValueWithOrigin> LinkInterfaceIncludeDirectoriesEntries;
+ std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
+ std::vector<TargetPropertyEntry*> CompileOptionsEntries;
+ std::vector<cmValueWithOrigin> LinkInterfacePropertyEntries;
- std::map<std::string, std::vector<IncludeDirectoriesEntry*> >
+ std::map<std::string, std::vector<TargetPropertyEntry*> >
CachedLinkInterfaceIncludeDirectoriesEntries;
+ std::map<std::string, std::vector<TargetPropertyEntry*> >
+ CachedLinkInterfaceCompileOptionsEntries;
std::map<std::string, std::string> CachedLinkInterfaceCompileDefinitions;
std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
+ std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
};
//----------------------------------------------------------------------------
void deleteAndClear(
- std::vector<cmTargetInternals::IncludeDirectoriesEntry*> &entries)
+ std::vector<cmTargetInternals::TargetPropertyEntry*> &entries)
{
- for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
+ for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
it = entries.begin(),
end = entries.end();
it != end; ++it)
@@ -167,10 +171,10 @@ void deleteAndClear(
//----------------------------------------------------------------------------
void deleteAndClear(
std::map<std::string,
- std::vector<cmTargetInternals::IncludeDirectoriesEntry*> > &entries)
+ std::vector<cmTargetInternals::TargetPropertyEntry*> > &entries)
{
for (std::map<std::string,
- std::vector<cmTargetInternals::IncludeDirectoriesEntry*> >::iterator
+ std::vector<cmTargetInternals::TargetPropertyEntry*> >::iterator
it = entries.begin(), end = entries.end(); it != end; ++it)
{
deleteAndClear(it->second);
@@ -180,7 +184,8 @@ void deleteAndClear(
//----------------------------------------------------------------------------
cmTargetInternals::~cmTargetInternals()
{
- deleteAndClear(CachedLinkInterfaceIncludeDirectoriesEntries);
+ deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
+ deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
}
//----------------------------------------------------------------------------
@@ -191,6 +196,7 @@ cmTarget::cmTarget()
this->PolicyStatusCMP0004 = cmPolicies::WARN;
this->PolicyStatusCMP0008 = cmPolicies::WARN;
this->PolicyStatusCMP0020 = cmPolicies::WARN;
+ this->PolicyStatusCMP0021 = cmPolicies::WARN;
this->LinkLibrariesAnalyzed = false;
this->HaveInstallRule = false;
this->DLLPlatform = false;
@@ -198,6 +204,7 @@ cmTarget::cmTarget()
this->IsImportedTarget = false;
this->BuildInterfaceIncludesAppended = false;
this->DebugIncludesDone = false;
+ this->DebugCompileOptionsDone = false;
}
//----------------------------------------------------------------------------
@@ -277,6 +284,7 @@ void cmTarget::DefineProperties(cmake *cm)
"Contents of COMPILE_DEFINITIONS may use \"generator expressions\" with "
"the syntax \"$<...>\". "
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+ CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS
CM_DOCUMENT_COMPILE_DEFINITIONS_DISCLAIMER);
cm->DefineProperty
@@ -285,6 +293,32 @@ void cmTarget::DefineProperties(cmake *cm)
"This is the configuration-specific version of COMPILE_DEFINITIONS.");
cm->DefineProperty
+ ("COMPILE_OPTIONS", cmProperty::TARGET,
+ "List of options to pass to the compiler.",
+ "This property specifies the list of options specified "
+ "so far for this property. "
+ "This property exists on directories and targets. "
+ "\n"
+ "The target property values are used by the generators to set "
+ "the options for the compiler.\n"
+ "Contents of COMPILE_OPTIONS may use \"generator expressions\" with "
+ "the syntax \"$<...>\". "
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+ CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS);
+
+ cm->DefineProperty
+ ("INTERFACE_COMPILE_OPTIONS", cmProperty::TARGET,
+ "List of interface options to pass to the compiler.",
+ "Targets may populate this property to publish the compile options "
+ "required to compile against the headers for the target. Consuming "
+ "targets can add entries to their own COMPILE_OPTIONS property such "
+ "as $<TARGET_PROPERTY:foo,INTERFACE_COMPILE_OPTIONS> to use the "
+ "compile options specified in the interface of 'foo'."
+ "\n"
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+ CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS);
+
+ cm->DefineProperty
("DEFINE_SYMBOL", cmProperty::TARGET,
"Define a symbol when compiling this target's sources.",
"DEFINE_SYMBOL sets the name of the preprocessor symbol defined when "
@@ -292,7 +326,7 @@ void cmTarget::DefineProperties(cmake *cm)
"If not set here then it is set to target_EXPORTS by default "
"(with some substitutions if the target is not a valid C "
"identifier). This is useful for headers to know whether they are "
- "being included from inside their library our outside to properly "
+ "being included from inside their library or outside to properly "
"setup dllexport/dllimport decorations. ");
cm->DefineProperty
@@ -605,7 +639,8 @@ void cmTarget::DefineProperties(cmake *cm)
"See also the include_directories command.\n"
"Contents of INCLUDE_DIRECTORIES may use \"generator expressions\" with "
"the syntax \"$<...>\". "
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+ CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS);
cm->DefineProperty
("INSTALL_NAME_DIR", cmProperty::TARGET,
@@ -802,7 +837,8 @@ void cmTarget::DefineProperties(cmake *cm)
"as $<TARGET_PROPERTY:foo,INTERFACE_INCLUDE_DIRECTORIES> to use the "
"include directories specified in the interface of 'foo'."
"\n"
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+ CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS);
cm->DefineProperty
("INTERFACE_COMPILE_DEFINITIONS", cmProperty::TARGET,
@@ -813,7 +849,8 @@ void cmTarget::DefineProperties(cmake *cm)
"as $<TARGET_PROPERTY:foo,INTERFACE_COMPILE_DEFINITIONS> to use the "
"compile definitions specified in the interface of 'foo'."
"\n"
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+ CM_DOCUMENT_LANGUAGE_GENERATOR_EXPRESSIONS);
cm->DefineProperty
("LINK_INTERFACE_MULTIPLICITY", cmProperty::TARGET,
@@ -867,6 +904,13 @@ void cmTarget::DefineProperties(cmake *cm)
"OSX_ARCHITECTURES.");
cm->DefineProperty
+ ("EXPORT_NAME", cmProperty::TARGET,
+ "Exported name for target files.",
+ "This sets the name for the IMPORTED target generated when it this "
+ "target is is exported. "
+ "If not set, the logical target name is used by default.");
+
+ cm->DefineProperty
("OUTPUT_NAME", cmProperty::TARGET,
"Output name for target files.",
"This sets the base name for output files created for an executable or "
@@ -886,9 +930,9 @@ void cmTarget::DefineProperties(cmake *cm)
cm->DefineProperty
("PDB_NAME", cmProperty::TARGET,
- "Output name for MS debug symbols .pdb file.",
+ "Output name for MS debug symbols .pdb file from linker.",
"Set the base name for debug symbols file created for an "
- "executable or library target. "
+ "executable or shared library target. "
"If not set, the logical target name is used by default. "
"\n"
"This property is not implemented by the Visual Studio 6 generator.");
@@ -916,6 +960,35 @@ void cmTarget::DefineProperties(cmake *cm)
"(such as \"lib\") on a library name.");
cm->DefineProperty
+ ("C_VISIBILITY_PRESET", cmProperty::TARGET,
+ "Value for symbol visibility compile flags",
+ "The C_VISIBILITY_PRESET property determines the value passed used in "
+ "a visibility related compile option, such as -fvisibility=. This "
+ "property only has an affect for libraries and executables with "
+ "exports. This property is initialized by the value of the variable "
+ "CMAKE_C_VISIBILITY_PRESET if it is set when a target is created.");
+
+ cm->DefineProperty
+ ("CXX_VISIBILITY_PRESET", cmProperty::TARGET,
+ "Value for symbol visibility compile flags",
+ "The CXX_VISIBILITY_PRESET property determines the value passed used in "
+ "a visibility related compile option, such as -fvisibility=. This "
+ "property only has an affect for libraries and executables with "
+ "exports. This property is initialized by the value of the variable "
+ "CMAKE_CXX_VISIBILITY_PRESET if it is set when a target is created.");
+
+ cm->DefineProperty
+ ("VISIBILITY_INLINES_HIDDEN", cmProperty::TARGET,
+ "Whether to add a compile flag to hide symbols of inline functions",
+ "The VISIBILITY_INLINES_HIDDEN property determines whether a flag for "
+ "hiding symbols for inline functions. the value passed used in "
+ "a visibility related compile option, such as -fvisibility=. This "
+ "property only has an affect for libraries and executables with "
+ "exports. This property is initialized by the value of the variable "
+ "CMAKE_VISIBILITY_INLINES_HIDDEN if it is set when a target is "
+ "created.");
+
+ cm->DefineProperty
("POSITION_INDEPENDENT_CODE", cmProperty::TARGET,
"Whether to create a position-independent target",
"The POSITION_INDEPENDENT_CODE property determines whether position "
@@ -1054,7 +1127,7 @@ void cmTarget::DefineProperties(cmake *cm)
("SOVERSION", cmProperty::TARGET,
"What version number is this target.",
"For shared libraries VERSION and SOVERSION can be used to specify "
- "the build version and api version respectively. When building or "
+ "the build version and API version respectively. When building or "
"installing appropriate symlinks are created if the platform "
"supports symlinks and the linker supports so-names. "
"If only one of both is specified the missing is assumed to have "
@@ -1092,7 +1165,7 @@ void cmTarget::DefineProperties(cmake *cm)
("VERSION", cmProperty::TARGET,
"What version number is this target.",
"For shared libraries VERSION and SOVERSION can be used to specify "
- "the build version and api version respectively. When building or "
+ "the build version and API version respectively. When building or "
"installing appropriate symlinks are created if the platform "
"supports symlinks and the linker supports so-names. "
"If only one of both is specified the missing is assumed to have "
@@ -1156,7 +1229,7 @@ void cmTarget::DefineProperties(cmake *cm)
cm->DefineProperty
("MACOSX_FRAMEWORK_INFO_PLIST", cmProperty::TARGET,
"Specify a custom Info.plist template for a Mac OS X Framework.",
- "An library target with FRAMEWORK enabled will be built as a "
+ "A library target with FRAMEWORK enabled will be built as a "
"framework on Mac OS X. "
"By default its Info.plist file is created by configuring a template "
"called MacOSXFrameworkInfo.plist.in located in the CMAKE_MODULE_PATH. "
@@ -1174,6 +1247,15 @@ void cmTarget::DefineProperties(cmake *cm)
"hard-code all the settings instead of using the target properties.");
cm->DefineProperty
+ ("MACOSX_RPATH", cmProperty::TARGET,
+ "Whether to use rpaths on Mac OS X.",
+ "When this property is set to true, the directory portion of the"
+ "\"install_name\" field of shared libraries will default to \"@rpath\"."
+ "Runtime paths will also be embedded in binaries using this target."
+ "This property is initialized by the value of the variable "
+ "CMAKE_MACOSX_RPATH if it is set when a target is created.");
+
+ cm->DefineProperty
("ENABLE_EXPORTS", cmProperty::TARGET,
"Specify whether an executable exports symbols for loadable modules.",
"Normally an executable does not export any symbols because it is "
@@ -1247,7 +1329,7 @@ void cmTarget::DefineProperties(cmake *cm)
cm->DefineProperty
("GENERATOR_FILE_NAME", cmProperty::TARGET,
"Generator's file for this target.",
- "An internal property used by some generators to record the name of "
+ "An internal property used by some generators to record the name of the "
"project or dsp file associated with this target. Note that at configure "
"time, this property is only set for targets created by "
"include_external_msproject().");
@@ -1316,6 +1398,16 @@ void cmTarget::DefineProperties(cmake *cm)
"this value with \"ManagedCProj\", for example, in a Visual "
"Studio managed C++ unit test project.");
cm->DefineProperty
+ ("VS_GLOBAL_ROOTNAMESPACE", cmProperty::TARGET,
+ "Visual Studio project root namespace.",
+ "Sets the \"RootNamespace\" attribute for a generated Visual Studio "
+ "project. The attribute will be generated only if this is set.");
+ cm->DefineProperty
+ ("VS_DOTNET_TARGET_FRAMEWORK_VERSION", cmProperty::TARGET,
+ "Specify the .NET target framework version.",
+ "Used to specify the .NET target framework version for C++/CLI. "
+ "For example, \"v4.5\".");
+ cm->DefineProperty
("VS_DOTNET_REFERENCES", cmProperty::TARGET,
"Visual Studio managed project .NET references",
"Adds one or more semicolon-delimited .NET references to a "
@@ -1397,9 +1489,9 @@ void cmTarget::DefineProperties(cmake *cm)
cm->DefineProperty
("PDB_OUTPUT_DIRECTORY", cmProperty::TARGET,
- "Output directory for MS debug symbols .pdb files.",
+ "Output directory for MS debug symbols .pdb file from linker.",
"This property specifies the directory into which the MS debug symbols "
- "will be placed. "
+ "will be placed by the linker. "
"This property is initialized by the value of the variable "
"CMAKE_PDB_OUTPUT_DIRECTORY if it is set when a target is created."
"\n"
@@ -1501,6 +1593,8 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", 0);
this->SetPropertyDefault("WIN32_EXECUTABLE", 0);
this->SetPropertyDefault("MACOSX_BUNDLE", 0);
+ this->SetPropertyDefault("MACOSX_RPATH", 0);
+
// Collect the set of configuration types.
std::vector<std::string> configNames;
@@ -1551,6 +1645,18 @@ void cmTarget::SetMakefile(cmMakefile* mf)
{
this->InsertInclude(*it);
}
+ const std::vector<cmValueWithOrigin> parentOptions =
+ this->Makefile->GetCompileOptionsEntries();
+
+ for (std::vector<cmValueWithOrigin>::const_iterator it
+ = parentOptions.begin(); it != parentOptions.end(); ++it)
+ {
+ this->InsertCompileOption(*it);
+ }
+
+ this->SetPropertyDefault("C_VISIBILITY_PRESET", 0);
+ this->SetPropertyDefault("CXX_VISIBILITY_PRESET", 0);
+ this->SetPropertyDefault("VISIBILITY_INLINES_HIDDEN", 0);
if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY
|| this->TargetTypeValue == cmTarget::MODULE_LIBRARY)
@@ -1568,6 +1674,8 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->Makefile->GetPolicyStatus(cmPolicies::CMP0008);
this->PolicyStatusCMP0020 =
this->Makefile->GetPolicyStatus(cmPolicies::CMP0020);
+ this->PolicyStatusCMP0021 =
+ this->Makefile->GetPolicyStatus(cmPolicies::CMP0021);
}
//----------------------------------------------------------------------------
@@ -1669,6 +1777,13 @@ bool cmTarget::IsCFBundleOnApple()
}
//----------------------------------------------------------------------------
+bool cmTarget::IsBundleOnApple()
+{
+ return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() ||
+ this->IsCFBundleOnApple();
+}
+
+//----------------------------------------------------------------------------
class cmTargetTraceDependencies
{
public:
@@ -2491,8 +2606,6 @@ cmTarget::AnalyzeLibDependencies( const cmMakefile& mf )
}
}
- typedef std::vector< std::string > LinkLine;
-
// The dependency map.
DependencyMap dep_map;
@@ -2716,19 +2829,38 @@ void cmTarget::SetProperty(const char* prop, const char* value)
deleteAndClear(this->Internal->IncludeDirectoriesEntries);
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
this->Internal->IncludeDirectoriesEntries.push_back(
- new cmTargetInternals::IncludeDirectoriesEntry(cge));
+ new cmTargetInternals::TargetPropertyEntry(cge));
+ return;
+ }
+ if(strcmp(prop,"COMPILE_OPTIONS") == 0)
+ {
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ cmGeneratorExpression ge(lfbt);
+ deleteAndClear(this->Internal->CompileOptionsEntries);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
+ this->Internal->CompileOptionsEntries.push_back(
+ new cmTargetInternals::TargetPropertyEntry(cge));
+ return;
+ }
+ if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported())
+ {
+ cmOStringStream e;
+ e << "EXPORT_NAME property can't be set on imported targets (\""
+ << this->Name << "\")\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
return;
}
if (strcmp(prop, "LINK_LIBRARIES") == 0)
{
- this->Internal->LinkInterfaceIncludeDirectoriesEntries.clear();
+ this->Internal->LinkInterfacePropertyEntries.clear();
if (cmGeneratorExpression::IsValidTargetName(value)
|| cmGeneratorExpression::Find(value) != std::string::npos)
{
cmListFileBacktrace lfbt;
this->Makefile->GetBacktrace(lfbt);
cmValueWithOrigin entry(value, lfbt);
- this->Internal->LinkInterfaceIncludeDirectoriesEntries.push_back(entry);
+ this->Internal->LinkInterfacePropertyEntries.push_back(entry);
}
// Fall through
}
@@ -2750,7 +2882,24 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
this->Makefile->GetBacktrace(lfbt);
cmGeneratorExpression ge(lfbt);
this->Internal->IncludeDirectoriesEntries.push_back(
- new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(value)));
+ new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
+ return;
+ }
+ if(strcmp(prop,"COMPILE_OPTIONS") == 0)
+ {
+ cmListFileBacktrace lfbt;
+ this->Makefile->GetBacktrace(lfbt);
+ cmGeneratorExpression ge(lfbt);
+ this->Internal->CompileOptionsEntries.push_back(
+ new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
+ return;
+ }
+ if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported())
+ {
+ cmOStringStream e;
+ e << "EXPORT_NAME property can't be set on imported targets (\""
+ << this->Name << "\")\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
return;
}
if (strcmp(prop, "LINK_LIBRARIES") == 0)
@@ -2761,7 +2910,7 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
cmListFileBacktrace lfbt;
this->Makefile->GetBacktrace(lfbt);
cmValueWithOrigin entry(value, lfbt);
- this->Internal->LinkInterfaceIncludeDirectoriesEntries.push_back(entry);
+ this->Internal->LinkInterfacePropertyEntries.push_back(entry);
}
// Fall through
}
@@ -2770,6 +2919,26 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
}
//----------------------------------------------------------------------------
+const char* cmTarget::GetExportName()
+{
+ const char *exportName = this->GetProperty("EXPORT_NAME");
+
+ if (exportName && *exportName)
+ {
+ if (!cmGeneratorExpression::IsValidTargetName(exportName))
+ {
+ cmOStringStream e;
+ e << "EXPORT_NAME property \"" << exportName << "\" for \""
+ << this->GetName() << "\": is not valid.";
+ cmSystemTools::Error(e.str().c_str());
+ return "";
+ }
+ return exportName;
+ }
+ return this->GetName();
+}
+
+//----------------------------------------------------------------------------
void cmTarget::AppendBuildInterfaceIncludes()
{
if(this->GetType() != cmTarget::SHARED_LIBRARY &&
@@ -2806,17 +2975,31 @@ void cmTarget::InsertInclude(const cmValueWithOrigin &entry,
{
cmGeneratorExpression ge(entry.Backtrace);
- std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::iterator position
+ std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position
= before ? this->Internal->IncludeDirectoriesEntries.begin()
: this->Internal->IncludeDirectoriesEntries.end();
this->Internal->IncludeDirectoriesEntries.insert(position,
- new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(entry.Value)));
+ new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value)));
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::InsertCompileOption(const cmValueWithOrigin &entry,
+ bool before)
+{
+ cmGeneratorExpression ge(entry.Backtrace);
+
+ std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position
+ = before ? this->Internal->CompileOptionsEntries.begin()
+ : this->Internal->CompileOptionsEntries.end();
+
+ this->Internal->CompileOptionsEntries.insert(position,
+ new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value)));
}
//----------------------------------------------------------------------------
static void processIncludeDirectories(cmTarget *tgt,
- const std::vector<cmTargetInternals::IncludeDirectoriesEntry*> &entries,
+ const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
std::vector<std::string> &includes,
std::set<std::string> &uniqueIncludes,
cmGeneratorExpressionDAGChecker *dagChecker,
@@ -2824,12 +3007,12 @@ static void processIncludeDirectories(cmTarget *tgt,
{
cmMakefile *mf = tgt->GetMakefile();
- for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
+ for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
it = entries.begin(), end = entries.end(); it != end; ++it)
{
bool testIsOff = true;
bool cacheIncludes = false;
- std::vector<std::string> entryIncludes = (*it)->CachedIncludes;
+ std::vector<std::string> entryIncludes = (*it)->CachedEntries;
if(!entryIncludes.empty())
{
testIsOff = false;
@@ -2876,14 +3059,41 @@ static void processIncludeDirectories(cmTarget *tgt,
if (!cmSystemTools::FileIsFullPath(li->c_str()))
{
+ cmOStringStream e;
+ bool noMessage = false;
+ cmake::MessageType messageType = cmake::FATAL_ERROR;
if (!(*it)->TargetName.empty())
{
- cmOStringStream e;
e << "Target \"" << (*it)->TargetName << "\" contains relative "
"path in its INTERFACE_INCLUDE_DIRECTORIES:\n"
" \"" << *li << "\" ";
- tgt->GetMakefile()->IssueMessage(cmake::FATAL_ERROR,
- e.str().c_str());
+ }
+ else
+ {
+ switch(tgt->GetPolicyStatusCMP0021())
+ {
+ case cmPolicies::WARN:
+ {
+ cmOStringStream w;
+ e << (mf->GetPolicies()
+ ->GetPolicyWarning(cmPolicies::CMP0021)) << "\n";
+ messageType = cmake::AUTHOR_WARNING;
+ }
+ break;
+ case cmPolicies::OLD:
+ noMessage = true;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Issue the fatal message.
+ break;
+ }
+ e << "Found relative path while evaluating include directories of "
+ "\"" << tgt->GetName() << "\":\n \"" << *li << "\"\n";
+ }
+ if (!noMessage)
+ {
+ tgt->GetMakefile()->IssueMessage(messageType, e.str().c_str());
return;
}
}
@@ -2905,7 +3115,7 @@ static void processIncludeDirectories(cmTarget *tgt,
}
if (cacheIncludes)
{
- (*it)->CachedIncludes = entryIncludes;
+ (*it)->CachedEntries = entryIncludes;
}
if (!usedIncludes.empty())
{
@@ -2925,8 +3135,8 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
cmListFileBacktrace lfbt;
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
- this->GetName(),
- "INCLUDE_DIRECTORIES", 0, 0);
+ this->GetName(),
+ "INCLUDE_DIRECTORIES", 0, 0);
this->AppendBuildInterfaceIncludes();
@@ -2961,8 +3171,8 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
if (!this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[configString])
{
for (std::vector<cmValueWithOrigin>::const_iterator
- it = this->Internal->LinkInterfaceIncludeDirectoriesEntries.begin(),
- end = this->Internal->LinkInterfaceIncludeDirectoriesEntries.end();
+ it = this->Internal->LinkInterfacePropertyEntries.begin(),
+ end = this->Internal->LinkInterfacePropertyEntries.end();
it != end; ++it)
{
{
@@ -2991,7 +3201,7 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
this->Internal
->CachedLinkInterfaceIncludeDirectoriesEntries[configString].push_back(
- new cmTargetInternals::IncludeDirectoriesEntry(cge,
+ new cmTargetInternals::TargetPropertyEntry(cge,
it->Value));
}
}
@@ -3019,6 +3229,159 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
}
//----------------------------------------------------------------------------
+static void processCompileOptions(cmTarget *tgt,
+ const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
+ std::vector<std::string> &options,
+ std::set<std::string> &uniqueOptions,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ const char *config, bool debugOptions)
+{
+ cmMakefile *mf = tgt->GetMakefile();
+
+ for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
+ it = entries.begin(), end = entries.end(); it != end; ++it)
+ {
+ bool cacheOptions = false;
+ std::vector<std::string> entryOptions = (*it)->CachedEntries;
+ if(entryOptions.empty())
+ {
+ cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
+ config,
+ false,
+ tgt,
+ dagChecker),
+ entryOptions);
+ if (mf->IsGeneratingBuildSystem()
+ && !(*it)->ge->GetHadContextSensitiveCondition())
+ {
+ cacheOptions = true;
+ }
+ }
+ std::string usedOptions;
+ for(std::vector<std::string>::iterator
+ li = entryOptions.begin(); li != entryOptions.end(); ++li)
+ {
+ std::string opt = *li;
+
+ if(uniqueOptions.insert(opt).second)
+ {
+ options.push_back(opt);
+ if (debugOptions)
+ {
+ usedOptions += " * " + opt + "\n";
+ }
+ }
+ }
+ if (cacheOptions)
+ {
+ (*it)->CachedEntries = entryOptions;
+ }
+ if (!usedOptions.empty())
+ {
+ mf->GetCMakeInstance()->IssueMessage(cmake::LOG,
+ std::string("Used compile options for target ")
+ + tgt->GetName() + ":\n"
+ + usedOptions, (*it)->ge->GetBacktrace());
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::GetCompileOptions(std::vector<std::string> &result,
+ const char *config)
+{
+ std::set<std::string> uniqueOptions;
+ cmListFileBacktrace lfbt;
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ "COMPILE_OPTIONS", 0, 0);
+
+ std::vector<std::string> debugProperties;
+ const char *debugProp =
+ this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
+ if (debugProp)
+ {
+ cmSystemTools::ExpandListArgument(debugProp, debugProperties);
+ }
+
+ bool debugOptions = !this->DebugCompileOptionsDone
+ && std::find(debugProperties.begin(),
+ debugProperties.end(),
+ "COMPILE_OPTIONS")
+ != debugProperties.end();
+
+ if (this->Makefile->IsGeneratingBuildSystem())
+ {
+ this->DebugCompileOptionsDone = true;
+ }
+
+ processCompileOptions(this,
+ this->Internal->CompileOptionsEntries,
+ result,
+ uniqueOptions,
+ &dagChecker,
+ config,
+ debugOptions);
+
+ std::string configString = config ? config : "";
+ if (!this->Internal->CacheLinkInterfaceCompileOptionsDone[configString])
+ {
+ for (std::vector<cmValueWithOrigin>::const_iterator
+ it = this->Internal->LinkInterfacePropertyEntries.begin(),
+ end = this->Internal->LinkInterfacePropertyEntries.end();
+ it != end; ++it)
+ {
+ {
+ cmGeneratorExpression ge(lfbt);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(it->Value);
+ std::string targetResult = cge->Evaluate(this->Makefile, config,
+ false, this, 0, 0);
+ if (!this->Makefile->FindTargetToUse(targetResult.c_str()))
+ {
+ continue;
+ }
+ }
+ std::string optionGenex = "$<TARGET_PROPERTY:" +
+ it->Value + ",INTERFACE_COMPILE_OPTIONS>";
+ if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
+ {
+ // Because it->Value is a generator expression, ensure that it
+ // evaluates to the non-empty string before being used in the
+ // TARGET_PROPERTY expression.
+ optionGenex = "$<$<BOOL:" + it->Value + ">:" + optionGenex + ">";
+ }
+ cmGeneratorExpression ge(it->Backtrace);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
+ optionGenex);
+
+ this->Internal
+ ->CachedLinkInterfaceCompileOptionsEntries[configString].push_back(
+ new cmTargetInternals::TargetPropertyEntry(cge,
+ it->Value));
+ }
+ }
+
+ processCompileOptions(this,
+ this->Internal->CachedLinkInterfaceCompileOptionsEntries[configString],
+ result,
+ uniqueOptions,
+ &dagChecker,
+ config,
+ debugOptions);
+
+ if (!this->Makefile->IsGeneratingBuildSystem())
+ {
+ deleteAndClear(this->Internal->CachedLinkInterfaceCompileOptionsEntries);
+ }
+ else
+ {
+ this->Internal->CacheLinkInterfaceCompileOptionsDone[configString] = true;
+ }
+}
+
+//----------------------------------------------------------------------------
std::string cmTarget::GetCompileDefinitions(const char *config)
{
const char *configProp = 0;
@@ -3304,17 +3667,23 @@ const char* cmTarget::NormalGetLocation(const char* config)
// Now handle the deprecated build-time configuration location.
this->Location = this->GetDirectory();
- if(!this->Location.empty())
- {
- this->Location += "/";
- }
const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
if(cfgid && strcmp(cfgid, ".") != 0)
{
- this->Location += cfgid;
this->Location += "/";
+ this->Location += cfgid;
+ }
+
+ if(this->IsAppBundleOnApple())
+ {
+ std::string macdir = this->BuildMacContentDirectory("", config, false);
+ if(!macdir.empty())
+ {
+ this->Location += "/";
+ this->Location += macdir;
+ }
}
- this->Location = this->BuildMacContentDirectory(this->Location, config);
+ this->Location += "/";
this->Location += this->GetFullName(config, false);
return this->Location.c_str();
}
@@ -3437,9 +3806,9 @@ const char *cmTarget::GetProperty(const char* prop,
static std::string output;
output = "";
std::string sep;
- typedef cmTargetInternals::IncludeDirectoriesEntry
- IncludeDirectoriesEntry;
- for (std::vector<IncludeDirectoriesEntry*>::const_iterator
+ typedef cmTargetInternals::TargetPropertyEntry
+ TargetPropertyEntry;
+ for (std::vector<TargetPropertyEntry*>::const_iterator
it = this->Internal->IncludeDirectoriesEntries.begin(),
end = this->Internal->IncludeDirectoriesEntries.end();
it != end; ++it)
@@ -3450,6 +3819,24 @@ const char *cmTarget::GetProperty(const char* prop,
}
return output.c_str();
}
+ if(strcmp(prop,"COMPILE_OPTIONS") == 0)
+ {
+ static std::string output;
+ output = "";
+ std::string sep;
+ typedef cmTargetInternals::TargetPropertyEntry
+ TargetPropertyEntry;
+ for (std::vector<TargetPropertyEntry*>::const_iterator
+ it = this->Internal->CompileOptionsEntries.begin(),
+ end = this->Internal->CompileOptionsEntries.end();
+ it != end; ++it)
+ {
+ output += sep;
+ output += (*it)->ge->GetInput();
+ sep = ";";
+ }
+ return output.c_str();
+ }
if (strcmp(prop,"IMPORTED") == 0)
{
@@ -3798,6 +4185,10 @@ std::string cmTarget::GetSOName(const char* config)
else
{
// Use the soname given if any.
+ if(info->SOName.find("@rpath/") == 0)
+ {
+ return info->SOName.substr(6);
+ }
return info->SOName;
}
}
@@ -3820,6 +4211,75 @@ std::string cmTarget::GetSOName(const char* config)
}
//----------------------------------------------------------------------------
+bool cmTarget::HasMacOSXRpath(const char* config)
+{
+ bool install_name_is_rpath = false;
+ bool macosx_rpath = this->GetPropertyAsBool("MACOSX_RPATH");
+
+ if(!this->IsImportedTarget)
+ {
+ const char* install_name = this->GetProperty("INSTALL_NAME_DIR");
+ bool use_install_name =
+ this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
+ if(install_name && use_install_name &&
+ std::string(install_name) == "@rpath")
+ {
+ install_name_is_rpath = true;
+ }
+ }
+ else
+ {
+ // Lookup the imported soname.
+ if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
+ {
+ if(!info->NoSOName && !info->SOName.empty())
+ {
+ if(info->SOName.find("@rpath/") == 0)
+ {
+ install_name_is_rpath = true;
+ }
+ }
+ else
+ {
+ std::string install_name;
+ cmSystemTools::GuessLibraryInstallName(info->Location, install_name);
+ if(install_name.find("@rpath") != std::string::npos)
+ {
+ install_name_is_rpath = true;
+ }
+ }
+ }
+ }
+
+ if(!install_name_is_rpath && !macosx_rpath)
+ {
+ return false;
+ }
+
+ if(!this->Makefile->IsSet("CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG"))
+ {
+ cmOStringStream w;
+ w << "Attempting to use";
+ if(macosx_rpath)
+ {
+ w << " MACOSX_RPATH";
+ }
+ else
+ {
+ w << " @rpath";
+ }
+ w << " without CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG being set.";
+ w << " This could be because you are using a Mac OS X version";
+ w << " less than 10.5 or because CMake's platform configuration is";
+ w << " corrupt.";
+ cmake* cm = this->Makefile->GetCMakeInstance();
+ cm->IssueMessage(cmake::FATAL_ERROR, w.str(), this->GetBacktrace());
+ }
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config)
{
if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY)
@@ -3916,7 +4376,13 @@ std::string cmTarget::GetFullPath(const char* config, bool implib,
std::string cmTarget::NormalGetFullPath(const char* config, bool implib,
bool realname)
{
- std::string fpath = this->GetMacContentDirectory(config, implib);
+ std::string fpath = this->GetDirectory(config, implib);
+ fpath += "/";
+ if(this->IsAppBundleOnApple())
+ {
+ fpath = this->BuildMacContentDirectory(fpath, config, false);
+ fpath += "/";
+ }
// Add the full name of the target.
if(implib)
@@ -4048,10 +4514,28 @@ void cmTarget::GetFullNameInternal(const char* config,
targetSuffix = this->Makefile->GetSafeDefinition(suffixVar);
}
- // frameworks do not have a prefix or a suffix
+ // frameworks have directory prefix but no suffix
+ std::string fw_prefix;
if(this->IsFrameworkOnApple())
{
- targetPrefix = 0;
+ fw_prefix = this->GetOutputName(config, false);
+ fw_prefix += ".framework/";
+ targetPrefix = fw_prefix.c_str();
+ targetSuffix = 0;
+ }
+
+ if(this->IsCFBundleOnApple())
+ {
+ fw_prefix = this->GetOutputName(config, false);
+ fw_prefix += ".";
+ const char *ext = this->GetProperty("BUNDLE_EXTENSION");
+ if (!ext)
+ {
+ ext = "bundle";
+ }
+ fw_prefix += ext;
+ fw_prefix += "/Contents/MacOS/";
+ targetPrefix = fw_prefix.c_str();
targetSuffix = 0;
}
@@ -4131,13 +4615,24 @@ void cmTarget::GetLibraryNames(std::string& name,
// The library name.
name = prefix+base+suffix;
- // The library's soname.
- this->ComputeVersionedName(soName, prefix, base, suffix,
- name, soversion);
-
- // The library's real name on disk.
- this->ComputeVersionedName(realName, prefix, base, suffix,
- name, version);
+ if(this->IsFrameworkOnApple())
+ {
+ realName = prefix;
+ realName += "Versions/";
+ realName += this->GetFrameworkVersion();
+ realName += "/";
+ realName += base;
+ soName = realName;
+ }
+ else
+ {
+ // The library's soname.
+ this->ComputeVersionedName(soName, prefix, base, suffix,
+ name, soversion);
+ // The library's real name on disk.
+ this->ComputeVersionedName(realName, prefix, base, suffix,
+ name, version);
+ }
// The import library name.
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
@@ -4425,14 +4920,13 @@ bool cmTarget::NeedRelinkBeforeInstall(const char* config)
}
//----------------------------------------------------------------------------
-std::string cmTarget::GetInstallNameDirForBuildTree(const char* config,
- bool for_xcode)
+std::string cmTarget::GetInstallNameDirForBuildTree(const char* config)
{
// If building directly for installation then the build tree install_name
// is the same as the install tree.
if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
{
- return GetInstallNameDirForInstallTree(config, for_xcode);
+ return GetInstallNameDirForInstallTree();
}
// Use the build tree directory for the target.
@@ -4440,12 +4934,16 @@ std::string cmTarget::GetInstallNameDirForBuildTree(const char* config,
!this->Makefile->IsOn("CMAKE_SKIP_RPATH") &&
!this->GetPropertyAsBool("SKIP_BUILD_RPATH"))
{
- std::string dir = this->GetDirectory(config);
- dir += "/";
- if(this->IsFrameworkOnApple() && !for_xcode)
+ std::string dir;
+ if(this->GetPropertyAsBool("MACOSX_RPATH"))
{
- dir += this->GetFrameworkDirectory(config);
+ dir = "@rpath";
}
+ else
+ {
+ dir = this->GetDirectory(config);
+ }
+ dir += "/";
return dir;
}
else
@@ -4455,8 +4953,7 @@ std::string cmTarget::GetInstallNameDirForBuildTree(const char* config,
}
//----------------------------------------------------------------------------
-std::string cmTarget::GetInstallNameDirForInstallTree(const char* config,
- bool for_xcode)
+std::string cmTarget::GetInstallNameDirForInstallTree()
{
if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
{
@@ -4472,12 +4969,10 @@ std::string cmTarget::GetInstallNameDirForInstallTree(const char* config,
dir += "/";
}
}
-
- if(this->IsFrameworkOnApple() && !for_xcode)
+ if(dir.empty() && this->GetPropertyAsBool("MACOSX_RPATH"))
{
- dir += this->GetFrameworkDirectory(config);
+ dir = "@rpath/";
}
-
return dir;
}
else
@@ -5059,7 +5554,6 @@ void cmTarget::GetLanguages(std::set<cmStdString>& languages) const
//----------------------------------------------------------------------------
bool cmTarget::IsChrpathUsed(const char* config)
{
-#if defined(CMAKE_USE_ELF_PARSER)
// Only certain target types have an rpath.
if(!(this->GetType() == cmTarget::SHARED_LIBRARY ||
this->GetType() == cmTarget::MODULE_LIBRARY ||
@@ -5093,6 +5587,12 @@ bool cmTarget::IsChrpathUsed(const char* config)
return false;
}
+ if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
+ {
+ return true;
+ }
+
+#if defined(CMAKE_USE_ELF_PARSER)
// Enable if the rpath flag uses a separator and the target uses ELF
// binaries.
if(const char* ll = this->GetLinkerLanguage(config, this))
@@ -5289,7 +5789,6 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
ImportInfo& info,
cmTarget *headTarget)
{
- (void)headTarget;
// 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.
@@ -5936,59 +6435,86 @@ cmTarget::GetLinkInformation(const char* config, cmTarget *head)
}
//----------------------------------------------------------------------------
-std::string cmTarget::GetFrameworkDirectory(const char* config)
+std::string cmTarget::GetFrameworkDirectory(const char* config,
+ bool rootDir)
{
std::string fpath;
- fpath += this->GetFullName(config, false);
- fpath += ".framework/Versions/";
- fpath += this->GetFrameworkVersion();
- fpath += "/";
+ fpath += this->GetOutputName(config, false);
+ fpath += ".framework";
+ if(!rootDir)
+ {
+ fpath += "/Versions/";
+ fpath += this->GetFrameworkVersion();
+ }
+ return fpath;
+}
+
+//----------------------------------------------------------------------------
+std::string cmTarget::GetCFBundleDirectory(const char* config,
+ bool contentOnly)
+{
+ std::string fpath;
+ fpath += this->GetOutputName(config, false);
+ fpath += ".";
+ const char *ext = this->GetProperty("BUNDLE_EXTENSION");
+ if (!ext)
+ {
+ ext = "bundle";
+ }
+ fpath += ext;
+ fpath += "/Contents";
+ if(!contentOnly)
+ fpath += "/MacOS";
+ return fpath;
+}
+
+//----------------------------------------------------------------------------
+std::string cmTarget::GetAppBundleDirectory(const char* config,
+ bool contentOnly)
+{
+ std::string fpath = this->GetFullName(config, false);
+ fpath += ".app/Contents";
+ if(!contentOnly)
+ fpath += "/MacOS";
return fpath;
}
//----------------------------------------------------------------------------
std::string cmTarget::BuildMacContentDirectory(const std::string& base,
const char* config,
- bool includeMacOS)
+ bool contentOnly)
{
std::string fpath = base;
if(this->IsAppBundleOnApple())
{
- fpath += this->GetFullName(config, false);
- fpath += ".app/Contents/";
- if(includeMacOS)
- fpath += "MacOS/";
+ fpath += this->GetAppBundleDirectory(config, contentOnly);
}
if(this->IsFrameworkOnApple())
{
- fpath += this->GetFrameworkDirectory(config);
+ fpath += this->GetFrameworkDirectory(config, contentOnly);
}
if(this->IsCFBundleOnApple())
{
- fpath += this->GetFullName(config, false);
- fpath += ".";
- const char *ext = this->GetProperty("BUNDLE_EXTENSION");
- if (!ext)
- {
- ext = "bundle";
- }
- fpath += ext;
- fpath += "/Contents/";
- if(includeMacOS)
- fpath += "MacOS/";
+ fpath += this->GetCFBundleDirectory(config, contentOnly);
}
return fpath;
}
//----------------------------------------------------------------------------
std::string cmTarget::GetMacContentDirectory(const char* config,
- bool implib,
- bool includeMacOS)
+ bool implib)
{
// Start with the output directory for the target.
std::string fpath = this->GetDirectory(config, implib);
fpath += "/";
- fpath = this->BuildMacContentDirectory(fpath, config, includeMacOS);
+ bool contentOnly = true;
+ if(this->IsFrameworkOnApple())
+ {
+ // additional files with a framework go into the version specific
+ // directory
+ contentOnly = false;
+ }
+ fpath = this->BuildMacContentDirectory(fpath, config, contentOnly);
return fpath;
}
@@ -6035,6 +6561,7 @@ cmTargetInternalPointer
cmTargetInternalPointer::~cmTargetInternalPointer()
{
deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
+ deleteAndClear(this->Pointer->CompileOptionsEntries);
delete this->Pointer;
}