Merge topic 'target-sources-refactor'

5de63265 Genex: Only evaluate TARGET_OBJECTS to determine target sources.
aa0a3562 cmGeneratorTarget: Compute target objects on demand
042c1c83 cmTarget: Compute languages from object libraries on demand.
fdcefe3c cmGeneratorTarget: Compute consumed object libraries on demand.
c355d108 cmComputeTargetDepends: Track object library depends.
e5da9e51 cmTarget: Allow any generator expression in SOURCES property.
5702e106 cmTarget: Include TARGET_OBJECTS genex in target SOURCES property.
857d30b5 cmGlobalGenerator: Add interface to call ForceLinkerLanguages
28e1d2f8 cmStringCommand: Add GENEX_STRIP subcommand.
bf98cc25 Genex: Evaluate TARGET_OBJECTS as a normal expression.
8cd113ad cmTarget: Store strings instead of cmSourceFile* to represent SOURCES.
4959f341 cmSourceFileLocation: Collapse full path for directory comparisons.
fcc92878 cmSourceFileLocation: Remove unused Update method.
59e8740a cmTarget: Remove AddSourceFile method
26d494ba cmTarget: Use string API to add sources to cmTarget objects.
d38423ec cmTarget: Add a method to obtain list of filenames for sources.
...
This commit is contained in:
Brad King 2014-04-03 12:51:51 -04:00 committed by CMake Topic Stage
commit 93054aa84f
64 changed files with 778 additions and 271 deletions

View File

@ -35,8 +35,11 @@ If ``EXCLUDE_FROM_ALL`` is given the corresponding property will be set on
the created target. See documentation of the :prop_tgt:`EXCLUDE_FROM_ALL` the created target. See documentation of the :prop_tgt:`EXCLUDE_FROM_ALL`
target property for details. target property for details.
See the :manual:`cmake-buildsystem(7)` manual for more on defining Source arguments to ``add_executable`` may use "generator expressions" with
buildsystem properties. 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.
-------------------------------------------------------------------------- --------------------------------------------------------------------------

View File

@ -39,8 +39,10 @@ If ``EXCLUDE_FROM_ALL`` is given the corresponding property will be set on
the created target. See documentation of the :prop_tgt:`EXCLUDE_FROM_ALL` the created target. See documentation of the :prop_tgt:`EXCLUDE_FROM_ALL`
target property for details. target property for details.
See the :manual:`cmake-buildsystem(7)` manual for more on defining buildsystem Source arguments to ``add_library`` may use "generator expressions" with
properties. 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.
-------------------------------------------------------------------------- --------------------------------------------------------------------------

View File

@ -35,6 +35,7 @@ String operations.
string(FIND <string> <substring> <output variable> [REVERSE]) string(FIND <string> <substring> <output variable> [REVERSE])
string(TIMESTAMP <output variable> [<format string>] [UTC]) string(TIMESTAMP <output variable> [<format string>] [UTC])
string(MAKE_C_IDENTIFIER <input string> <output variable>) string(MAKE_C_IDENTIFIER <input string> <output variable>)
string(GENEX_STRIP <input string> <output variable>)
REGEX MATCH will match the regular expression once and store the match REGEX MATCH will match the regular expression once and store the match
in the output variable. in the output variable.
@ -154,3 +155,7 @@ If no explicit <format string> is given it will default to:
MAKE_C_IDENTIFIER will write a string which can be used as an MAKE_C_IDENTIFIER will write a string which can be used as an
identifier in C. identifier in C.
``GENEX_STRIP`` will strip any
:manual:`generator expressions <cmake-generator-expressions(7)>` from the
``input string`` and store the result in the ``output variable``.

View File

@ -188,3 +188,8 @@ property is non-empty::
Content of ``...`` converted to upper case. Content of ``...`` converted to upper case.
``$<MAKE_C_IDENTIFIER:...>`` ``$<MAKE_C_IDENTIFIER:...>``
Content of ``...`` converted to a C identifier. Content of ``...`` converted to a C identifier.
``$<TARGET_OBJECTS:objLib>``
List of objects resulting from build of ``objLib``. ``objLib`` must be an
object of type ``OBJECT_LIBRARY``. This expression may only be used in
the sources of :command:`add_library` and :command:`add_executable`
commands.

View File

@ -102,3 +102,4 @@ All Policies
/policy/CMP0048 /policy/CMP0048
/policy/CMP0049 /policy/CMP0049
/policy/CMP0050 /policy/CMP0050
/policy/CMP0051

24
Help/policy/CMP0051.rst Normal file
View File

@ -0,0 +1,24 @@
CMP0051
-------
List TARGET_OBJECTS in SOURCES target property.
CMake 3.0 and lower did not include the ``TARGET_OBJECTS``
:manual:`generator expression <cmake-generator-expressions(7)>` when
returning the :prop_tgt:`SOURCES` target property.
Configure-time CMake code is not able to handle generator expressions. If
using the :prop_tgt:`SOURCES` target property at configure time, it may be
necessary to first remove generator expressions using the
:command:`string(STRIP_GENEX)` command. Generate-time CMake code such as
:command:`file(GENERATE)` can handle the content without stripping.
The ``OLD`` behavior for this policy is to omit ``TARGET_OBJECTS``
expressions from the :prop_tgt:`SOURCES` target property. The ``NEW``
behavior for this policy is to include ``TARGET_OBJECTS`` expressions
in the output.
This policy was introduced in CMake version 3.1.
CMake version |release| warns when the policy is not set and uses
``OLD`` behavior. Use the :command:`cmake_policy` command to set it
to ``OLD`` or ``NEW`` explicitly.

View File

@ -0,0 +1,6 @@
string-GENEX_STRIP
------------------
* The :command:`string` command learned a new ``GENEX_STRIP`` subcommand
which removes
:manual:`generator expression <cmake-generator-expressions(7)>`.

View File

@ -0,0 +1,12 @@
target-SOURCES-genex
--------------------
* The :prop_tgt:`SOURCES` target property now contains
:manual:`generator expression <cmake-generator-expressions(7)>`
such as ``TARGET_OBJECTS`` when read at configure time, if
policy :policy:`CMP0051` is ``NEW``.
* The :prop_tgt:`SOURCES` target property now generally supports
:manual:`generator expression <cmake-generator-expressions(7)>`. The
generator expressions may be used in the :command:`add_library` and
:command:`add_executable` commands.

View File

@ -16,6 +16,7 @@
#include "cmLocalGenerator.h" #include "cmLocalGenerator.h"
#include "cmMakefile.h" #include "cmMakefile.h"
#include "cmSystemTools.h" #include "cmSystemTools.h"
#include "cmSourceFile.h"
#include "cmTarget.h" #include "cmTarget.h"
#include "cmake.h" #include "cmake.h"
@ -213,6 +214,34 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
{ {
std::set<std::string> emitted; std::set<std::string> emitted;
{ {
cmGeneratorTarget* gt = depender->GetMakefile()->GetLocalGenerator()
->GetGlobalGenerator()
->GetGeneratorTarget(depender);
std::vector<cmSourceFile const*> objectFiles;
gt->GetExternalObjects(objectFiles);
for(std::vector<cmSourceFile const*>::const_iterator
it = objectFiles.begin(); it != objectFiles.end(); ++it)
{
std::string objLib = (*it)->GetObjectLibrary();
if (!objLib.empty() && emitted.insert(objLib).second)
{
if(depender->GetType() != cmTarget::EXECUTABLE &&
depender->GetType() != cmTarget::STATIC_LIBRARY &&
depender->GetType() != cmTarget::SHARED_LIBRARY &&
depender->GetType() != cmTarget::MODULE_LIBRARY)
{
this->GlobalGenerator->GetCMakeInstance()
->IssueMessage(cmake::FATAL_ERROR,
"Only executables and non-OBJECT libraries may "
"reference target objects.",
depender->GetBacktrace());
return;
}
const_cast<cmTarget*>(depender)->AddUtility(objLib);
}
}
}
{
std::vector<std::string> tlibs; std::vector<std::string> tlibs;
depender->GetDirectLinkLibraries("", tlibs, depender); depender->GetDirectLinkLibraries("", tlibs, depender);
// A target should not depend on itself. // A target should not depend on itself.

View File

@ -168,7 +168,7 @@ void cmFLTKWrapUICommand::FinalPass()
for(size_t classNum = 0; classNum < lastHeadersClass; classNum++) for(size_t classNum = 0; classNum < lastHeadersClass; classNum++)
{ {
this->Makefile->GetTargets()[this->Target] this->Makefile->GetTargets()[this->Target]
.AddSourceFile(this->GeneratedSourcesClasses[classNum]); .AddSource(this->GeneratedSourcesClasses[classNum]->GetFullPath());
} }
} }
} }

View File

@ -90,6 +90,7 @@ const char *cmCompiledGeneratorExpression::Evaluate(
context.HadError = false; context.HadError = false;
context.HadContextSensitiveCondition = false; context.HadContextSensitiveCondition = false;
context.HeadTarget = headTarget; context.HeadTarget = headTarget;
context.EvaluateForBuildsystem = this->EvaluateForBuildsystem;
context.CurrentTarget = currentTarget ? currentTarget : headTarget; context.CurrentTarget = currentTarget ? currentTarget : headTarget;
context.Backtrace = this->Backtrace; context.Backtrace = this->Backtrace;
@ -124,7 +125,8 @@ cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
cmListFileBacktrace const& backtrace, cmListFileBacktrace const& backtrace,
const std::string& input) const std::string& input)
: Backtrace(backtrace), Input(input), : Backtrace(backtrace), Input(input),
HadContextSensitiveCondition(false) HadContextSensitiveCondition(false),
EvaluateForBuildsystem(false)
{ {
cmGeneratorExpressionLexer l; cmGeneratorExpressionLexer l;
std::vector<cmGeneratorExpressionToken> tokens = std::vector<cmGeneratorExpressionToken> tokens =

View File

@ -112,6 +112,11 @@ public:
return this->HadContextSensitiveCondition; return this->HadContextSensitiveCondition;
} }
void SetEvaluateForBuildsystem(bool eval)
{
this->EvaluateForBuildsystem = eval;
}
private: private:
cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace, cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace,
const std::string& input); const std::string& input);
@ -131,6 +136,7 @@ private:
mutable std::set<std::string> SeenTargetProperties; mutable std::set<std::string> SeenTargetProperties;
mutable std::string Output; mutable std::string Output;
mutable bool HadContextSensitiveCondition; mutable bool HadContextSensitiveCondition;
bool EvaluateForBuildsystem;
}; };
#endif #endif

View File

@ -15,6 +15,8 @@
#include "cmGeneratorExpressionParser.h" #include "cmGeneratorExpressionParser.h"
#include "cmGeneratorExpressionDAGChecker.h" #include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorExpression.h" #include "cmGeneratorExpression.h"
#include "cmLocalGenerator.h"
#include "cmSourceFile.h"
#include <cmsys/String.h> #include <cmsys/String.h>
@ -1239,6 +1241,77 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode
} targetNameNode; } targetNameNode;
//----------------------------------------------------------------------------
static const struct TargetObjectsNode : public cmGeneratorExpressionNode
{
TargetObjectsNode() {}
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *) const
{
if (!context->EvaluateForBuildsystem)
{
cmOStringStream e;
e << "The evaluation of the TARGET_OBJECTS generator expression "
"is only suitable for consumption by CMake. It is not suitable "
"for writing out elsewhere.";
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
std::string tgtName = parameters.front();
cmGeneratorTarget* gt =
context->Makefile->FindGeneratorTargetToUse(tgtName.c_str());
if (!gt)
{
cmOStringStream e;
e << "Objects of target \"" << tgtName
<< "\" referenced but no such target exists.";
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
if (gt->GetType() != cmTarget::OBJECT_LIBRARY)
{
cmOStringStream e;
e << "Objects of target \"" << tgtName
<< "\" referenced but is not an OBJECT library.";
reportError(context, content->GetOriginalExpression(), e.str());
return std::string();
}
std::vector<cmSourceFile const*> objectSources;
gt->GetObjectSources(objectSources);
std::map<cmSourceFile const*, std::string> mapping;
for(std::vector<cmSourceFile const*>::const_iterator it
= objectSources.begin(); it != objectSources.end(); ++it)
{
mapping[*it];
}
gt->LocalGenerator->ComputeObjectFilenames(mapping, gt);
std::string obj_dir = gt->ObjectDirectory;
std::string result;
const char* sep = "";
for(std::map<cmSourceFile const*, std::string>::const_iterator it
= mapping.begin(); it != mapping.end(); ++it)
{
assert(!it->second.empty());
result += sep;
std::string objFile = obj_dir + it->second;
cmSourceFile* sf = context->Makefile->GetOrCreateSource(objFile, true);
sf->SetObjectLibrary(tgtName);
sf->SetProperty("EXTERNAL_OBJECT", "1");
result += objFile;
sep = ";";
}
return result;
}
} targetObjectsNode;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static const char* targetPolicyWhitelist[] = { static const char* targetPolicyWhitelist[] = {
0 0
@ -1593,6 +1666,7 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
nodeMap["SEMICOLON"] = &semicolonNode; nodeMap["SEMICOLON"] = &semicolonNode;
nodeMap["TARGET_PROPERTY"] = &targetPropertyNode; nodeMap["TARGET_PROPERTY"] = &targetPropertyNode;
nodeMap["TARGET_NAME"] = &targetNameNode; nodeMap["TARGET_NAME"] = &targetNameNode;
nodeMap["TARGET_OBJECTS"] = &targetObjectsNode;
nodeMap["TARGET_POLICY"] = &targetPolicyNode; nodeMap["TARGET_POLICY"] = &targetPolicyNode;
nodeMap["BUILD_INTERFACE"] = &buildInterfaceNode; nodeMap["BUILD_INTERFACE"] = &buildInterfaceNode;
nodeMap["INSTALL_INTERFACE"] = &installInterfaceNode; nodeMap["INSTALL_INTERFACE"] = &installInterfaceNode;

View File

@ -34,6 +34,7 @@ struct cmGeneratorExpressionContext
bool Quiet; bool Quiet;
bool HadError; bool HadError;
bool HadContextSensitiveCondition; bool HadContextSensitiveCondition;
bool EvaluateForBuildsystem;
}; };
struct cmGeneratorExpressionDAGChecker; struct cmGeneratorExpressionDAGChecker;

View File

@ -311,20 +311,38 @@ cmGeneratorTarget
::GetObjectSources(std::vector<cmSourceFile const*> &data) const ::GetObjectSources(std::vector<cmSourceFile const*> &data) const
{ {
IMPLEMENT_VISIT(ObjectSources); IMPLEMENT_VISIT(ObjectSources);
if (!this->Objects.empty())
{
return;
}
for(std::vector<cmSourceFile const*>::const_iterator it = data.begin();
it != data.end(); ++it)
{
this->Objects[*it];
}
this->LocalGenerator->ComputeObjectFilenames(this->Objects, this);
}
void cmGeneratorTarget::ComputeObjectMapping()
{
if(!this->Objects.empty())
{
return;
}
std::vector<cmSourceFile const*> sourceFiles;
this->GetObjectSources(sourceFiles);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file) const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file)
{ {
this->ComputeObjectMapping();
return this->Objects[file]; return this->Objects[file];
} }
void cmGeneratorTarget::AddObject(cmSourceFile const* sf,
std::string const&name)
{
this->Objects[sf] = name;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf) void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
{ {
@ -334,6 +352,7 @@ void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
{ {
const_cast<cmGeneratorTarget*>(this)->ComputeObjectMapping();
std::set<cmSourceFile const*>::const_iterator it std::set<cmSourceFile const*>::const_iterator it
= this->ExplicitObjectName.find(file); = this->ExplicitObjectName.find(file);
return it != this->ExplicitObjectName.end(); return it != this->ExplicitObjectName.end();
@ -503,58 +522,6 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const
this->Target->GetSourceFiles(files); this->Target->GetSourceFiles(files);
} }
//----------------------------------------------------------------------------
void cmGeneratorTarget::LookupObjectLibraries()
{
std::vector<std::string> const& objLibs =
this->Target->GetObjectLibraries();
for(std::vector<std::string>::const_iterator oli = objLibs.begin();
oli != objLibs.end(); ++oli)
{
std::string const& objLibName = *oli;
if(cmTarget* objLib = this->Makefile->FindTargetToUse(objLibName))
{
if(objLib->GetType() == cmTarget::OBJECT_LIBRARY)
{
if(this->Target->GetType() != cmTarget::EXECUTABLE &&
this->Target->GetType() != cmTarget::STATIC_LIBRARY &&
this->Target->GetType() != cmTarget::SHARED_LIBRARY &&
this->Target->GetType() != cmTarget::MODULE_LIBRARY)
{
this->GlobalGenerator->GetCMakeInstance()
->IssueMessage(cmake::FATAL_ERROR,
"Only executables and non-OBJECT libraries may "
"reference target objects.",
this->Target->GetBacktrace());
return;
}
this->Target->AddUtility(objLib->GetName());
this->ObjectLibraries.push_back(objLib);
}
else
{
cmOStringStream e;
e << "Objects of target \"" << objLibName
<< "\" referenced but is not an OBJECT library.";
this->GlobalGenerator->GetCMakeInstance()
->IssueMessage(cmake::FATAL_ERROR, e.str(),
this->Target->GetBacktrace());
return;
}
}
else
{
cmOStringStream e;
e << "Objects of target \"" << objLibName
<< "\" referenced but no such target exists.";
this->GlobalGenerator->GetCMakeInstance()
->IssueMessage(cmake::FATAL_ERROR, e.str(),
this->Target->GetBacktrace());
return;
}
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string cmGeneratorTarget::GetModuleDefinitionFile() const std::string cmGeneratorTarget::GetModuleDefinitionFile() const
{ {
@ -567,9 +534,26 @@ std::string cmGeneratorTarget::GetModuleDefinitionFile() const
void void
cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs) const cmGeneratorTarget::UseObjectLibraries(std::vector<std::string>& objs) const
{ {
std::vector<cmSourceFile const*> objectFiles;
this->GetExternalObjects(objectFiles);
std::vector<cmTarget*> objectLibraries;
std::set<cmTarget*> emitted;
for(std::vector<cmSourceFile const*>::const_iterator
it = objectFiles.begin(); it != objectFiles.end(); ++it)
{
std::string objLib = (*it)->GetObjectLibrary();
if (cmTarget* tgt = this->Makefile->FindTargetToUse(objLib))
{
if (emitted.insert(tgt).second)
{
objectLibraries.push_back(tgt);
}
}
}
for(std::vector<cmTarget*>::const_iterator for(std::vector<cmTarget*>::const_iterator
ti = this->ObjectLibraries.begin(); ti = objectLibraries.begin();
ti != this->ObjectLibraries.end(); ++ti) ti != objectLibraries.end(); ++ti)
{ {
cmTarget* objLib = *ti; cmTarget* objLib = *ti;
cmGeneratorTarget* ogt = cmGeneratorTarget* ogt =
@ -600,12 +584,12 @@ private:
cmGlobalGenerator const* GlobalGenerator; cmGlobalGenerator const* GlobalGenerator;
typedef cmGeneratorTarget::SourceEntry SourceEntry; typedef cmGeneratorTarget::SourceEntry SourceEntry;
SourceEntry* CurrentEntry; SourceEntry* CurrentEntry;
std::queue<cmSourceFile*> SourceQueue; std::queue<std::string> SourceQueue;
std::set<cmSourceFile*> SourcesQueued; std::set<std::string> SourcesQueued;
typedef std::map<std::string, cmSourceFile*> NameMapType; typedef std::map<std::string, cmSourceFile*> NameMapType;
NameMapType NameMap; NameMapType NameMap;
void QueueSource(cmSourceFile* sf); void QueueSource(std::string const& name);
void FollowName(std::string const& name); void FollowName(std::string const& name);
void FollowNames(std::vector<std::string> const& names); void FollowNames(std::vector<std::string> const& names);
bool IsUtility(std::string const& dep); bool IsUtility(std::string const& dep);
@ -628,11 +612,11 @@ cmTargetTraceDependencies
this->CurrentEntry = 0; this->CurrentEntry = 0;
// Queue all the source files already specified for the target. // Queue all the source files already specified for the target.
std::vector<cmSourceFile*> sources;
if (this->Target->GetType() != cmTarget::INTERFACE_LIBRARY) if (this->Target->GetType() != cmTarget::INTERFACE_LIBRARY)
{ {
std::vector<std::string> sources;
this->Target->GetSourceFiles(sources); this->Target->GetSourceFiles(sources);
for(std::vector<cmSourceFile*>::const_iterator si = sources.begin(); for(std::vector<std::string>::const_iterator si = sources.begin();
si != sources.end(); ++si) si != sources.end(); ++si)
{ {
this->QueueSource(*si); this->QueueSource(*si);
@ -652,7 +636,8 @@ void cmTargetTraceDependencies::Trace()
while(!this->SourceQueue.empty()) while(!this->SourceQueue.empty())
{ {
// Get the next source from the queue. // Get the next source from the queue.
cmSourceFile* sf = this->SourceQueue.front(); std::string src = this->SourceQueue.front();
cmSourceFile* sf = this->Makefile->GetSource(src);
this->SourceQueue.pop(); this->SourceQueue.pop();
this->CurrentEntry = &this->GeneratorTarget->SourceEntries[sf]; this->CurrentEntry = &this->GeneratorTarget->SourceEntries[sf];
@ -680,14 +665,14 @@ void cmTargetTraceDependencies::Trace()
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTargetTraceDependencies::QueueSource(cmSourceFile* sf) void cmTargetTraceDependencies::QueueSource(std::string const& name)
{ {
if(this->SourcesQueued.insert(sf).second) if(this->SourcesQueued.insert(name).second)
{ {
this->SourceQueue.push(sf); this->SourceQueue.push(name);
// Make sure this file is in the target. // Make sure this file is in the target.
this->Target->AddSourceFile(sf); this->Target->AddSource(name);
} }
} }
@ -709,8 +694,7 @@ void cmTargetTraceDependencies::FollowName(std::string const& name)
{ {
this->CurrentEntry->Depends.push_back(sf); this->CurrentEntry->Depends.push_back(sf);
} }
this->QueueSource(sf->GetFullPath());
this->QueueSource(sf);
} }
} }

View File

@ -35,7 +35,6 @@ public:
void GetObjectSources(std::vector<cmSourceFile const*> &) const; void GetObjectSources(std::vector<cmSourceFile const*> &) const;
const std::string& GetObjectName(cmSourceFile const* file); const std::string& GetObjectName(cmSourceFile const* file);
void AddObject(cmSourceFile const* sf, std::string const&name);
bool HasExplicitObjectName(cmSourceFile const* file) const; bool HasExplicitObjectName(cmSourceFile const* file) const;
void AddExplicitObjectName(cmSourceFile const* sf); void AddExplicitObjectName(cmSourceFile const* sf);
@ -47,6 +46,8 @@ public:
void GetCustomCommands(std::vector<cmSourceFile const*>&) const; void GetCustomCommands(std::vector<cmSourceFile const*>&) const;
void GetExpectedResxHeaders(std::set<std::string>&) const; void GetExpectedResxHeaders(std::set<std::string>&) const;
void ComputeObjectMapping();
cmTarget* Target; cmTarget* Target;
cmMakefile* Makefile; cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator; cmLocalGenerator* LocalGenerator;
@ -84,8 +85,6 @@ public:
*/ */
void TraceDependencies(); void TraceDependencies();
void LookupObjectLibraries();
/** Get sources that must be built before the given source. */ /** Get sources that must be built before the given source. */
std::vector<cmSourceFile*> const* std::vector<cmSourceFile*> const*
GetSourceDepends(cmSourceFile const* sf) const; GetSourceDepends(cmSourceFile const* sf) const;
@ -125,9 +124,8 @@ private:
typedef std::map<cmSourceFile const*, SourceEntry> SourceEntriesType; typedef std::map<cmSourceFile const*, SourceEntry> SourceEntriesType;
SourceEntriesType SourceEntries; SourceEntriesType SourceEntries;
std::map<cmSourceFile const*, std::string> Objects; mutable std::map<cmSourceFile const*, std::string> Objects;
std::set<cmSourceFile const*> ExplicitObjectName; std::set<cmSourceFile const*> ExplicitObjectName;
std::vector<cmTarget*> ObjectLibraries;
mutable std::map<std::string, std::vector<std::string> > SystemIncludesCache; mutable std::map<std::string, std::vector<std::string> > SystemIncludesCache;
void ConstructSourceFileFlags() const; void ConstructSourceFileFlags() const;

View File

@ -216,6 +216,11 @@ bool cmGlobalGenerator::GenerateImportFile(const std::string &file)
return false; return false;
} }
void cmGlobalGenerator::ForceLinkerLanguages()
{
}
bool bool
cmGlobalGenerator::IsExportedTargetsFile(const std::string &filename) const cmGlobalGenerator::IsExportedTargetsFile(const std::string &filename) const
{ {
@ -1196,6 +1201,8 @@ void cmGlobalGenerator::Generate()
// Create per-target generator information. // Create per-target generator information.
this->CreateGeneratorTargets(); this->CreateGeneratorTargets();
this->ForceLinkerLanguages();
#ifdef CMAKE_BUILD_WITH_CMAKE #ifdef CMAKE_BUILD_WITH_CMAKE
for (AutogensType::iterator it = autogens.begin(); it != autogens.end(); for (AutogensType::iterator it = autogens.begin(); it != autogens.end();
++it) ++it)
@ -1217,8 +1224,6 @@ void cmGlobalGenerator::Generate()
this->LocalGenerators[i]->GenerateTargetManifest(); this->LocalGenerators[i]->GenerateTargetManifest();
} }
this->ComputeGeneratorTargetObjects();
this->ProcessEvaluationFiles(); this->ProcessEvaluationFiles();
// Compute the inter-target dependencies. // Compute the inter-target dependencies.
@ -1409,6 +1414,7 @@ void cmGlobalGenerator::CreateGeneratorTargets(cmMakefile *mf)
{ {
cmTarget* t = &ti->second; cmTarget* t = &ti->second;
cmGeneratorTarget* gt = new cmGeneratorTarget(t); cmGeneratorTarget* gt = new cmGeneratorTarget(t);
this->ComputeTargetObjectDirectory(gt);
this->GeneratorTargets[t] = gt; this->GeneratorTargets[t] = gt;
generatorTargets[t] = gt; generatorTargets[t] = gt;
} }
@ -1434,29 +1440,6 @@ void cmGlobalGenerator::CreateGeneratorTargets()
} }
} }
//----------------------------------------------------------------------------
void cmGlobalGenerator::ComputeGeneratorTargetObjects()
{
// Construct per-target generator information.
for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
{
cmMakefile *mf = this->LocalGenerators[i]->GetMakefile();
cmGeneratorTargetsType targets = mf->GetGeneratorTargets();
for(cmGeneratorTargetsType::iterator ti = targets.begin();
ti != targets.end(); ++ti)
{
if (ti->second->Target->IsImported()
|| ti->second->Target->GetType() == cmTarget::INTERFACE_LIBRARY)
{
continue;
}
cmGeneratorTarget* gt = ti->second;
this->ComputeTargetObjectDirectory(gt);
gt->LookupObjectLibraries();
this->ComputeTargetObjects(gt);
}
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmGlobalGenerator::ClearGeneratorMembers() void cmGlobalGenerator::ClearGeneratorMembers()
@ -1517,29 +1500,6 @@ cmGlobalGenerator::GetGeneratorTarget(cmTarget const* t) const
return ti->second; return ti->second;
} }
//----------------------------------------------------------------------------
void cmGlobalGenerator::ComputeTargetObjects(cmGeneratorTarget* gt) const
{
std::vector<cmSourceFile const*> objectSources;
gt->GetObjectSources(objectSources);
std::map<cmSourceFile const*, std::string> mapping;
for(std::vector<cmSourceFile const*>::const_iterator it
= objectSources.begin(); it != objectSources.end(); ++it)
{
mapping[*it];
}
gt->LocalGenerator->ComputeObjectFilenames(mapping, gt);
for(std::map<cmSourceFile const*, std::string>::const_iterator it
= mapping.begin(); it != mapping.end(); ++it)
{
assert(!it->second.empty());
gt->AddObject(it->first, it->second);
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmGlobalGenerator::ComputeTargetObjectDirectory(cmGeneratorTarget*) const void cmGlobalGenerator::ComputeTargetObjectDirectory(cmGeneratorTarget*) const
{ {

View File

@ -423,6 +423,8 @@ private:
void WriteSummary(cmTarget* target); void WriteSummary(cmTarget* target);
void FinalizeTargetCompileInfo(); void FinalizeTargetCompileInfo();
virtual void ForceLinkerLanguages();
virtual void PrintCompilerAdvice(std::ostream& os, std::string const& lang, virtual void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
const char* envVar) const; const char* envVar) const;
void CheckCompilerIdCompatibility(cmMakefile* mf, void CheckCompilerIdCompatibility(cmMakefile* mf,
@ -442,8 +444,6 @@ private:
friend class cmake; friend class cmake;
void CreateGeneratorTargets(cmMakefile* mf); void CreateGeneratorTargets(cmMakefile* mf);
void CreateGeneratorTargets(); void CreateGeneratorTargets();
void ComputeGeneratorTargetObjects();
void ComputeTargetObjects(cmGeneratorTarget* gt) const;
void ClearGeneratorMembers(); void ClearGeneratorMembers();

View File

@ -16,6 +16,7 @@
#include "cmVisualStudioWCEPlatformParser.h" #include "cmVisualStudioWCEPlatformParser.h"
#include "cmake.h" #include "cmake.h"
#include "cmGeneratedFileStream.h" #include "cmGeneratedFileStream.h"
#include "cmSourceFile.h"
static const char vs8generatorName[] = "Visual Studio 8 2005"; static const char vs8generatorName[] = "Visual Studio 8 2005";
@ -323,7 +324,7 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
no_main_dependency, commandLines, "Checking Build System", no_main_dependency, commandLines, "Checking Build System",
no_working_directory, true)) no_working_directory, true))
{ {
tgt->AddSourceFile(file); tgt->AddSource(file->GetFullPath());
} }
else else
{ {

View File

@ -343,7 +343,6 @@ void cmGlobalXCodeGenerator::Generate()
// add ALL_BUILD, INSTALL, etc // add ALL_BUILD, INSTALL, etc
this->AddExtraTargets(root, it->second); this->AddExtraTargets(root, it->second);
} }
this->ForceLinkerLanguages();
this->cmGlobalGenerator::Generate(); this->cmGlobalGenerator::Generate();
if(cmSystemTools::GetErrorOccuredFlag()) if(cmSystemTools::GetErrorOccuredFlag())
{ {
@ -412,7 +411,7 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
std::string listfile = mf->GetStartDirectory(); std::string listfile = mf->GetStartDirectory();
listfile += "/"; listfile += "/";
listfile += "CMakeLists.txt"; listfile += "CMakeLists.txt";
allbuild->AddSource(listfile.c_str()); allbuild->AddSourceCMP0049(listfile.c_str());
// Add XCODE depend helper // Add XCODE depend helper
std::string dir = mf->GetCurrentOutputDirectory(); std::string dir = mf->GetCurrentOutputDirectory();
@ -495,7 +494,7 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
listfile = lg->GetMakefile()->GetStartDirectory(); listfile = lg->GetMakefile()->GetStartDirectory();
listfile += "/"; listfile += "/";
listfile += "CMakeLists.txt"; listfile += "CMakeLists.txt";
target.AddSource(listfile.c_str()); target.AddSourceCMP0049(listfile.c_str());
} }
} }
} }
@ -988,6 +987,8 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
cmtarget.GetSourceFiles(classes); cmtarget.GetSourceFiles(classes);
std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare()); std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
gtgt->ComputeObjectMapping();
std::vector<cmXCodeObject*> externalObjFiles; std::vector<cmXCodeObject*> externalObjFiles;
std::vector<cmXCodeObject*> headerFiles; std::vector<cmXCodeObject*> headerFiles;
std::vector<cmXCodeObject*> resourceFiles; std::vector<cmXCodeObject*> resourceFiles;
@ -1008,8 +1009,11 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
if(filetype && if(filetype &&
filetype->GetString() == "compiled.mach-o.objfile") filetype->GetString() == "compiled.mach-o.objfile")
{ {
if ((*i)->GetObjectLibrary().empty())
{
externalObjFiles.push_back(xsf); externalObjFiles.push_back(xsf);
} }
}
else if(this->IsHeaderFile(*i) || else if(this->IsHeaderFile(*i) ||
(tsFlags.Type == cmGeneratorTarget::SourceFileTypePrivateHeader) || (tsFlags.Type == cmGeneratorTarget::SourceFileTypePrivateHeader) ||
(tsFlags.Type == cmGeneratorTarget::SourceFileTypePublicHeader)) (tsFlags.Type == cmGeneratorTarget::SourceFileTypePublicHeader))
@ -1260,7 +1264,7 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget)
if(cmSourceFile* sf = mf->GetOrCreateSource(fname.c_str())) if(cmSourceFile* sf = mf->GetOrCreateSource(fname.c_str()))
{ {
sf->SetProperty("LANGUAGE", llang.c_str()); sf->SetProperty("LANGUAGE", llang.c_str());
cmtarget.AddSourceFile(sf); cmtarget.AddSource(fname);
} }
} }
@ -2934,8 +2938,8 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root,
if(cmtarget.GetPropertyAsBool("MACOSX_BUNDLE")) if(cmtarget.GetPropertyAsBool("MACOSX_BUNDLE"))
{ {
std::string plist = this->ComputeInfoPListLocation(cmtarget); std::string plist = this->ComputeInfoPListLocation(cmtarget);
cmSourceFile* sf = mf->GetOrCreateSource(plist.c_str(), true); mf->GetOrCreateSource(plist, true);
cmtarget.AddSourceFile(sf); cmtarget.AddSource(plist);
} }
std::vector<cmSourceFile*> classes; std::vector<cmSourceFile*> classes;

View File

@ -751,8 +751,8 @@ void cmLocalGenerator::AddBuildTargetRule(const std::string& llang,
comment.c_str(), comment.c_str(),
this->Makefile->GetStartOutputDirectory() this->Makefile->GetStartOutputDirectory()
); );
target.Target->AddSourceFile this->Makefile->GetSource(targetFullPath);
(this->Makefile->GetSource(targetFullPath)); target.Target->AddSource(targetFullPath);
} }

View File

@ -253,9 +253,9 @@ void cmLocalVisualStudio6Generator::AddDSPBuildRule(cmTarget& tgt)
makefileIn.c_str(), commandLines, makefileIn.c_str(), commandLines,
comment.c_str(), comment.c_str(),
no_working_directory, true); no_working_directory, true);
if(cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) if(this->Makefile->GetSource(makefileIn.c_str()))
{ {
tgt.AddSourceFile(file); tgt.AddSource(makefileIn);
} }
else else
{ {
@ -324,6 +324,11 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
for(std::vector<cmSourceFile*>::const_iterator i = classes.begin(); for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
i != classes.end(); i++) i != classes.end(); i++)
{ {
if (!(*i)->GetObjectLibrary().empty())
{
continue;
}
// Add the file to the list of sources. // Add the file to the list of sources.
std::string source = (*i)->GetFullPath(); std::string source = (*i)->GetFullPath();
cmSourceGroup* sourceGroup = cmSourceGroup* sourceGroup =
@ -398,6 +403,11 @@ void cmLocalVisualStudio6Generator
for(std::vector<const cmSourceFile *>::const_iterator sf = for(std::vector<const cmSourceFile *>::const_iterator sf =
sourceFiles.begin(); sf != sourceFiles.end(); ++sf) sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
{ {
if (!(*sf)->GetObjectLibrary().empty())
{
continue;
}
std::string source = (*sf)->GetFullPath(); std::string source = (*sf)->GetFullPath();
const cmCustomCommand *command = const cmCustomCommand *command =
(*sf)->GetCustomCommand(); (*sf)->GetCustomCommand();
@ -591,7 +601,7 @@ cmLocalVisualStudio6Generator
origCommand.GetCommandLines(), comment, origCommand.GetCommandLines(), comment,
origCommand.GetWorkingDirectory().c_str())) origCommand.GetWorkingDirectory().c_str()))
{ {
target.AddSourceFile(outsf); target.AddSource(outsf->GetFullPath());
} }
// Replace the dependencies with the output of this rule so that the // Replace the dependencies with the output of this rule so that the

View File

@ -117,7 +117,7 @@ void cmLocalVisualStudio7Generator::AddCMakeListsRules()
{ {
if(l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET) if(l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET)
{ {
l->second.AddSourceFile(sf); l->second.AddSource(sf->GetFullPath());
} }
} }
} }
@ -153,7 +153,7 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets()
force.c_str(), no_depends, no_main_dependency, force.c_str(), no_depends, no_main_dependency,
force_commands, " ", 0, true)) force_commands, " ", 0, true))
{ {
tgt.AddSourceFile(file); tgt.AddSource(file->GetFullPath());
} }
} }
} }
@ -1401,6 +1401,10 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
for(std::vector<cmSourceFile*>::const_iterator i = classes.begin(); for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
i != classes.end(); i++) i != classes.end(); i++)
{ {
if (!(*i)->GetObjectLibrary().empty())
{
continue;
}
// Add the file to the list of sources. // Add the file to the list of sources.
std::string source = (*i)->GetFullPath(); std::string source = (*i)->GetFullPath();
if(cmSystemTools::UpperCase((*i)->GetExtension()) == "DEF") if(cmSystemTools::UpperCase((*i)->GetExtension()) == "DEF")

View File

@ -1182,7 +1182,7 @@ cmMakefile::AddCustomCommandOldStyle(const std::string& target,
{ {
if (this->Targets.find(target) != this->Targets.end()) if (this->Targets.find(target) != this->Targets.end())
{ {
this->Targets[target].AddSourceFile(sf); this->Targets[target].AddSource(sf->GetFullPath());
} }
else else
{ {
@ -1266,7 +1266,7 @@ cmMakefile::AddUtilityCommand(const std::string& utilityName,
commandLines, comment, commandLines, comment,
workingDirectory, no_replace, workingDirectory, no_replace,
escapeOldStyle); escapeOldStyle);
cmSourceFile* sf = target->AddSource(force); cmSourceFile* sf = target->AddSourceCMP0049(force);
// The output is not actually created so mark it symbolic. // The output is not actually created so mark it symbolic.
if(sf) if(sf)

View File

@ -202,9 +202,6 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
// Generate this object file's rule file. // Generate this object file's rule file.
this->WriteObjectRuleFiles(**si); this->WriteObjectRuleFiles(**si);
} }
// Add object library contents as external objects.
this->GeneratorTarget->UseObjectLibraries(this->ExternalObjects);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -525,17 +525,6 @@ cmNinjaTargetGenerator
this->ModuleDefinitionFile = this->ConvertToNinjaPath(def.c_str()); this->ModuleDefinitionFile = this->ConvertToNinjaPath(def.c_str());
} }
{
// Add object library contents as external objects.
std::vector<std::string> objs;
this->GeneratorTarget->UseObjectLibraries(objs);
for(std::vector<std::string>::iterator oi = objs.begin();
oi != objs.end(); ++oi)
{
this->Objects.push_back(ConvertToNinjaPath(oi->c_str()));
}
}
this->GetBuildFileStream() << "\n"; this->GetBuildFileStream() << "\n";
} }

View File

@ -343,6 +343,11 @@ cmPolicies::cmPolicies()
CMP0050, "CMP0050", CMP0050, "CMP0050",
"Disallow add_custom_command SOURCE signatures.", "Disallow add_custom_command SOURCE signatures.",
3,0,0, cmPolicies::WARN); 3,0,0, cmPolicies::WARN);
this->DefinePolicy(
CMP0051, "CMP0051",
"List TARGET_OBJECTS in SOURCES target property.",
3,1,0, cmPolicies::WARN);
} }
cmPolicies::~cmPolicies() cmPolicies::~cmPolicies()

View File

@ -104,6 +104,7 @@ public:
CMP0048, ///< project() command manages VERSION variables CMP0048, ///< project() command manages VERSION variables
CMP0049, ///< Do not expand variables in target source entries CMP0049, ///< Do not expand variables in target source entries
CMP0050, ///< Disallow add_custom_command SOURCE signatures CMP0050, ///< Disallow add_custom_command SOURCE signatures
CMP0051, ///< List TARGET_OBJECTS in SOURCES target property
/** \brief Always the last entry. /** \brief Always the last entry.
* *

View File

@ -187,13 +187,11 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target)
mocCppFile += "/"; mocCppFile += "/";
mocCppFile += automocTargetName; mocCppFile += automocTargetName;
mocCppFile += ".cpp"; mocCppFile += ".cpp";
cmSourceFile* mocCppSource = makefile->GetOrCreateSource( makefile->GetOrCreateSource(mocCppFile, true);
mocCppFile,
true);
makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
mocCppFile.c_str(), false); mocCppFile.c_str(), false);
target->AddSourceFile(mocCppSource); target->AddSource(mocCppFile);
} }
// create a custom target for running generators at buildtime: // create a custom target for running generators at buildtime:
std::string autogenTargetName = getAutogenTargetName(target); std::string autogenTargetName = getAutogenTargetName(target);
@ -479,7 +477,7 @@ void cmQtAutoGenerators::SetupSourceFiles(cmTarget const* target)
const char *skipMocSep = ""; const char *skipMocSep = "";
const char *skipUicSep = ""; const char *skipUicSep = "";
std::vector<cmSourceFile*> newRccFiles; std::vector<std::string> newRccFiles;
for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin(); for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
fileIt != srcFiles.end(); fileIt != srcFiles.end();
@ -512,9 +510,8 @@ void cmQtAutoGenerators::SetupSourceFiles(cmTarget const* target)
rcc_output_file += "/qrc_" + basename + ".cpp"; rcc_output_file += "/qrc_" + basename + ".cpp";
makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
rcc_output_file.c_str(), false); rcc_output_file.c_str(), false);
cmSourceFile* rccCppSource makefile->GetOrCreateSource(rcc_output_file, true);
= makefile->GetOrCreateSource(rcc_output_file, true); newRccFiles.push_back(rcc_output_file);
newRccFiles.push_back(rccCppSource);
} }
} }
@ -546,11 +543,11 @@ void cmQtAutoGenerators::SetupSourceFiles(cmTarget const* target)
} }
} }
for(std::vector<cmSourceFile*>::const_iterator fileIt = newRccFiles.begin(); for(std::vector<std::string>::const_iterator fileIt = newRccFiles.begin();
fileIt != newRccFiles.end(); fileIt != newRccFiles.end();
++fileIt) ++fileIt)
{ {
const_cast<cmTarget*>(target)->AddSourceFile(*fileIt); const_cast<cmTarget*>(target)->AddSource(*fileIt);
} }
} }

View File

@ -38,6 +38,18 @@ std::string const& cmSourceFile::GetExtension() const
return this->Extension; return this->Extension;
} }
//----------------------------------------------------------------------------
void cmSourceFile::SetObjectLibrary(std::string const& objlib)
{
this->ObjectLibrary = objlib;
}
//----------------------------------------------------------------------------
std::string cmSourceFile::GetObjectLibrary() const
{
return this->ObjectLibrary;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
std::string cmSourceFile::GetLanguage() std::string cmSourceFile::GetLanguage()
{ {

View File

@ -97,6 +97,9 @@ public:
*/ */
bool Matches(cmSourceFileLocation const&); bool Matches(cmSourceFileLocation const&);
void SetObjectLibrary(std::string const& objlib);
std::string GetObjectLibrary() const;
private: private:
cmSourceFileLocation Location; cmSourceFileLocation Location;
cmPropertyMap Properties; cmPropertyMap Properties;
@ -105,6 +108,7 @@ private:
std::string Language; std::string Language;
std::string FullPath; std::string FullPath;
bool FindFullPathFailed; bool FindFullPathFailed;
std::string ObjectLibrary;
bool FindFullPath(std::string* error); bool FindFullPath(std::string* error);
bool TryFullPath(const std::string& path, const std::string& ext); bool TryFullPath(const std::string& path, const std::string& ext);

View File

@ -16,6 +16,42 @@
#include "cmGlobalGenerator.h" #include "cmGlobalGenerator.h"
#include "cmSystemTools.h" #include "cmSystemTools.h"
#include "assert.h"
//----------------------------------------------------------------------------
cmSourceFileLocation::cmSourceFileLocation()
: Makefile(0), AmbiguousDirectory(true), AmbiguousExtension(true)
{
}
//----------------------------------------------------------------------------
cmSourceFileLocation::cmSourceFileLocation(const cmSourceFileLocation& loc)
: Makefile(loc.Makefile)
{
this->AmbiguousDirectory = loc.AmbiguousDirectory;
this->AmbiguousExtension = loc.AmbiguousExtension;
this->Directory = loc.Directory;
this->Name = loc.Name;
}
//----------------------------------------------------------------------------
cmSourceFileLocation&
cmSourceFileLocation::operator=(const cmSourceFileLocation& loc)
{
if(this == &loc)
{
return *this;
}
this->Makefile = loc.Makefile;
this->AmbiguousDirectory = loc.AmbiguousDirectory;
this->AmbiguousExtension = loc.AmbiguousExtension;
this->Directory = loc.Directory;
this->Name = loc.Name;
this->UpdateExtension(this->Name);
return *this;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmSourceFileLocation cmSourceFileLocation
::cmSourceFileLocation(cmMakefile const* mf, const std::string& name) ::cmSourceFileLocation(cmMakefile const* mf, const std::string& name)
@ -24,23 +60,15 @@ cmSourceFileLocation
this->AmbiguousDirectory = !cmSystemTools::FileIsFullPath(name.c_str()); this->AmbiguousDirectory = !cmSystemTools::FileIsFullPath(name.c_str());
this->AmbiguousExtension = true; this->AmbiguousExtension = true;
this->Directory = cmSystemTools::GetFilenamePath(name); this->Directory = cmSystemTools::GetFilenamePath(name);
if (cmSystemTools::FileIsFullPath(this->Directory.c_str()))
{
this->Directory
= cmSystemTools::CollapseFullPath(this->Directory.c_str());
}
this->Name = cmSystemTools::GetFilenameName(name); this->Name = cmSystemTools::GetFilenameName(name);
this->UpdateExtension(name); this->UpdateExtension(name);
} }
//----------------------------------------------------------------------------
void cmSourceFileLocation::Update(const std::string& name)
{
if(this->AmbiguousDirectory)
{
this->UpdateDirectory(name);
}
if(this->AmbiguousExtension)
{
this->UpdateExtension(name);
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmSourceFileLocation::Update(cmSourceFileLocation const& loc) void cmSourceFileLocation::Update(cmSourceFileLocation const& loc)
{ {
@ -59,6 +87,7 @@ void cmSourceFileLocation::Update(cmSourceFileLocation const& loc)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmSourceFileLocation::DirectoryUseSource() void cmSourceFileLocation::DirectoryUseSource()
{ {
assert(this->Makefile);
if(this->AmbiguousDirectory) if(this->AmbiguousDirectory)
{ {
this->Directory = this->Directory =
@ -71,6 +100,7 @@ void cmSourceFileLocation::DirectoryUseSource()
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmSourceFileLocation::DirectoryUseBinary() void cmSourceFileLocation::DirectoryUseBinary()
{ {
assert(this->Makefile);
if(this->AmbiguousDirectory) if(this->AmbiguousDirectory)
{ {
this->Directory = this->Directory =
@ -83,6 +113,7 @@ void cmSourceFileLocation::DirectoryUseBinary()
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmSourceFileLocation::UpdateExtension(const std::string& name) void cmSourceFileLocation::UpdateExtension(const std::string& name)
{ {
assert(this->Makefile);
// Check the extension. // Check the extension.
std::string ext = cmSystemTools::GetFilenameLastExtension(name); std::string ext = cmSystemTools::GetFilenameLastExtension(name);
if(!ext.empty()) { ext = ext.substr(1); } if(!ext.empty()) { ext = ext.substr(1); }
@ -136,22 +167,12 @@ void cmSourceFileLocation::UpdateExtension(const std::string& name)
} }
} }
//----------------------------------------------------------------------------
void cmSourceFileLocation::UpdateDirectory(const std::string& name)
{
// If a full path was given we know the directory.
if(cmSystemTools::FileIsFullPath(name.c_str()))
{
this->Directory = cmSystemTools::GetFilenamePath(name);
this->AmbiguousDirectory = false;
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
cmSourceFileLocation cmSourceFileLocation
::MatchesAmbiguousExtension(cmSourceFileLocation const& loc) const ::MatchesAmbiguousExtension(cmSourceFileLocation const& loc) const
{ {
assert(this->Makefile);
// This location's extension is not ambiguous but loc's extension // This location's extension is not ambiguous but loc's extension
// is. See if the names match as-is. // is. See if the names match as-is.
if(this->Name == loc.Name) if(this->Name == loc.Name)
@ -188,6 +209,7 @@ cmSourceFileLocation
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc) bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc)
{ {
assert(this->Makefile);
if(this->AmbiguousExtension && loc.AmbiguousExtension) if(this->AmbiguousExtension && loc.AmbiguousExtension)
{ {
// Both extensions are ambiguous. Since only the old fixed set of // Both extensions are ambiguous. Since only the old fixed set of

View File

@ -34,6 +34,9 @@ public:
* instance with an initial name. * instance with an initial name.
*/ */
cmSourceFileLocation(cmMakefile const* mf, const std::string& name); cmSourceFileLocation(cmMakefile const* mf, const std::string& name);
cmSourceFileLocation();
cmSourceFileLocation(const cmSourceFileLocation& loc);
cmSourceFileLocation& operator=(const cmSourceFileLocation& loc);
/** /**
* Return whether the givne source file location could refers to the * Return whether the givne source file location could refers to the
@ -93,9 +96,7 @@ private:
// Update the location with additional knowledge. // Update the location with additional knowledge.
void Update(cmSourceFileLocation const& loc); void Update(cmSourceFileLocation const& loc);
void Update(const std::string& name);
void UpdateExtension(const std::string& name); void UpdateExtension(const std::string& name);
void UpdateDirectory(const std::string& name);
}; };
#endif #endif

View File

@ -101,6 +101,10 @@ bool cmStringCommand
{ {
return this->HandleMakeCIdentifierCommand(args); return this->HandleMakeCIdentifierCommand(args);
} }
else if(subCommand == "GENEX_STRIP")
{
return this->HandleGenexStripCommand(args);
}
std::string e = "does not recognize sub-command "+subCommand; std::string e = "does not recognize sub-command "+subCommand;
this->SetError(e); this->SetError(e);
@ -809,6 +813,27 @@ bool cmStringCommand
return true; return true;
} }
//----------------------------------------------------------------------------
bool cmStringCommand
::HandleGenexStripCommand(std::vector<std::string> const& args)
{
if(args.size() != 3)
{
this->SetError("sub-command GENEX_STRIP requires two arguments.");
return false;
}
const std::string& input = args[1];
std::string result = cmGeneratorExpression::Preprocess(input,
cmGeneratorExpression::StripAllGeneratorExpressions);
const std::string& variableName = args[2];
this->Makefile->AddDefinition(variableName, result.c_str());
return true;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmStringCommand::HandleStripCommand( bool cmStringCommand::HandleStripCommand(
std::vector<std::string> const& args) std::vector<std::string> const& args)

View File

@ -75,6 +75,7 @@ protected:
bool HandleFindCommand(std::vector<std::string> const& args); bool HandleFindCommand(std::vector<std::string> const& args);
bool HandleTimestampCommand(std::vector<std::string> const& args); bool HandleTimestampCommand(std::vector<std::string> const& args);
bool HandleMakeCIdentifierCommand(std::vector<std::string> const& args); bool HandleMakeCIdentifierCommand(std::vector<std::string> const& args);
bool HandleGenexStripCommand(std::vector<std::string> const& args);
class RegexReplacement class RegexReplacement
{ {

View File

@ -150,6 +150,7 @@ public:
std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries; std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
std::vector<TargetPropertyEntry*> CompileOptionsEntries; std::vector<TargetPropertyEntry*> CompileOptionsEntries;
std::vector<TargetPropertyEntry*> CompileDefinitionsEntries; std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
std::vector<TargetPropertyEntry*> SourceEntries;
std::vector<cmValueWithOrigin> LinkImplementationPropertyEntries; std::vector<cmValueWithOrigin> LinkImplementationPropertyEntries;
mutable std::map<std::string, std::vector<TargetPropertyEntry*> > mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
@ -542,15 +543,28 @@ bool cmTarget::IsBundleOnApple() const
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const void cmTarget::GetSourceFiles(std::vector<std::string> &files) const
{ {
assert(this->GetType() != INTERFACE_LIBRARY); assert(this->GetType() != INTERFACE_LIBRARY);
for(std::vector<cmSourceFile*>::const_iterator for(std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
si = this->SourceFiles.begin(); si = this->Internal->SourceEntries.begin();
si != this->SourceFiles.end(); ++si) si != this->Internal->SourceEntries.end(); ++si)
{ {
std::vector<std::string> srcs;
cmSystemTools::ExpandListArgument((*si)->ge->Evaluate(this->Makefile,
"",
false,
this),
srcs);
for(std::vector<std::string>::const_iterator i = srcs.begin();
i != srcs.end(); ++i)
{
std::string src = *i;
cmSourceFile* sf = this->Makefile->GetOrCreateSource(src);
std::string e; std::string e;
if((*si)->GetFullPath(&e).empty()) src = sf->GetFullPath(&e);
if(src.empty())
{ {
if(!e.empty()) if(!e.empty())
{ {
@ -560,17 +574,27 @@ void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const
} }
return; return;
} }
files.push_back(src);
}
} }
files = this->SourceFiles;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::AddSourceFile(cmSourceFile* sf) void cmTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const
{ {
if (std::find(this->SourceFiles.begin(), this->SourceFiles.end(), sf) std::vector<std::string> srcs;
== this->SourceFiles.end()) this->GetSourceFiles(srcs);
std::set<cmSourceFile*> emitted;
for(std::vector<std::string>::const_iterator i = srcs.begin();
i != srcs.end(); ++i)
{ {
this->SourceFiles.push_back(sf); cmSourceFile* sf = this->Makefile->GetOrCreateSource(*i);
if (emitted.insert(sf).second)
{
files.push_back(sf);
}
} }
} }
@ -583,17 +607,17 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs)
const char* src = i->c_str(); const char* src = i->c_str();
if(src[0] == '$' && src[1] == '<') if(src[0] == '$' && src[1] == '<')
{ {
this->ProcessSourceExpression(*i); this->AddSource(src);
} }
else else
{ {
this->AddSource(src); this->AddSourceCMP0049(src);
} }
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmSourceFile* cmTarget::AddSource(const std::string& s) cmSourceFile* cmTarget::AddSourceCMP0049(const std::string& s)
{ {
std::string src = s; std::string src = s;
@ -632,28 +656,91 @@ cmSourceFile* cmTarget::AddSource(const std::string& s)
} }
} }
} }
return this->AddSource(src);
cmSourceFile* sf = this->Makefile->GetOrCreateSource(src);
this->AddSourceFile(sf);
return sf;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::ProcessSourceExpression(std::string const& expr) struct CreateLocation
{ {
if(cmHasLiteralPrefix(expr.c_str(), "$<TARGET_OBJECTS:") && cmMakefile const* Makefile;
expr[expr.size()-1] == '>')
CreateLocation(cmMakefile const* mf)
: Makefile(mf)
{ {
std::string objLibName = expr.substr(17, expr.size()-18);
this->ObjectLibraries.push_back(objLibName);
} }
else
cmSourceFileLocation operator()(const std::string& filename)
{ {
cmOStringStream e; return cmSourceFileLocation(this->Makefile, filename);
e << "Unrecognized generator expression:\n"
<< " " << expr;
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
} }
};
//----------------------------------------------------------------------------
struct LocationMatcher
{
const cmSourceFileLocation& Needle;
LocationMatcher(const cmSourceFileLocation& needle)
: Needle(needle)
{
}
bool operator()(cmSourceFileLocation &loc)
{
return loc.Matches(this->Needle);
}
};
//----------------------------------------------------------------------------
struct TargetPropertyEntryFinder
{
private:
const cmSourceFileLocation& Needle;
public:
TargetPropertyEntryFinder(const cmSourceFileLocation& needle)
: Needle(needle)
{
}
bool operator()(cmTargetInternals::TargetPropertyEntry* entry)
{
std::vector<std::string> files;
cmSystemTools::ExpandListArgument(entry->ge->GetInput(), files);
std::vector<cmSourceFileLocation> locations(files.size());
std::transform(files.begin(), files.end(), locations.begin(),
CreateLocation(this->Needle.GetMakefile()));
return std::find_if(locations.begin(), locations.end(),
LocationMatcher(this->Needle)) != locations.end();
}
};
//----------------------------------------------------------------------------
cmSourceFile* cmTarget::AddSource(const std::string& src)
{
cmSourceFileLocation sfl(this->Makefile, src);
if (std::find_if(this->Internal->SourceEntries.begin(),
this->Internal->SourceEntries.end(),
TargetPropertyEntryFinder(sfl))
== this->Internal->SourceEntries.end())
{
cmListFileBacktrace lfbt;
this->Makefile->GetBacktrace(lfbt);
cmGeneratorExpression ge(lfbt);
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(src);
cge->SetEvaluateForBuildsystem(true);
this->Internal->SourceEntries.push_back(
new cmTargetInternals::TargetPropertyEntry(cge));
}
if (cmGeneratorExpression::Find(src) != std::string::npos)
{
return 0;
}
return this->Makefile->GetOrCreateSource(src);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -2766,16 +2853,77 @@ const char *cmTarget::GetProperty(const std::string& prop,
{ {
cmOStringStream ss; cmOStringStream ss;
const char* sep = ""; const char* sep = "";
for(std::vector<cmSourceFile*>::const_iterator typedef cmTargetInternals::TargetPropertyEntry
i = this->SourceFiles.begin(); TargetPropertyEntry;
i != this->SourceFiles.end(); ++i) for(std::vector<TargetPropertyEntry*>::const_iterator
i = this->Internal->SourceEntries.begin();
i != this->Internal->SourceEntries.end(); ++i)
{
std::string entry = (*i)->ge->GetInput();
std::vector<std::string> files;
cmSystemTools::ExpandListArgument(entry, files);
for (std::vector<std::string>::const_iterator
li = files.begin(); li != files.end(); ++li)
{
if(cmHasLiteralPrefix(*li, "$<TARGET_OBJECTS:") &&
(*li)[li->size() - 1] == '>')
{
std::string objLibName = li->substr(17, li->size()-18);
if (cmGeneratorExpression::Find(objLibName) != std::string::npos)
{ {
// Separate from the previous list entries.
ss << sep; ss << sep;
sep = ";"; sep = ";";
ss << *li;
continue;
}
bool addContent = false;
bool noMessage = true;
cmOStringStream e;
cmake::MessageType messageType = cmake::AUTHOR_WARNING;
switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0051))
{
case cmPolicies::WARN:
e << (this->Makefile->GetPolicies()
->GetPolicyWarning(cmPolicies::CMP0051)) << "\n";
noMessage = false;
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::NEW:
addContent = true;
}
if (!noMessage)
{
e << "Target \"" << this->Name << "\" contains $<TARGET_OBJECTS> "
"generator expression in its sources list. This content was not "
"previously part of the SOURCES property when that property was "
"read at configure time. Code reading that property needs to be "
"adapted to ignore the generator expression using the "
"string(GENEX_STRIP) command.";
this->Makefile->IssueMessage(messageType, e.str());
}
if (addContent)
{
ss << sep;
sep = ";";
ss << *li;
}
}
else if (cmGeneratorExpression::Find(*li) == std::string::npos)
{
ss << sep;
sep = ";";
ss << *li;
}
else
{
cmSourceFile *sf = this->Makefile->GetOrCreateSource(*li);
// Construct what is known about this source file location. // Construct what is known about this source file location.
cmSourceFileLocation const& location = (*i)->GetLocation(); cmSourceFileLocation const& location = sf->GetLocation();
std::string sname = location.GetDirectory(); std::string sname = location.GetDirectory();
if(!sname.empty()) if(!sname.empty())
{ {
@ -2783,9 +2931,13 @@ const char *cmTarget::GetProperty(const std::string& prop,
} }
sname += location.GetName(); sname += location.GetName();
ss << sep;
sep = ";";
// Append this list entry. // Append this list entry.
ss << sname; ss << sname;
} }
}
}
this->Properties.SetProperty("SOURCES", ss.str().c_str(), this->Properties.SetProperty("SOURCES", ss.str().c_str(),
cmProperty::TARGET); cmProperty::TARGET);
} }
@ -4844,8 +4996,10 @@ bool cmTarget::IsLinkInterfaceDependentNumberMaxProperty(const std::string &p,
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::GetLanguages(std::set<std::string>& languages) const void cmTarget::GetLanguages(std::set<std::string>& languages) const
{ {
std::vector<cmSourceFile*> sourceFiles;
this->GetSourceFiles(sourceFiles);
for(std::vector<cmSourceFile*>::const_iterator for(std::vector<cmSourceFile*>::const_iterator
i = this->SourceFiles.begin(); i != this->SourceFiles.end(); ++i) i = sourceFiles.begin(); i != sourceFiles.end(); ++i)
{ {
const std::string& lang = (*i)->GetLanguage(); const std::string& lang = (*i)->GetLanguage();
if(!lang.empty()) if(!lang.empty())
@ -4853,6 +5007,53 @@ void cmTarget::GetLanguages(std::set<std::string>& languages) const
languages.insert(lang); languages.insert(lang);
} }
} }
std::vector<cmTarget*> objectLibraries;
std::vector<cmSourceFile const*> externalObjects;
if (this->Makefile->GetGeneratorTargets().empty())
{
// At configure-time, this method can be called as part of getting the
// LOCATION property or to export() a file to be include()d. However
// there is no cmGeneratorTarget at configure-time, so search the SOURCES
// for TARGET_OBJECTS instead for backwards compatibility with OLD
// behavior of CMP0024 and CMP0026 only.
std::vector<std::string> srcs;
cmSystemTools::ExpandListArgument(this->GetProperty("SOURCES"), srcs);
for(std::vector<std::string>::const_iterator it = srcs.begin();
it != srcs.end(); ++it)
{
if (cmHasLiteralPrefix(*it, "$<TARGET_OBJECTS:")
&& cmHasLiteralSuffix(*it, ">"))
{
std::string objLibName = it->substr(17, it->size()-18);
if (cmTarget* tgt = this->Makefile->FindTargetToUse(objLibName))
{
objectLibraries.push_back(tgt);
}
}
}
}
else
{
cmGeneratorTarget* gt = this->Makefile->GetLocalGenerator()
->GetGlobalGenerator()
->GetGeneratorTarget(this);
gt->GetExternalObjects(externalObjects);
for(std::vector<cmSourceFile const*>::const_iterator
i = externalObjects.begin(); i != externalObjects.end(); ++i)
{
std::string objLib = (*i)->GetObjectLibrary();
if (cmTarget* tgt = this->Makefile->FindTargetToUse(objLib))
{
objectLibraries.push_back(tgt);
}
}
}
for(std::vector<cmTarget*>::const_iterator
i = objectLibraries.begin(); i != objectLibraries.end(); ++i)
{
(*i)->GetLanguages(languages);
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -5917,19 +6118,6 @@ cmTarget::ComputeLinkImplementationLanguages(LinkImplementation& impl) const
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); this->GetLanguages(languages);
// Get languages used in object library sources.
for(std::vector<std::string>::const_iterator
i = this->ObjectLibraries.begin();
i != this->ObjectLibraries.end(); ++i)
{
if(cmTarget* objLib = this->Makefile->FindTargetToUse(*i))
{
if(objLib->GetType() == cmTarget::OBJECT_LIBRARY)
{
objLib->GetLanguages(languages);
}
}
}
// 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)
@ -6395,6 +6583,7 @@ cmTargetInternalPointer::~cmTargetInternalPointer()
deleteAndClear(this->Pointer->IncludeDirectoriesEntries); deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
deleteAndClear(this->Pointer->CompileOptionsEntries); deleteAndClear(this->Pointer->CompileOptionsEntries);
deleteAndClear(this->Pointer->CompileDefinitionsEntries); deleteAndClear(this->Pointer->CompileDefinitionsEntries);
deleteAndClear(this->Pointer->SourceEntries);
delete this->Pointer; delete this->Pointer;
} }

View File

@ -135,17 +135,14 @@ 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) const;
void GetSourceFiles(std::vector<cmSourceFile*> &files) const; void GetSourceFiles(std::vector<cmSourceFile*> &files) const;
void AddSourceFile(cmSourceFile* sf);
std::vector<std::string> const& GetObjectLibraries() const
{
return this->ObjectLibraries;
}
/** /**
* Add sources to the target. * Add sources to the target.
*/ */
void AddSources(std::vector<std::string> const& srcs); void AddSources(std::vector<std::string> const& srcs);
cmSourceFile* AddSourceCMP0049(const std::string& src);
cmSourceFile* AddSource(const std::string& src); cmSourceFile* AddSource(const std::string& src);
enum LinkLibraryType {GENERAL, DEBUG, OPTIMIZED}; enum LinkLibraryType {GENERAL, DEBUG, OPTIMIZED};
@ -685,8 +682,6 @@ private:
std::vector<cmCustomCommand> PreLinkCommands; std::vector<cmCustomCommand> PreLinkCommands;
std::vector<cmCustomCommand> PostBuildCommands; std::vector<cmCustomCommand> PostBuildCommands;
TargetType TargetTypeValue; TargetType TargetTypeValue;
std::vector<cmSourceFile*> SourceFiles;
std::vector<std::string> ObjectLibraries;
LinkLibraryVectorType LinkLibraries; LinkLibraryVectorType LinkLibraries;
LinkLibraryVectorType PrevLinkedLibraries; LinkLibraryVectorType PrevLinkedLibraries;
bool LinkLibrariesAnalyzed; bool LinkLibrariesAnalyzed;

View File

@ -1054,6 +1054,19 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
std::vector<cmSourceFile const*> externalObjects; std::vector<cmSourceFile const*> externalObjects;
this->GeneratorTarget->GetExternalObjects(externalObjects); this->GeneratorTarget->GetExternalObjects(externalObjects);
for(std::vector<cmSourceFile const*>::iterator
si = externalObjects.begin();
si != externalObjects.end(); )
{
if (!(*si)->GetObjectLibrary().empty())
{
si = externalObjects.erase(si);
}
else
{
++si;
}
}
if(this->LocalGenerator->GetVersion() > cmLocalVisualStudioGenerator::VS10) if(this->LocalGenerator->GetVersion() > cmLocalVisualStudioGenerator::VS10)
{ {
// For VS >= 11 we use LinkObjects to avoid linking custom command // For VS >= 11 we use LinkObjects to avoid linking custom command

View File

@ -166,7 +166,7 @@ add_library(imported4 SHARED IMPORTED)
set_property(TARGET imported4 APPEND PROPERTY set_property(TARGET imported4 APPEND PROPERTY
INCLUDE_DIRECTORIES $<TARGET_PROPERTY:imported3,INTERFACE_INCLUDE_DIRECTORIES>) INCLUDE_DIRECTORIES $<TARGET_PROPERTY:imported3,INTERFACE_INCLUDE_DIRECTORIES>)
add_executable(someexe empty.cpp) add_executable(someexe $<1:empty.cpp> $<0:does_not_exist>)
add_executable(Alias::SomeExe ALIAS someexe) add_executable(Alias::SomeExe ALIAS someexe)
add_library(Alias::SomeLib ALIAS empty1) add_library(Alias::SomeLib ALIAS empty1)

View File

@ -143,3 +143,5 @@ set_property(CACHE SOME_ENTRY PROPERTY VALUE "${expect_VALUE}")
set_property(CACHE SOME_ENTRY PROPERTY ADVANCED "${expect_ADVANCED}") set_property(CACHE SOME_ENTRY PROPERTY ADVANCED "${expect_ADVANCED}")
set_property(CACHE SOME_ENTRY PROPERTY STRINGS "${expect_STRINGS}") set_property(CACHE SOME_ENTRY PROPERTY STRINGS "${expect_STRINGS}")
check_cache_props() check_cache_props()
add_subdirectory(SubDir2)

View File

@ -0,0 +1,5 @@
set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/../subdirtest.cxx"
PROPERTIES COMPILE_DEFINITIONS SUBDIR_TEST)
add_executable(subdirtest "${CMAKE_CURRENT_SOURCE_DIR}/../subdirtest.cxx")

View File

@ -0,0 +1,9 @@
#ifndef SUBDIR_TEST
#error Expected SUBDIR_TEST
#endif
int main(int, char**)
{
return 0;
}

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1 @@
^Sources: "empty.cpp;\$<TARGET_OBJECTS:objects>"$

View File

@ -0,0 +1,10 @@
cmake_policy(SET CMP0051 NEW)
add_library(objects OBJECT empty.cpp)
add_library(empty empty.cpp $<TARGET_OBJECTS:objects>)
get_target_property(srcs empty SOURCES)
message("Sources: \"${srcs}\"")

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1 @@
^Sources: "empty.cpp"$

View File

@ -0,0 +1,10 @@
cmake_policy(SET CMP0051 OLD)
add_library(objects OBJECT empty.cpp)
add_library(empty empty.cpp $<TARGET_OBJECTS:objects>)
get_target_property(srcs empty SOURCES)
message("Sources: \"${srcs}\"")

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1,15 @@
CMake Warning \(dev\) at CMP0051-WARN.cmake:6 \(get_target_property\):
Policy CMP0051 is not set: List TARGET_OBJECTS in SOURCES target property.
Run "cmake --help-policy CMP0051" for policy details. Use the cmake_policy
command to set the policy and suppress this warning.
Target "empty" contains \$<TARGET_OBJECTS> generator expression in its
sources list. This content was not previously part of the SOURCES property
when that property was read at configure time. Code reading that property
needs to be adapted to ignore the generator expression using the
string\(GENEX_STRIP\) command.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
Sources: "empty.cpp"$

View File

@ -0,0 +1,8 @@
add_library(objects OBJECT empty.cpp)
add_library(empty empty.cpp $<TARGET_OBJECTS:objects>)
get_target_property(srcs empty SOURCES)
message("Sources: \"${srcs}\"")

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.0)
project(${RunCMake_TEST} CXX)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,5 @@
include(RunCMake)
run_cmake(CMP0051-OLD)
run_cmake(CMP0051-NEW)
run_cmake(CMP0051-WARN)

View File

@ -0,0 +1,7 @@
#ifdef _WIN32
__declspec(dllexport)
#endif
int empty()
{
return 0;
}

View File

@ -34,6 +34,7 @@ add_RunCMake_test(CMP0045)
add_RunCMake_test(CMP0046) add_RunCMake_test(CMP0046)
add_RunCMake_test(CMP0049) add_RunCMake_test(CMP0049)
add_RunCMake_test(CMP0050) add_RunCMake_test(CMP0050)
add_RunCMake_test(CMP0051)
add_RunCMake_test(CTest) add_RunCMake_test(CTest)
if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles") if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles")
add_RunCMake_test(CompilerChange) add_RunCMake_test(CompilerChange)
@ -49,6 +50,7 @@ add_RunCMake_test(GeneratorToolset)
add_RunCMake_test(TargetPropertyGeneratorExpressions) add_RunCMake_test(TargetPropertyGeneratorExpressions)
add_RunCMake_test(Languages) add_RunCMake_test(Languages)
add_RunCMake_test(ObjectLibrary) add_RunCMake_test(ObjectLibrary)
add_RunCMake_test(TargetObjects)
add_RunCMake_test(find_dependency) add_RunCMake_test(find_dependency)
if(NOT WIN32) if(NOT WIN32)
add_RunCMake_test(PositionIndependentCode) add_RunCMake_test(PositionIndependentCode)

View File

@ -1,6 +1,8 @@
CMake Error at BadSourceExpression1.cmake:1 \(add_library\): CMake Error at BadSourceExpression1.cmake:1 \(add_library\):
Unrecognized generator expression: Error evaluating generator expression:
\$<BAD_EXPRESSION> \$<BAD_EXPRESSION>
Expression did not evaluate to a known generator expression
Call Stack \(most recent call first\): Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\) CMakeLists.txt:3 \(include\)

View File

@ -1,4 +1,8 @@
CMake Error at BadSourceExpression2.cmake:1 \(add_library\): CMake Error at BadSourceExpression2.cmake:1 \(add_library\):
Error evaluating generator expression:
\$<TARGET_OBJECTS:DoesNotExist>
Objects of target "DoesNotExist" referenced but no such target exists. Objects of target "DoesNotExist" referenced but no such target exists.
Call Stack \(most recent call first\): Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\) CMakeLists.txt:3 \(include\)

View File

@ -1,4 +1,8 @@
CMake Error at BadSourceExpression3.cmake:2 \(add_library\): CMake Error at BadSourceExpression3.cmake:2 \(add_library\):
Error evaluating generator expression:
\$<TARGET_OBJECTS:NotObjLib>
Objects of target "NotObjLib" referenced but is not an OBJECT library. Objects of target "NotObjLib" referenced but is not an OBJECT library.
Call Stack \(most recent call first\): Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\) CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,17 @@
CMake Error at BadContext.cmake:2 \(file\):
Error evaluating generator expression:
\$<TARGET_OBJECTS:NoTarget>
The evaluation of the TARGET_OBJECTS generator expression is only suitable
for consumption by CMake. It is not suitable for writing out elsewhere.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
+
CMake Error:
Error evaluating generator expression:
\$<TARGET_OBJECTS:NoTarget>
The evaluation of the TARGET_OBJECTS generator expression is only suitable
for consumption by CMake. It is not suitable for writing out elsewhere.

View File

@ -0,0 +1,4 @@
file(GENERATE OUTPUT test_output CONTENT $<TARGET_OBJECTS:NoTarget>)
install(FILES $<TARGET_OBJECTS:NoTarget> DESTINATION objects)

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 2.8.4)
project(${RunCMake_TEST})
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,3 @@
include(RunCMake)
run_cmake(BadContext)

View File

@ -286,3 +286,9 @@ string(MAKE_C_IDENTIFIER "1one-two$" MCI_1)
if(NOT MCI_1 STREQUAL _1one_two_) if(NOT MCI_1 STREQUAL _1one_two_)
message(SEND_ERROR "MAKE_C_IDENTIFIER did not create expected result.") message(SEND_ERROR "MAKE_C_IDENTIFIER did not create expected result.")
endif() endif()
string(GENEX_STRIP "one;$<1:two;three>;four;$<TARGET_OBJECTS:some_target>" strip_result)
if (NOT strip_result STREQUAL "one;four")
message(SEND_ERROR "GENEX_STRIP did not create expected result: ${strip_result}")
endif()