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`
target property for details.
See the :manual:`cmake-buildsystem(7)` manual for more on defining
buildsystem properties.
Source arguments to ``add_executable`` 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.
--------------------------------------------------------------------------

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`
target property for details.
See the :manual:`cmake-buildsystem(7)` manual for more on defining buildsystem
properties.
Source arguments to ``add_library`` 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.
--------------------------------------------------------------------------

View File

@ -35,6 +35,7 @@ String operations.
string(FIND <string> <substring> <output variable> [REVERSE])
string(TIMESTAMP <output variable> [<format string>] [UTC])
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
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
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.
``$<MAKE_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/CMP0049
/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 "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmSourceFile.h"
#include "cmTarget.h"
#include "cmake.h"
@ -213,6 +214,34 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
{
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;
depender->GetDirectLinkLibraries("", tlibs, depender);
// A target should not depend on itself.

View File

@ -168,7 +168,7 @@ void cmFLTKWrapUICommand::FinalPass()
for(size_t classNum = 0; classNum < lastHeadersClass; classNum++)
{
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.HadContextSensitiveCondition = false;
context.HeadTarget = headTarget;
context.EvaluateForBuildsystem = this->EvaluateForBuildsystem;
context.CurrentTarget = currentTarget ? currentTarget : headTarget;
context.Backtrace = this->Backtrace;
@ -124,7 +125,8 @@ cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
cmListFileBacktrace const& backtrace,
const std::string& input)
: Backtrace(backtrace), Input(input),
HadContextSensitiveCondition(false)
HadContextSensitiveCondition(false),
EvaluateForBuildsystem(false)
{
cmGeneratorExpressionLexer l;
std::vector<cmGeneratorExpressionToken> tokens =

View File

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

View File

@ -15,6 +15,8 @@
#include "cmGeneratorExpressionParser.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorExpression.h"
#include "cmLocalGenerator.h"
#include "cmSourceFile.h"
#include <cmsys/String.h>
@ -1239,6 +1241,77 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode
} 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[] = {
0
@ -1593,6 +1666,7 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
nodeMap["SEMICOLON"] = &semicolonNode;
nodeMap["TARGET_PROPERTY"] = &targetPropertyNode;
nodeMap["TARGET_NAME"] = &targetNameNode;
nodeMap["TARGET_OBJECTS"] = &targetObjectsNode;
nodeMap["TARGET_POLICY"] = &targetPolicyNode;
nodeMap["BUILD_INTERFACE"] = &buildInterfaceNode;
nodeMap["INSTALL_INTERFACE"] = &installInterfaceNode;

View File

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

View File

@ -311,20 +311,38 @@ cmGeneratorTarget
::GetObjectSources(std::vector<cmSourceFile const*> &data) const
{
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)
{
this->ComputeObjectMapping();
return this->Objects[file];
}
void cmGeneratorTarget::AddObject(cmSourceFile const* sf,
std::string const&name)
{
this->Objects[sf] = name;
}
//----------------------------------------------------------------------------
void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
{
@ -334,6 +352,7 @@ void cmGeneratorTarget::AddExplicitObjectName(cmSourceFile const* sf)
//----------------------------------------------------------------------------
bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const
{
const_cast<cmGeneratorTarget*>(this)->ComputeObjectMapping();
std::set<cmSourceFile const*>::const_iterator it
= this->ExplicitObjectName.find(file);
return it != this->ExplicitObjectName.end();
@ -503,58 +522,6 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const
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
{
@ -567,9 +534,26 @@ std::string cmGeneratorTarget::GetModuleDefinitionFile() const
void
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
ti = this->ObjectLibraries.begin();
ti != this->ObjectLibraries.end(); ++ti)
ti = objectLibraries.begin();
ti != objectLibraries.end(); ++ti)
{
cmTarget* objLib = *ti;
cmGeneratorTarget* ogt =
@ -600,12 +584,12 @@ private:
cmGlobalGenerator const* GlobalGenerator;
typedef cmGeneratorTarget::SourceEntry SourceEntry;
SourceEntry* CurrentEntry;
std::queue<cmSourceFile*> SourceQueue;
std::set<cmSourceFile*> SourcesQueued;
std::queue<std::string> SourceQueue;
std::set<std::string> SourcesQueued;
typedef std::map<std::string, cmSourceFile*> NameMapType;
NameMapType NameMap;
void QueueSource(cmSourceFile* sf);
void QueueSource(std::string const& name);
void FollowName(std::string const& name);
void FollowNames(std::vector<std::string> const& names);
bool IsUtility(std::string const& dep);
@ -628,11 +612,11 @@ cmTargetTraceDependencies
this->CurrentEntry = 0;
// Queue all the source files already specified for the target.
std::vector<cmSourceFile*> sources;
if (this->Target->GetType() != cmTarget::INTERFACE_LIBRARY)
{
std::vector<std::string> 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)
{
this->QueueSource(*si);
@ -652,7 +636,8 @@ void cmTargetTraceDependencies::Trace()
while(!this->SourceQueue.empty())
{
// 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->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.
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->QueueSource(sf);
this->QueueSource(sf->GetFullPath());
}
}

View File

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

View File

@ -216,6 +216,11 @@ bool cmGlobalGenerator::GenerateImportFile(const std::string &file)
return false;
}
void cmGlobalGenerator::ForceLinkerLanguages()
{
}
bool
cmGlobalGenerator::IsExportedTargetsFile(const std::string &filename) const
{
@ -1196,6 +1201,8 @@ void cmGlobalGenerator::Generate()
// Create per-target generator information.
this->CreateGeneratorTargets();
this->ForceLinkerLanguages();
#ifdef CMAKE_BUILD_WITH_CMAKE
for (AutogensType::iterator it = autogens.begin(); it != autogens.end();
++it)
@ -1217,8 +1224,6 @@ void cmGlobalGenerator::Generate()
this->LocalGenerators[i]->GenerateTargetManifest();
}
this->ComputeGeneratorTargetObjects();
this->ProcessEvaluationFiles();
// Compute the inter-target dependencies.
@ -1409,6 +1414,7 @@ void cmGlobalGenerator::CreateGeneratorTargets(cmMakefile *mf)
{
cmTarget* t = &ti->second;
cmGeneratorTarget* gt = new cmGeneratorTarget(t);
this->ComputeTargetObjectDirectory(gt);
this->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()
@ -1517,29 +1500,6 @@ cmGlobalGenerator::GetGeneratorTarget(cmTarget const* t) const
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
{

View File

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

View File

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

View File

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

View File

@ -751,8 +751,8 @@ void cmLocalGenerator::AddBuildTargetRule(const std::string& llang,
comment.c_str(),
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,
comment.c_str(),
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
{
@ -324,6 +324,11 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
for(std::vector<cmSourceFile*>::const_iterator i = classes.begin();
i != classes.end(); i++)
{
if (!(*i)->GetObjectLibrary().empty())
{
continue;
}
// Add the file to the list of sources.
std::string source = (*i)->GetFullPath();
cmSourceGroup* sourceGroup =
@ -398,6 +403,11 @@ void cmLocalVisualStudio6Generator
for(std::vector<const cmSourceFile *>::const_iterator sf =
sourceFiles.begin(); sf != sourceFiles.end(); ++sf)
{
if (!(*sf)->GetObjectLibrary().empty())
{
continue;
}
std::string source = (*sf)->GetFullPath();
const cmCustomCommand *command =
(*sf)->GetCustomCommand();
@ -591,7 +601,7 @@ cmLocalVisualStudio6Generator
origCommand.GetCommandLines(), comment,
origCommand.GetWorkingDirectory().c_str()))
{
target.AddSourceFile(outsf);
target.AddSource(outsf->GetFullPath());
}
// 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)
{
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_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();
i != classes.end(); i++)
{
if (!(*i)->GetObjectLibrary().empty())
{
continue;
}
// Add the file to the list of sources.
std::string source = (*i)->GetFullPath();
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())
{
this->Targets[target].AddSourceFile(sf);
this->Targets[target].AddSource(sf->GetFullPath());
}
else
{
@ -1266,7 +1266,7 @@ cmMakefile::AddUtilityCommand(const std::string& utilityName,
commandLines, comment,
workingDirectory, no_replace,
escapeOldStyle);
cmSourceFile* sf = target->AddSource(force);
cmSourceFile* sf = target->AddSourceCMP0049(force);
// The output is not actually created so mark it symbolic.
if(sf)

View File

@ -202,9 +202,6 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules()
// Generate this object file's rule file.
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());
}
{
// 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";
}

View File

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

View File

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

View File

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

View File

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

View File

@ -16,6 +16,42 @@
#include "cmGlobalGenerator.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(cmMakefile const* mf, const std::string& name)
@ -24,23 +60,15 @@ cmSourceFileLocation
this->AmbiguousDirectory = !cmSystemTools::FileIsFullPath(name.c_str());
this->AmbiguousExtension = true;
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->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)
{
@ -59,6 +87,7 @@ void cmSourceFileLocation::Update(cmSourceFileLocation const& loc)
//----------------------------------------------------------------------------
void cmSourceFileLocation::DirectoryUseSource()
{
assert(this->Makefile);
if(this->AmbiguousDirectory)
{
this->Directory =
@ -71,6 +100,7 @@ void cmSourceFileLocation::DirectoryUseSource()
//----------------------------------------------------------------------------
void cmSourceFileLocation::DirectoryUseBinary()
{
assert(this->Makefile);
if(this->AmbiguousDirectory)
{
this->Directory =
@ -83,6 +113,7 @@ void cmSourceFileLocation::DirectoryUseBinary()
//----------------------------------------------------------------------------
void cmSourceFileLocation::UpdateExtension(const std::string& name)
{
assert(this->Makefile);
// Check the extension.
std::string ext = cmSystemTools::GetFilenameLastExtension(name);
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
cmSourceFileLocation
::MatchesAmbiguousExtension(cmSourceFileLocation const& loc) const
{
assert(this->Makefile);
// This location's extension is not ambiguous but loc's extension
// is. See if the names match as-is.
if(this->Name == loc.Name)
@ -188,6 +209,7 @@ cmSourceFileLocation
//----------------------------------------------------------------------------
bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc)
{
assert(this->Makefile);
if(this->AmbiguousExtension && loc.AmbiguousExtension)
{
// Both extensions are ambiguous. Since only the old fixed set of

View File

@ -34,6 +34,9 @@ public:
* instance with an initial 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
@ -93,9 +96,7 @@ private:
// Update the location with additional knowledge.
void Update(cmSourceFileLocation const& loc);
void Update(const std::string& name);
void UpdateExtension(const std::string& name);
void UpdateDirectory(const std::string& name);
};
#endif

View File

@ -101,6 +101,10 @@ bool cmStringCommand
{
return this->HandleMakeCIdentifierCommand(args);
}
else if(subCommand == "GENEX_STRIP")
{
return this->HandleGenexStripCommand(args);
}
std::string e = "does not recognize sub-command "+subCommand;
this->SetError(e);
@ -809,6 +813,27 @@ bool cmStringCommand
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(
std::vector<std::string> const& args)

View File

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

View File

@ -150,6 +150,7 @@ public:
std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
std::vector<TargetPropertyEntry*> CompileOptionsEntries;
std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
std::vector<TargetPropertyEntry*> SourceEntries;
std::vector<cmValueWithOrigin> LinkImplementationPropertyEntries;
mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
@ -542,35 +543,58 @@ 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);
for(std::vector<cmSourceFile*>::const_iterator
si = this->SourceFiles.begin();
si != this->SourceFiles.end(); ++si)
for(std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
si = this->Internal->SourceEntries.begin();
si != this->Internal->SourceEntries.end(); ++si)
{
std::string e;
if((*si)->GetFullPath(&e).empty())
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)
{
if(!e.empty())
std::string src = *i;
cmSourceFile* sf = this->Makefile->GetOrCreateSource(src);
std::string e;
src = sf->GetFullPath(&e);
if(src.empty())
{
cmake* cm = this->Makefile->GetCMakeInstance();
cm->IssueMessage(cmake::FATAL_ERROR, e,
this->GetBacktrace());
if(!e.empty())
{
cmake* cm = this->Makefile->GetCMakeInstance();
cm->IssueMessage(cmake::FATAL_ERROR, e,
this->GetBacktrace());
}
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)
== this->SourceFiles.end())
std::vector<std::string> srcs;
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();
if(src[0] == '$' && src[1] == '<')
{
this->ProcessSourceExpression(*i);
this->AddSource(src);
}
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;
@ -632,28 +656,91 @@ cmSourceFile* cmTarget::AddSource(const std::string& s)
}
}
}
cmSourceFile* sf = this->Makefile->GetOrCreateSource(src);
this->AddSourceFile(sf);
return sf;
return this->AddSource(src);
}
//----------------------------------------------------------------------------
void cmTarget::ProcessSourceExpression(std::string const& expr)
struct CreateLocation
{
if(cmHasLiteralPrefix(expr.c_str(), "$<TARGET_OBJECTS:") &&
expr[expr.size()-1] == '>')
cmMakefile const* Makefile;
CreateLocation(cmMakefile const* mf)
: Makefile(mf)
{
}
cmSourceFileLocation operator()(const std::string& filename)
{
return cmSourceFileLocation(this->Makefile, filename);
}
};
//----------------------------------------------------------------------------
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())
{
std::string objLibName = expr.substr(17, expr.size()-18);
this->ObjectLibraries.push_back(objLibName);
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));
}
else
if (cmGeneratorExpression::Find(src) != std::string::npos)
{
cmOStringStream e;
e << "Unrecognized generator expression:\n"
<< " " << expr;
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return 0;
}
return this->Makefile->GetOrCreateSource(src);
}
//----------------------------------------------------------------------------
@ -2766,25 +2853,90 @@ const char *cmTarget::GetProperty(const std::string& prop,
{
cmOStringStream ss;
const char* sep = "";
for(std::vector<cmSourceFile*>::const_iterator
i = this->SourceFiles.begin();
i != this->SourceFiles.end(); ++i)
typedef cmTargetInternals::TargetPropertyEntry
TargetPropertyEntry;
for(std::vector<TargetPropertyEntry*>::const_iterator
i = this->Internal->SourceEntries.begin();
i != this->Internal->SourceEntries.end(); ++i)
{
// Separate from the previous list entries.
ss << sep;
sep = ";";
std::string entry = (*i)->ge->GetInput();
// Construct what is known about this source file location.
cmSourceFileLocation const& location = (*i)->GetLocation();
std::string sname = location.GetDirectory();
if(!sname.empty())
std::vector<std::string> files;
cmSystemTools::ExpandListArgument(entry, files);
for (std::vector<std::string>::const_iterator
li = files.begin(); li != files.end(); ++li)
{
sname += "/";
}
sname += location.GetName();
if(cmHasLiteralPrefix(*li, "$<TARGET_OBJECTS:") &&
(*li)[li->size() - 1] == '>')
{
std::string objLibName = li->substr(17, li->size()-18);
// Append this list entry.
ss << sname;
if (cmGeneratorExpression::Find(objLibName) != std::string::npos)
{
ss << 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.
cmSourceFileLocation const& location = sf->GetLocation();
std::string sname = location.GetDirectory();
if(!sname.empty())
{
sname += "/";
}
sname += location.GetName();
ss << sep;
sep = ";";
// Append this list entry.
ss << sname;
}
}
}
this->Properties.SetProperty("SOURCES", ss.str().c_str(),
cmProperty::TARGET);
@ -4844,8 +4996,10 @@ bool cmTarget::IsLinkInterfaceDependentNumberMaxProperty(const std::string &p,
//----------------------------------------------------------------------------
void cmTarget::GetLanguages(std::set<std::string>& languages) const
{
std::vector<cmSourceFile*> sourceFiles;
this->GetSourceFiles(sourceFiles);
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();
if(!lang.empty())
@ -4853,6 +5007,53 @@ void cmTarget::GetLanguages(std::set<std::string>& languages) const
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;
// Get languages used in our source files.
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.
for(std::set<std::string>::iterator li = languages.begin();
li != languages.end(); ++li)
@ -6395,6 +6583,7 @@ cmTargetInternalPointer::~cmTargetInternalPointer()
deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
deleteAndClear(this->Pointer->CompileOptionsEntries);
deleteAndClear(this->Pointer->CompileDefinitionsEntries);
deleteAndClear(this->Pointer->SourceEntries);
delete this->Pointer;
}

View File

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

View File

@ -1054,6 +1054,19 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
std::vector<cmSourceFile const*> 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)
{
// 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
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_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 STRINGS "${expect_STRINGS}")
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(CMP0049)
add_RunCMake_test(CMP0050)
add_RunCMake_test(CMP0051)
add_RunCMake_test(CTest)
if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles")
add_RunCMake_test(CompilerChange)
@ -49,6 +50,7 @@ add_RunCMake_test(GeneratorToolset)
add_RunCMake_test(TargetPropertyGeneratorExpressions)
add_RunCMake_test(Languages)
add_RunCMake_test(ObjectLibrary)
add_RunCMake_test(TargetObjects)
add_RunCMake_test(find_dependency)
if(NOT WIN32)
add_RunCMake_test(PositionIndependentCode)

View File

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

View File

@ -1,4 +1,8 @@
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.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -1,4 +1,8 @@
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.
Call Stack \(most recent call first\):
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_)
message(SEND_ERROR "MAKE_C_IDENTIFIER did not create expected result.")
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()