cmTarget: Allow transitive evaluation of SOURCES property.
Extend the cmGeneratorExpressionDAGChecker with an interface returning the name of the top target. Use that to determine when there is a DAG violation, as required by the RunCMake.Languages tests.
This commit is contained in:
parent
e6971df6ab
commit
3676fb4963
|
@ -152,6 +152,7 @@ Properties on Targets
|
||||||
/prop_tgt/INTERFACE_INCLUDE_DIRECTORIES
|
/prop_tgt/INTERFACE_INCLUDE_DIRECTORIES
|
||||||
/prop_tgt/INTERFACE_LINK_LIBRARIES
|
/prop_tgt/INTERFACE_LINK_LIBRARIES
|
||||||
/prop_tgt/INTERFACE_POSITION_INDEPENDENT_CODE
|
/prop_tgt/INTERFACE_POSITION_INDEPENDENT_CODE
|
||||||
|
/prop_tgt/INTERFACE_SOURCES
|
||||||
/prop_tgt/INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
|
/prop_tgt/INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
|
||||||
/prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG
|
/prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG
|
||||||
/prop_tgt/INTERPROCEDURAL_OPTIMIZATION
|
/prop_tgt/INTERPROCEDURAL_OPTIMIZATION
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
INTERFACE_SOURCES
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
List of interface sources to pass to the compiler.
|
||||||
|
|
||||||
|
Targets may populate this property to publish the sources
|
||||||
|
for consuming targets to compile. Consuming
|
||||||
|
targets can add entries to their own :prop_tgt:`SOURCES` property
|
||||||
|
such as ``$<TARGET_PROPERTY:foo,INTERFACE_SOURCES>`` to use the
|
||||||
|
sources specified in the interface of ``foo``.
|
||||||
|
|
||||||
|
Contents of ``INTERFACE_SOURCES`` may use "generator expressions"
|
||||||
|
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
|
||||||
|
manual for available expressions. See the :manual:`cmake-buildsystem(7)`
|
||||||
|
manual for more on defining buildsystem properties.
|
|
@ -0,0 +1,5 @@
|
||||||
|
target-INTERFACE_SOURCES
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
* A new :prop_tgt:`INTERFACE_SOURCES` target property was introduced. This is
|
||||||
|
consumed by dependent targets, which compile and link the listed sources.
|
|
@ -179,6 +179,18 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char *tgt)
|
||||||
|| strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
|
|| strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string cmGeneratorExpressionDAGChecker::TopTarget() const
|
||||||
|
{
|
||||||
|
const cmGeneratorExpressionDAGChecker *top = this;
|
||||||
|
const cmGeneratorExpressionDAGChecker *parent = this->Parent;
|
||||||
|
while (parent)
|
||||||
|
{
|
||||||
|
top = parent;
|
||||||
|
parent = parent->Parent;
|
||||||
|
}
|
||||||
|
return top->Target;
|
||||||
|
}
|
||||||
|
|
||||||
enum TransitiveProperty {
|
enum TransitiveProperty {
|
||||||
#define DEFINE_ENUM_ENTRY(NAME) NAME,
|
#define DEFINE_ENUM_ENTRY(NAME) NAME,
|
||||||
CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(DEFINE_ENUM_ENTRY)
|
CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(DEFINE_ENUM_ENTRY)
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
SELECT(F, EvaluatingSystemIncludeDirectories, SYSTEM_INCLUDE_DIRECTORIES) \
|
SELECT(F, EvaluatingSystemIncludeDirectories, SYSTEM_INCLUDE_DIRECTORIES) \
|
||||||
SELECT(F, EvaluatingCompileDefinitions, COMPILE_DEFINITIONS) \
|
SELECT(F, EvaluatingCompileDefinitions, COMPILE_DEFINITIONS) \
|
||||||
SELECT(F, EvaluatingCompileOptions, COMPILE_OPTIONS) \
|
SELECT(F, EvaluatingCompileOptions, COMPILE_OPTIONS) \
|
||||||
SELECT(F, EvaluatingAutoUicOptions, AUTOUIC_OPTIONS)
|
SELECT(F, EvaluatingAutoUicOptions, AUTOUIC_OPTIONS) \
|
||||||
|
SELECT(F, EvaluatingSources, SOURCES)
|
||||||
|
|
||||||
#define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \
|
#define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \
|
||||||
CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH)
|
CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH)
|
||||||
|
@ -70,6 +71,8 @@ struct cmGeneratorExpressionDAGChecker
|
||||||
void SetTransitivePropertiesOnly()
|
void SetTransitivePropertiesOnly()
|
||||||
{ this->TransitivePropertiesOnly = true; }
|
{ this->TransitivePropertiesOnly = true; }
|
||||||
|
|
||||||
|
std::string TopTarget() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Result CheckGraph() const;
|
Result CheckGraph() const;
|
||||||
|
|
||||||
|
|
|
@ -985,7 +985,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
||||||
if (propertyName == "LINKER_LANGUAGE")
|
if (propertyName == "LINKER_LANGUAGE")
|
||||||
{
|
{
|
||||||
if (target->LinkLanguagePropagatesToDependents() &&
|
if (target->LinkLanguagePropagatesToDependents() &&
|
||||||
dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries())
|
dagCheckerParent && (dagCheckerParent->EvaluatingLinkLibraries()
|
||||||
|
|| dagCheckerParent->EvaluatingSources()))
|
||||||
{
|
{
|
||||||
reportError(context, content->GetOriginalExpression(),
|
reportError(context, content->GetOriginalExpression(),
|
||||||
"LINKER_LANGUAGE target property can not be used while evaluating "
|
"LINKER_LANGUAGE target property can not be used while evaluating "
|
||||||
|
@ -1569,7 +1570,9 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
|
||||||
"Target \"" + name + "\" is not an executable or library.");
|
"Target \"" + name + "\" is not an executable or library.");
|
||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
if (dagChecker && dagChecker->EvaluatingLinkLibraries(name.c_str()))
|
if (dagChecker && (dagChecker->EvaluatingLinkLibraries(name.c_str())
|
||||||
|
|| (dagChecker->EvaluatingSources()
|
||||||
|
&& name == dagChecker->TopTarget())))
|
||||||
{
|
{
|
||||||
::reportError(context, content->GetOriginalExpression(),
|
::reportError(context, content->GetOriginalExpression(),
|
||||||
"Expressions which require the linker language may not "
|
"Expressions which require the linker language may not "
|
||||||
|
|
|
@ -159,10 +159,13 @@ public:
|
||||||
CachedLinkInterfaceCompileOptionsEntries;
|
CachedLinkInterfaceCompileOptionsEntries;
|
||||||
mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
|
mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
|
||||||
CachedLinkInterfaceCompileDefinitionsEntries;
|
CachedLinkInterfaceCompileDefinitionsEntries;
|
||||||
|
mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
|
||||||
|
CachedLinkInterfaceSourcesEntries;
|
||||||
|
|
||||||
mutable std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
|
mutable std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
|
||||||
mutable std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
|
mutable std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
|
||||||
mutable std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
|
mutable std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
|
||||||
|
mutable std::map<std::string, bool> CacheLinkInterfaceSourcesDone;
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -198,6 +201,7 @@ cmTargetInternals::~cmTargetInternals()
|
||||||
deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
|
deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
|
||||||
deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
|
deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
|
||||||
deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries);
|
deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries);
|
||||||
|
deleteAndClear(this->CachedLinkInterfaceSourcesEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -542,41 +546,155 @@ bool cmTarget::IsBundleOnApple() const
|
||||||
this->IsCFBundleOnApple();
|
this->IsCFBundleOnApple();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
static void processSources(cmTarget const* tgt,
|
||||||
|
const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
|
||||||
|
std::vector<std::string> &srcs,
|
||||||
|
std::set<std::string> &uniqueSrcs,
|
||||||
|
cmGeneratorExpressionDAGChecker *dagChecker,
|
||||||
|
cmTarget const* head,
|
||||||
|
std::string const& config)
|
||||||
|
{
|
||||||
|
cmMakefile *mf = tgt->GetMakefile();
|
||||||
|
|
||||||
|
for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
|
||||||
|
it = entries.begin(), end = entries.end(); it != end; ++it)
|
||||||
|
{
|
||||||
|
bool cacheSources = false;
|
||||||
|
std::vector<std::string> entrySources = (*it)->CachedEntries;
|
||||||
|
if(entrySources.empty())
|
||||||
|
{
|
||||||
|
cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
|
||||||
|
config,
|
||||||
|
false,
|
||||||
|
head ? head : tgt,
|
||||||
|
tgt,
|
||||||
|
dagChecker),
|
||||||
|
entrySources);
|
||||||
|
if (mf->IsGeneratingBuildSystem()
|
||||||
|
&& !(*it)->ge->GetHadContextSensitiveCondition())
|
||||||
|
{
|
||||||
|
cacheSources = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(std::vector<std::string>::iterator i = entrySources.begin();
|
||||||
|
i != entrySources.end(); ++i)
|
||||||
|
{
|
||||||
|
std::string& src = *i;
|
||||||
|
|
||||||
|
cmSourceFile* sf = mf->GetOrCreateSource(src);
|
||||||
|
std::string e;
|
||||||
|
src = sf->GetFullPath(&e);
|
||||||
|
if(src.empty())
|
||||||
|
{
|
||||||
|
if(!e.empty())
|
||||||
|
{
|
||||||
|
cmake* cm = mf->GetCMakeInstance();
|
||||||
|
cm->IssueMessage(cmake::FATAL_ERROR, e,
|
||||||
|
tgt->GetBacktrace());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cacheSources)
|
||||||
|
{
|
||||||
|
(*it)->CachedEntries = entrySources;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(std::vector<std::string>::iterator
|
||||||
|
li = entrySources.begin(); li != entrySources.end(); ++li)
|
||||||
|
{
|
||||||
|
std::string src = *li;
|
||||||
|
|
||||||
|
if(uniqueSrcs.insert(src).second)
|
||||||
|
{
|
||||||
|
srcs.push_back(src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void cmTarget::GetSourceFiles(std::vector<std::string> &files,
|
void cmTarget::GetSourceFiles(std::vector<std::string> &files,
|
||||||
const std::string& config) const
|
const std::string& config,
|
||||||
|
cmTarget const* head) const
|
||||||
{
|
{
|
||||||
assert(this->GetType() != INTERFACE_LIBRARY);
|
assert(this->GetType() != INTERFACE_LIBRARY);
|
||||||
for(std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
|
|
||||||
si = this->Internal->SourceEntries.begin();
|
|
||||||
si != this->Internal->SourceEntries.end(); ++si)
|
|
||||||
{
|
|
||||||
std::vector<std::string> srcs;
|
|
||||||
cmSystemTools::ExpandListArgument((*si)->ge->Evaluate(this->Makefile,
|
|
||||||
config,
|
|
||||||
false,
|
|
||||||
this),
|
|
||||||
srcs);
|
|
||||||
|
|
||||||
for(std::vector<std::string>::const_iterator i = srcs.begin();
|
|
||||||
i != srcs.end(); ++i)
|
cmListFileBacktrace lfbt;
|
||||||
|
|
||||||
|
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
|
||||||
|
this->GetName(),
|
||||||
|
"SOURCES", 0, 0);
|
||||||
|
|
||||||
|
std::set<std::string> uniqueSrcs;
|
||||||
|
processSources(this,
|
||||||
|
this->Internal->SourceEntries,
|
||||||
|
files,
|
||||||
|
uniqueSrcs,
|
||||||
|
&dagChecker,
|
||||||
|
head,
|
||||||
|
config);
|
||||||
|
|
||||||
|
if (!this->Internal->CacheLinkInterfaceSourcesDone[config])
|
||||||
|
{
|
||||||
|
for (std::vector<cmValueWithOrigin>::const_iterator
|
||||||
|
it = this->Internal->LinkImplementationPropertyEntries.begin(),
|
||||||
|
end = this->Internal->LinkImplementationPropertyEntries.end();
|
||||||
|
it != end; ++it)
|
||||||
{
|
{
|
||||||
std::string src = *i;
|
if (!cmGeneratorExpression::IsValidTargetName(it->Value)
|
||||||
cmSourceFile* sf = this->Makefile->GetOrCreateSource(src);
|
&& cmGeneratorExpression::Find(it->Value) == std::string::npos)
|
||||||
std::string e;
|
|
||||||
src = sf->GetFullPath(&e);
|
|
||||||
if(src.empty())
|
|
||||||
{
|
{
|
||||||
if(!e.empty())
|
continue;
|
||||||
{
|
}
|
||||||
cmake* cm = this->Makefile->GetCMakeInstance();
|
{
|
||||||
cm->IssueMessage(cmake::FATAL_ERROR, e,
|
cmGeneratorExpression ge(lfbt);
|
||||||
this->GetBacktrace());
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
|
||||||
}
|
ge.Parse(it->Value);
|
||||||
return;
|
std::string targetResult = cge->Evaluate(this->Makefile, config,
|
||||||
|
false, this, 0, &dagChecker);
|
||||||
|
if (!this->Makefile->FindTargetToUse(targetResult))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
files.push_back(src);
|
|
||||||
}
|
}
|
||||||
|
std::string sourceGenex = "$<TARGET_PROPERTY:" +
|
||||||
|
it->Value + ",INTERFACE_SOURCES>";
|
||||||
|
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.
|
||||||
|
sourceGenex = "$<$<BOOL:" + it->Value + ">:" + sourceGenex + ">";
|
||||||
|
}
|
||||||
|
cmGeneratorExpression ge(it->Backtrace);
|
||||||
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
|
||||||
|
sourceGenex);
|
||||||
|
|
||||||
|
this->Internal
|
||||||
|
->CachedLinkInterfaceSourcesEntries[config].push_back(
|
||||||
|
new cmTargetInternals::TargetPropertyEntry(cge,
|
||||||
|
it->Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processSources(this,
|
||||||
|
this->Internal->CachedLinkInterfaceSourcesEntries[config],
|
||||||
|
files,
|
||||||
|
uniqueSrcs,
|
||||||
|
&dagChecker,
|
||||||
|
head,
|
||||||
|
config);
|
||||||
|
|
||||||
|
if (!this->Makefile->IsGeneratingBuildSystem())
|
||||||
|
{
|
||||||
|
deleteAndClear(this->Internal->CachedLinkInterfaceSourcesEntries);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->Internal->CacheLinkInterfaceSourcesDone[config] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,10 +757,11 @@ cmTarget::GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files,
|
void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files,
|
||||||
const std::string& config) const
|
const std::string& config,
|
||||||
|
cmTarget const* head) const
|
||||||
{
|
{
|
||||||
std::vector<std::string> srcs;
|
std::vector<std::string> srcs;
|
||||||
this->GetSourceFiles(srcs, config);
|
this->GetSourceFiles(srcs, config, head);
|
||||||
|
|
||||||
std::set<cmSourceFile*> emitted;
|
std::set<cmSourceFile*> emitted;
|
||||||
|
|
||||||
|
@ -5053,10 +5172,11 @@ bool cmTarget::IsLinkInterfaceDependentNumberMaxProperty(const std::string &p,
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void cmTarget::GetLanguages(std::set<std::string>& languages,
|
void cmTarget::GetLanguages(std::set<std::string>& languages,
|
||||||
const std::string& config) const
|
const std::string& config,
|
||||||
|
cmTarget const* head) const
|
||||||
{
|
{
|
||||||
std::vector<cmSourceFile*> sourceFiles;
|
std::vector<cmSourceFile*> sourceFiles;
|
||||||
this->GetSourceFiles(sourceFiles, config);
|
this->GetSourceFiles(sourceFiles, config, head);
|
||||||
for(std::vector<cmSourceFile*>::const_iterator
|
for(std::vector<cmSourceFile*>::const_iterator
|
||||||
i = sourceFiles.begin(); i != sourceFiles.end(); ++i)
|
i = sourceFiles.begin(); i != sourceFiles.end(); ++i)
|
||||||
{
|
{
|
||||||
|
@ -5111,7 +5231,7 @@ void cmTarget::GetLanguages(std::set<std::string>& languages,
|
||||||
for(std::vector<cmTarget*>::const_iterator
|
for(std::vector<cmTarget*>::const_iterator
|
||||||
i = objectLibraries.begin(); i != objectLibraries.end(); ++i)
|
i = objectLibraries.begin(); i != objectLibraries.end(); ++i)
|
||||||
{
|
{
|
||||||
(*i)->GetLanguages(languages, config);
|
(*i)->GetLanguages(languages, config, head);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6050,7 +6170,7 @@ cmTarget::GetLinkImplementation(const std::string& config,
|
||||||
// Compute the link implementation for this configuration.
|
// Compute the link implementation for this configuration.
|
||||||
LinkImplementation impl;
|
LinkImplementation impl;
|
||||||
this->ComputeLinkImplementation(config, impl, head);
|
this->ComputeLinkImplementation(config, impl, head);
|
||||||
this->ComputeLinkImplementationLanguages(config, impl);
|
this->ComputeLinkImplementationLanguages(config, impl, head);
|
||||||
|
|
||||||
// Store the information for this configuration.
|
// Store the information for this configuration.
|
||||||
cmTargetInternals::LinkImplMapType::value_type entry(key, impl);
|
cmTargetInternals::LinkImplMapType::value_type entry(key, impl);
|
||||||
|
@ -6058,7 +6178,7 @@ cmTarget::GetLinkImplementation(const std::string& config,
|
||||||
}
|
}
|
||||||
else if (i->second.Languages.empty())
|
else if (i->second.Languages.empty())
|
||||||
{
|
{
|
||||||
this->ComputeLinkImplementationLanguages(config, i->second);
|
this->ComputeLinkImplementationLanguages(config, i->second, head);
|
||||||
}
|
}
|
||||||
|
|
||||||
return &i->second;
|
return &i->second;
|
||||||
|
@ -6172,12 +6292,13 @@ void cmTarget::ComputeLinkImplementation(const std::string& config,
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void
|
void
|
||||||
cmTarget::ComputeLinkImplementationLanguages(const std::string& config,
|
cmTarget::ComputeLinkImplementationLanguages(const std::string& config,
|
||||||
LinkImplementation& impl) const
|
LinkImplementation& impl,
|
||||||
|
cmTarget const* head) const
|
||||||
{
|
{
|
||||||
// This target needs runtime libraries for its source languages.
|
// This target needs runtime libraries for its source languages.
|
||||||
std::set<std::string> languages;
|
std::set<std::string> languages;
|
||||||
// Get languages used in our source files.
|
// Get languages used in our source files.
|
||||||
this->GetLanguages(languages, config);
|
this->GetLanguages(languages, config, head);
|
||||||
// Copy the set of langauges to the link implementation.
|
// Copy the set of langauges to the link implementation.
|
||||||
for(std::set<std::string>::iterator li = languages.begin();
|
for(std::set<std::string>::iterator li = languages.begin();
|
||||||
li != languages.end(); ++li)
|
li != languages.end(); ++li)
|
||||||
|
|
|
@ -136,9 +136,11 @@ public:
|
||||||
* Get the list of the source files used by this target
|
* Get the list of the source files used by this target
|
||||||
*/
|
*/
|
||||||
void GetSourceFiles(std::vector<std::string> &files,
|
void GetSourceFiles(std::vector<std::string> &files,
|
||||||
const std::string& config) const;
|
const std::string& config,
|
||||||
|
cmTarget const* head = 0) const;
|
||||||
void GetSourceFiles(std::vector<cmSourceFile*> &files,
|
void GetSourceFiles(std::vector<cmSourceFile*> &files,
|
||||||
const std::string& config) const;
|
const std::string& config,
|
||||||
|
cmTarget const* head = 0) const;
|
||||||
bool GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const;
|
bool GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -469,7 +471,8 @@ public:
|
||||||
// information to forward these property changes to the targets
|
// information to forward these property changes to the targets
|
||||||
// until we have per-target object file properties.
|
// until we have per-target object file properties.
|
||||||
void GetLanguages(std::set<std::string>& languages,
|
void GetLanguages(std::set<std::string>& languages,
|
||||||
const std::string& config) const;
|
std::string const& config,
|
||||||
|
cmTarget const* head = 0) const;
|
||||||
|
|
||||||
/** Return whether this target is an executable with symbol exports
|
/** Return whether this target is an executable with symbol exports
|
||||||
enabled. */
|
enabled. */
|
||||||
|
@ -743,7 +746,8 @@ private:
|
||||||
LinkImplementation& impl,
|
LinkImplementation& impl,
|
||||||
cmTarget const* head) const;
|
cmTarget const* head) const;
|
||||||
void ComputeLinkImplementationLanguages(const std::string& config,
|
void ComputeLinkImplementationLanguages(const std::string& config,
|
||||||
LinkImplementation& impl) const;
|
LinkImplementation& impl,
|
||||||
|
cmTarget const* head) const;
|
||||||
void ComputeLinkClosure(const std::string& config, LinkClosure& lc,
|
void ComputeLinkClosure(const std::string& config, LinkClosure& lc,
|
||||||
cmTarget const* head) const;
|
cmTarget const* head) const;
|
||||||
|
|
||||||
|
|
|
@ -282,6 +282,7 @@ if(BUILD_TESTING)
|
||||||
set(ConfigSources_BUILD_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
|
set(ConfigSources_BUILD_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
|
||||||
ADD_TEST_MACRO(ConfigSources ConfigSources)
|
ADD_TEST_MACRO(ConfigSources ConfigSources)
|
||||||
endif()
|
endif()
|
||||||
|
ADD_TEST_MACRO(SourcesProperty SourcesProperty)
|
||||||
set_tests_properties(EmptyLibrary PROPERTIES
|
set_tests_properties(EmptyLibrary PROPERTIES
|
||||||
PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target: test")
|
PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target: test")
|
||||||
ADD_TEST_MACRO(CrossCompile CrossCompile)
|
ADD_TEST_MACRO(CrossCompile CrossCompile)
|
||||||
|
|
|
@ -3,7 +3,15 @@ cmake_minimum_required(VERSION 3.0)
|
||||||
|
|
||||||
project(ConfigSources)
|
project(ConfigSources)
|
||||||
|
|
||||||
|
add_library(iface INTERFACE)
|
||||||
|
set_property(TARGET iface PROPERTY INTERFACE_SOURCES
|
||||||
|
iface_src.cpp
|
||||||
|
$<$<CONFIG:Debug>:iface_debug_src.cpp>
|
||||||
|
$<$<CONFIG:Release>:does_not_exist.cpp>
|
||||||
|
)
|
||||||
|
|
||||||
add_executable(ConfigSources
|
add_executable(ConfigSources
|
||||||
$<$<CONFIG:Debug>:main.cpp>
|
$<$<CONFIG:Debug>:main.cpp>
|
||||||
$<$<CONFIG:Release>:does_not_exist.cpp>
|
$<$<CONFIG:Release>:does_not_exist.cpp>
|
||||||
)
|
)
|
||||||
|
target_link_libraries(ConfigSources iface)
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
|
||||||
|
int iface_src();
|
||||||
|
|
||||||
|
int iface_debug();
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
#include "iface_debug.h"
|
||||||
|
|
||||||
|
int iface_debug()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
int iface_src()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
|
|
||||||
|
#include "iface_debug.h"
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
return 0;
|
return iface_src() + iface_debug();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
|
||||||
|
project(SourcesProperty)
|
||||||
|
|
||||||
|
add_library(iface INTERFACE)
|
||||||
|
set_property(TARGET iface PROPERTY INTERFACE_SOURCES iface.cpp)
|
||||||
|
|
||||||
|
add_executable(SourcesProperty main.cpp)
|
||||||
|
target_link_libraries(SourcesProperty iface)
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
int iface()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
int iface();
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
#include "iface.h"
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
return iface();
|
||||||
|
}
|
Loading…
Reference in New Issue