diff options
author | Brad King <brad.king@kitware.com> | 2014-04-03 16:51:51 (GMT) |
---|---|---|
committer | CMake Topic Stage <kwrobot@kitware.com> | 2014-04-03 16:51:51 (GMT) |
commit | 93054aa84f283de17c58fa2ee19a2a4a1668027d (patch) | |
tree | 8b53dac2eb3a77909458cba210a6873915fb45ab | |
parent | 1d4366ffac5814441c440d2832d9d8f187841113 (diff) | |
parent | 5de63265e3a22d9a8aa5ad437a5030ccfcbcd02d (diff) | |
download | CMake-93054aa84f283de17c58fa2ee19a2a4a1668027d.zip CMake-93054aa84f283de17c58fa2ee19a2a4a1668027d.tar.gz CMake-93054aa84f283de17c58fa2ee19a2a4a1668027d.tar.bz2 |
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.
...
64 files changed, 778 insertions, 271 deletions
diff --git a/Help/command/add_executable.rst b/Help/command/add_executable.rst index 231eeed..4ed10e1 100644 --- a/Help/command/add_executable.rst +++ b/Help/command/add_executable.rst @@ -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. + -------------------------------------------------------------------------- diff --git a/Help/command/add_library.rst b/Help/command/add_library.rst index 0944269..e93ef53 100644 --- a/Help/command/add_library.rst +++ b/Help/command/add_library.rst @@ -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. -------------------------------------------------------------------------- diff --git a/Help/command/string.rst b/Help/command/string.rst index af18825..abde6ee 100644 --- a/Help/command/string.rst +++ b/Help/command/string.rst @@ -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``. diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index ac8c3f8..dfda8dc 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -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. diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 8650a58..b763882 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -102,3 +102,4 @@ All Policies /policy/CMP0048 /policy/CMP0049 /policy/CMP0050 + /policy/CMP0051 diff --git a/Help/policy/CMP0051.rst b/Help/policy/CMP0051.rst new file mode 100644 index 0000000..7d85929 --- /dev/null +++ b/Help/policy/CMP0051.rst @@ -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. diff --git a/Help/release/dev/string-GENEX_STRIP.rst b/Help/release/dev/string-GENEX_STRIP.rst new file mode 100644 index 0000000..b5b1074 --- /dev/null +++ b/Help/release/dev/string-GENEX_STRIP.rst @@ -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)>`. diff --git a/Help/release/dev/target-SOURCES-genex.rst b/Help/release/dev/target-SOURCES-genex.rst new file mode 100644 index 0000000..9a65101 --- /dev/null +++ b/Help/release/dev/target-SOURCES-genex.rst @@ -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. diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 5ba843f..27fc862 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -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. diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx index 0a36b82..e2b114a 100644 --- a/Source/cmFLTKWrapUICommand.cxx +++ b/Source/cmFLTKWrapUICommand.cxx @@ -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()); } } } diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index e127f3a..d09e950 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -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 = diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index d0a6aef..da64515 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -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 diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 14b2a1a..95227d2 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -15,6 +15,8 @@ #include "cmGeneratorExpressionParser.h" #include "cmGeneratorExpressionDAGChecker.h" #include "cmGeneratorExpression.h" +#include "cmLocalGenerator.h" +#include "cmSourceFile.h" #include <cmsys/String.h> @@ -1240,6 +1242,77 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode } targetNameNode; //---------------------------------------------------------------------------- +static const struct TargetObjectsNode : public cmGeneratorExpressionNode +{ + TargetObjectsNode() {} + + std::string Evaluate(const std::vector<std::string> ¶meters, + 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 #define TARGET_POLICY_STRING(POLICY) \ @@ -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; diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h index a7099cb..54a2548 100644 --- a/Source/cmGeneratorExpressionEvaluator.h +++ b/Source/cmGeneratorExpressionEvaluator.h @@ -34,6 +34,7 @@ struct cmGeneratorExpressionContext bool Quiet; bool HadError; bool HadContextSensitiveCondition; + bool EvaluateForBuildsystem; }; struct cmGeneratorExpressionDAGChecker; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index b35e859..321dd42 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -311,18 +311,36 @@ 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); } -//---------------------------------------------------------------------------- -const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file) +void cmGeneratorTarget::ComputeObjectMapping() { - return this->Objects[file]; + if(!this->Objects.empty()) + { + return; + } + std::vector<cmSourceFile const*> sourceFiles; + this->GetObjectSources(sourceFiles); } -void cmGeneratorTarget::AddObject(cmSourceFile const* sf, - std::string const&name) +//---------------------------------------------------------------------------- +const std::string& cmGeneratorTarget::GetObjectName(cmSourceFile const* file) { - this->Objects[sf] = name; + this->ComputeObjectMapping(); + return this->Objects[file]; } //---------------------------------------------------------------------------- @@ -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(); @@ -504,58 +523,6 @@ void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*> &files) const } //---------------------------------------------------------------------------- -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 data; @@ -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()); } } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 53e27c5..38e6510 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -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; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 3d291f4..a12b68f 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -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() @@ -1518,29 +1501,6 @@ cmGlobalGenerator::GetGeneratorTarget(cmTarget const* t) const } //---------------------------------------------------------------------------- -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 { } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 49a418d..54f5f3b 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -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(); diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index ab4380c..e80df84 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -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 { diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index d4eb85b..d9d4927 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -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; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 9cafed1..c840888 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -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); } diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index 2ab25cc..11e9679 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -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 diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 52524aa..8bac10d 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -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") diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 621b8ee..b1d6fe2 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -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) diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index b3d3f71..5bb7b8b 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -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); } //---------------------------------------------------------------------------- diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 8865b3d..b7eab7d 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -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"; } diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index 2bd553f..759df91 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -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() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index b77235d..7a08a34 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -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. * diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index a6e6af7..71c4630 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -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); } } diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index b9b6251..0ab30a2 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -39,6 +39,18 @@ std::string const& cmSourceFile::GetExtension() const } //---------------------------------------------------------------------------- +void cmSourceFile::SetObjectLibrary(std::string const& objlib) +{ + this->ObjectLibrary = objlib; +} + +//---------------------------------------------------------------------------- +std::string cmSourceFile::GetObjectLibrary() const +{ + return this->ObjectLibrary; +} + +//---------------------------------------------------------------------------- std::string cmSourceFile::GetLanguage() { // If the language was set explicitly by the user then use it. diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h index 17c96ac..755a2cf 100644 --- a/Source/cmSourceFile.h +++ b/Source/cmSourceFile.h @@ -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); diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index 30a53cb..c050202 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -16,29 +16,57 @@ #include "cmGlobalGenerator.h" #include "cmSystemTools.h" +#include "assert.h" + //---------------------------------------------------------------------------- -cmSourceFileLocation -::cmSourceFileLocation(cmMakefile const* mf, const std::string& name) - : Makefile(mf) +cmSourceFileLocation::cmSourceFileLocation() + : Makefile(0), AmbiguousDirectory(true), AmbiguousExtension(true) { - this->AmbiguousDirectory = !cmSystemTools::FileIsFullPath(name.c_str()); - this->AmbiguousExtension = true; - this->Directory = cmSystemTools::GetFilenamePath(name); - this->Name = cmSystemTools::GetFilenameName(name); - this->UpdateExtension(name); + } //---------------------------------------------------------------------------- -void cmSourceFileLocation::Update(const std::string& name) +cmSourceFileLocation::cmSourceFileLocation(const cmSourceFileLocation& loc) + : Makefile(loc.Makefile) { - if(this->AmbiguousDirectory) + 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) { - this->UpdateDirectory(name); + return *this; } - if(this->AmbiguousExtension) + 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) + : Makefile(mf) +{ + this->AmbiguousDirectory = !cmSystemTools::FileIsFullPath(name.c_str()); + this->AmbiguousExtension = true; + this->Directory = cmSystemTools::GetFilenamePath(name); + if (cmSystemTools::FileIsFullPath(this->Directory.c_str())) { - this->UpdateExtension(name); + this->Directory + = cmSystemTools::CollapseFullPath(this->Directory.c_str()); } + this->Name = cmSystemTools::GetFilenameName(name); + this->UpdateExtension(name); } //---------------------------------------------------------------------------- @@ -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); } @@ -137,21 +168,11 @@ 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 diff --git a/Source/cmSourceFileLocation.h b/Source/cmSourceFileLocation.h index c83e8c0..c37fb1d 100644 --- a/Source/cmSourceFileLocation.h +++ b/Source/cmSourceFileLocation.h @@ -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 diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index 7bc7b05..ea762eb 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -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); @@ -810,6 +814,27 @@ bool cmStringCommand } //---------------------------------------------------------------------------- +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) { diff --git a/Source/cmStringCommand.h b/Source/cmStringCommand.h index b8053c5..5b7412d 100644 --- a/Source/cmStringCommand.h +++ b/Source/cmStringCommand.h @@ -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 { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 32aaccc..573b816 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -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 +{ + cmMakefile const* Makefile; + + CreateLocation(cmMakefile const* mf) + : Makefile(mf) + { + + } + + cmSourceFileLocation operator()(const std::string& filename) + { + return cmSourceFileLocation(this->Makefile, filename); + } +}; + +//---------------------------------------------------------------------------- +struct LocationMatcher { - if(cmHasLiteralPrefix(expr.c_str(), "$<TARGET_OBJECTS:") && - expr[expr.size()-1] == '>') + 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); + + 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(); - // Append this list entry. - ss << sname; + 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; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 3ef853b..fcbff93 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -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; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index bb76b7f..8d10e7c 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -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 diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt index a0e34ef..758165c 100644 --- a/Tests/GeneratorExpression/CMakeLists.txt +++ b/Tests/GeneratorExpression/CMakeLists.txt @@ -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) diff --git a/Tests/Properties/CMakeLists.txt b/Tests/Properties/CMakeLists.txt index 285d596..11fca45 100644 --- a/Tests/Properties/CMakeLists.txt +++ b/Tests/Properties/CMakeLists.txt @@ -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) diff --git a/Tests/Properties/SubDir2/CMakeLists.txt b/Tests/Properties/SubDir2/CMakeLists.txt new file mode 100644 index 0000000..377dc83 --- /dev/null +++ b/Tests/Properties/SubDir2/CMakeLists.txt @@ -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") diff --git a/Tests/Properties/subdirtest.cxx b/Tests/Properties/subdirtest.cxx new file mode 100644 index 0000000..02d8f3d --- /dev/null +++ b/Tests/Properties/subdirtest.cxx @@ -0,0 +1,9 @@ + +#ifndef SUBDIR_TEST +#error Expected SUBDIR_TEST +#endif + +int main(int, char**) +{ + return 0; +} diff --git a/Tests/RunCMake/CMP0051/CMP0051-NEW-result.txt b/Tests/RunCMake/CMP0051/CMP0051-NEW-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CMP0051/CMP0051-NEW-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0051/CMP0051-NEW-stderr.txt b/Tests/RunCMake/CMP0051/CMP0051-NEW-stderr.txt new file mode 100644 index 0000000..e5578ba --- /dev/null +++ b/Tests/RunCMake/CMP0051/CMP0051-NEW-stderr.txt @@ -0,0 +1 @@ +^Sources: "empty.cpp;\$<TARGET_OBJECTS:objects>"$ diff --git a/Tests/RunCMake/CMP0051/CMP0051-NEW.cmake b/Tests/RunCMake/CMP0051/CMP0051-NEW.cmake new file mode 100644 index 0000000..f304bf1 --- /dev/null +++ b/Tests/RunCMake/CMP0051/CMP0051-NEW.cmake @@ -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}\"") diff --git a/Tests/RunCMake/CMP0051/CMP0051-OLD-result.txt b/Tests/RunCMake/CMP0051/CMP0051-OLD-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CMP0051/CMP0051-OLD-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0051/CMP0051-OLD-stderr.txt b/Tests/RunCMake/CMP0051/CMP0051-OLD-stderr.txt new file mode 100644 index 0000000..cc17f33 --- /dev/null +++ b/Tests/RunCMake/CMP0051/CMP0051-OLD-stderr.txt @@ -0,0 +1 @@ +^Sources: "empty.cpp"$ diff --git a/Tests/RunCMake/CMP0051/CMP0051-OLD.cmake b/Tests/RunCMake/CMP0051/CMP0051-OLD.cmake new file mode 100644 index 0000000..0243e94 --- /dev/null +++ b/Tests/RunCMake/CMP0051/CMP0051-OLD.cmake @@ -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}\"") diff --git a/Tests/RunCMake/CMP0051/CMP0051-WARN-result.txt b/Tests/RunCMake/CMP0051/CMP0051-WARN-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CMP0051/CMP0051-WARN-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CMP0051/CMP0051-WARN-stderr.txt b/Tests/RunCMake/CMP0051/CMP0051-WARN-stderr.txt new file mode 100644 index 0000000..f1b0357 --- /dev/null +++ b/Tests/RunCMake/CMP0051/CMP0051-WARN-stderr.txt @@ -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"$ diff --git a/Tests/RunCMake/CMP0051/CMP0051-WARN.cmake b/Tests/RunCMake/CMP0051/CMP0051-WARN.cmake new file mode 100644 index 0000000..fd595ce --- /dev/null +++ b/Tests/RunCMake/CMP0051/CMP0051-WARN.cmake @@ -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}\"") diff --git a/Tests/RunCMake/CMP0051/CMakeLists.txt b/Tests/RunCMake/CMP0051/CMakeLists.txt new file mode 100644 index 0000000..3482e6b --- /dev/null +++ b/Tests/RunCMake/CMP0051/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.0) +project(${RunCMake_TEST} CXX) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CMP0051/RunCMakeTest.cmake b/Tests/RunCMake/CMP0051/RunCMakeTest.cmake new file mode 100644 index 0000000..621192d --- /dev/null +++ b/Tests/RunCMake/CMP0051/RunCMakeTest.cmake @@ -0,0 +1,5 @@ +include(RunCMake) + +run_cmake(CMP0051-OLD) +run_cmake(CMP0051-NEW) +run_cmake(CMP0051-WARN) diff --git a/Tests/RunCMake/CMP0051/empty.cpp b/Tests/RunCMake/CMP0051/empty.cpp new file mode 100644 index 0000000..bfbbdde --- /dev/null +++ b/Tests/RunCMake/CMP0051/empty.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty() +{ + return 0; +} diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 7691f32..4f059d6 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -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) diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-stderr.txt index a1cac36..859dc3f 100644 --- a/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-stderr.txt +++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression1-stderr.txt @@ -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\) diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-stderr.txt index f1fcbe8..7060c61 100644 --- a/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-stderr.txt +++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression2-stderr.txt @@ -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\) diff --git a/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt index ad14a35..838b3d8 100644 --- a/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt +++ b/Tests/RunCMake/ObjectLibrary/BadSourceExpression3-stderr.txt @@ -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\) diff --git a/Tests/RunCMake/TargetObjects/BadContext-result.txt b/Tests/RunCMake/TargetObjects/BadContext-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/TargetObjects/BadContext-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/TargetObjects/BadContext-stderr.txt b/Tests/RunCMake/TargetObjects/BadContext-stderr.txt new file mode 100644 index 0000000..92f2c91 --- /dev/null +++ b/Tests/RunCMake/TargetObjects/BadContext-stderr.txt @@ -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. diff --git a/Tests/RunCMake/TargetObjects/BadContext.cmake b/Tests/RunCMake/TargetObjects/BadContext.cmake new file mode 100644 index 0000000..67962a4 --- /dev/null +++ b/Tests/RunCMake/TargetObjects/BadContext.cmake @@ -0,0 +1,4 @@ + +file(GENERATE OUTPUT test_output CONTENT $<TARGET_OBJECTS:NoTarget>) + +install(FILES $<TARGET_OBJECTS:NoTarget> DESTINATION objects) diff --git a/Tests/RunCMake/TargetObjects/CMakeLists.txt b/Tests/RunCMake/TargetObjects/CMakeLists.txt new file mode 100644 index 0000000..be9d403 --- /dev/null +++ b/Tests/RunCMake/TargetObjects/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST}) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake b/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake new file mode 100644 index 0000000..85c76e2 --- /dev/null +++ b/Tests/RunCMake/TargetObjects/RunCMakeTest.cmake @@ -0,0 +1,3 @@ +include(RunCMake) + +run_cmake(BadContext) diff --git a/Tests/StringFileTest/CMakeLists.txt b/Tests/StringFileTest/CMakeLists.txt index 00383ab..be6d8fe 100644 --- a/Tests/StringFileTest/CMakeLists.txt +++ b/Tests/StringFileTest/CMakeLists.txt @@ -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() |