summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorStephen Kelly <steveire@gmail.com>2013-05-16 13:15:28 (GMT)
committerStephen Kelly <steveire@gmail.com>2013-06-02 09:56:37 (GMT)
commit80ca9c4b41ecdce069a6c3f4c1b558084a748876 (patch)
treee96eb29cd532378cd79c3e3ea4bb975ffbc2e285 /Source
parent7cb23084b2595d06aea46cead0e077b5f13aeddb (diff)
downloadCMake-80ca9c4b41ecdce069a6c3f4c1b558084a748876.zip
CMake-80ca9c4b41ecdce069a6c3f4c1b558084a748876.tar.gz
CMake-80ca9c4b41ecdce069a6c3f4c1b558084a748876.tar.bz2
Add COMPILE_OPTIONS target property.
This method reads generator expressions from the COMPILE_OPTIONS target property, as well as INTERFACE_COMPILE_OPTIONS from linked dependents.
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx8
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.h1
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx9
-rw-r--r--Source/cmLocalGenerator.cxx8
-rw-r--r--Source/cmTarget.cxx224
-rw-r--r--Source/cmTarget.h4
6 files changed, 253 insertions, 1 deletions
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index 5cb50b9..e5ffb0c 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -168,3 +168,11 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingCompileDefinitions() const
|| strcmp(prop, "INTERFACE_COMPILE_DEFINITIONS") == 0
|| strncmp(prop, "COMPILE_DEFINITIONS_", 20) == 0);
}
+
+//----------------------------------------------------------------------------
+bool cmGeneratorExpressionDAGChecker::EvaluatingCompileOptions() const
+{
+ const char *prop = this->Property.c_str();
+ return (strcmp(prop, "COMPILE_OPTIONS") == 0
+ || strcmp(prop, "INTERFACE_COMPILE_OPTIONS") == 0 );
+}
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index 62a5cdf..8d9fd76 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -40,6 +40,7 @@ struct cmGeneratorExpressionDAGChecker
bool EvaluatingLinkLibraries();
bool EvaluatingIncludeDirectories() const;
bool EvaluatingCompileDefinitions() const;
+ bool EvaluatingCompileOptions() const;
private:
Result checkGraph() const;
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index f27761a..5e7d00d 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -495,6 +495,7 @@ static const struct JoinNode : public cmGeneratorExpressionNode
static const char* targetPropertyTransitiveWhitelist[] = {
"INTERFACE_INCLUDE_DIRECTORIES"
, "INTERFACE_COMPILE_DEFINITIONS"
+ , "INTERFACE_COMPILE_OPTIONS"
};
std::string getLinkedTargetsContent(const std::vector<std::string> &libraries,
@@ -702,7 +703,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
else
{
assert(dagCheckerParent->EvaluatingIncludeDirectories()
- || dagCheckerParent->EvaluatingCompileDefinitions());
+ || dagCheckerParent->EvaluatingCompileDefinitions()
+ || dagCheckerParent->EvaluatingCompileOptions());
}
}
@@ -721,6 +723,11 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
{
interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
}
+ else if (propertyName == "INTERFACE_COMPILE_OPTIONS"
+ || propertyName == "COMPILE_OPTIONS")
+ {
+ interfacePropertyName = "INTERFACE_COMPILE_OPTIONS";
+ }
const char **transBegin = targetPropertyTransitiveWhitelist;
const char **transEnd = targetPropertyTransitiveWhitelist
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 9429450..57e25a1 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1334,6 +1334,14 @@ void cmLocalGenerator::GetCompileOptions(std::string& flags,
{
this->AppendFlags(flags, prop);
}
+
+ std::vector<std::string> opts; // TODO: Emitted.
+ target->GetCompileOptions(opts, config);
+ for(std::vector<std::string>::const_iterator li = opts.begin();
+ li != opts.end(); ++li)
+ {
+ this->AppendFlags(flags, li->c_str());
+ }
}
//----------------------------------------------------------------------------
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index a54f80b..ea5552e 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -140,14 +140,18 @@ public:
const std::string TargetName;
};
std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
+ std::vector<TargetPropertyEntry*> CompileOptionsEntries;
std::vector<cmValueWithOrigin> LinkInterfacePropertyEntries;
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;
};
//----------------------------------------------------------------------------
@@ -181,6 +185,7 @@ void deleteAndClear(
cmTargetInternals::~cmTargetInternals()
{
deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
+ deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
}
//----------------------------------------------------------------------------
@@ -199,6 +204,7 @@ cmTarget::cmTarget()
this->IsImportedTarget = false;
this->BuildInterfaceIncludesAppended = false;
this->DebugIncludesDone = false;
+ this->DebugCompileOptionsDone = false;
}
//----------------------------------------------------------------------------
@@ -287,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 targets only. "
+ "\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 "
@@ -2731,6 +2763,17 @@ void cmTarget::SetProperty(const char* prop, const char* value)
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;
@@ -2773,6 +2816,15 @@ void cmTarget::AppendProperty(const char* prop, const char* 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;
@@ -3094,6 +3146,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;
@@ -3525,6 +3730,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)
{
@@ -6109,6 +6332,7 @@ cmTargetInternalPointer
cmTargetInternalPointer::~cmTargetInternalPointer()
{
deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
+ deleteAndClear(this->Pointer->CompileOptionsEntries);
delete this->Pointer;
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 508fc11..7ec10df 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -503,6 +503,9 @@ public:
void AppendBuildInterfaceIncludes();
+ void GetCompileOptions(std::vector<std::string> &result,
+ const char *config);
+
bool IsNullImpliedByLinkLibraries(const std::string &p);
bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
const char *config);
@@ -627,6 +630,7 @@ private:
bool IsApple;
bool IsImportedTarget;
bool DebugIncludesDone;
+ bool DebugCompileOptionsDone;
mutable std::set<std::string> LinkImplicitNullProperties;
bool BuildInterfaceIncludesAppended;