diff --git a/Help/command/target_sources.rst b/Help/command/target_sources.rst new file mode 100644 index 000000000..ff756b4ff --- /dev/null +++ b/Help/command/target_sources.rst @@ -0,0 +1,28 @@ +target_sources +-------------- + +Add sources to a target. + +:: + + target_sources( + [items1...] + [ [items2...] ...]) + +Specify sources to use when compiling a given target. The +named ```` must have been created by a command such as +:command:`add_executable` or :command:`add_library` and must not be an +:prop_tgt:`IMPORTED Target`. + +The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to +specify the scope of the following arguments. ``PRIVATE`` and ``PUBLIC`` +items will populate the :prop_tgt:`SOURCES` property of +````. ``PUBLIC`` and ``INTERFACE`` items will populate the +:prop_tgt:`INTERFACE_SOURCES` property of ````. The +following arguments specify sources. Repeated calls for the same +```` append items in the order called. + +Arguments to ``target_sources`` may use "generator expressions" +with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` +manual for available expressions. See the :manual:`cmake-buildsystem(7)` +manual for more on defining buildsystem properties. diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst index fb0d2b528..4b1dbedc8 100644 --- a/Help/manual/cmake-commands.7.rst +++ b/Help/manual/cmake-commands.7.rst @@ -94,6 +94,7 @@ These commands may be used freely in CMake projects. /command/target_compile_options /command/target_include_directories /command/target_link_libraries + /command/target_sources /command/try_compile /command/try_run /command/unset diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 6ea5839c8..fd16eb95f 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -152,6 +152,7 @@ Properties on Targets /prop_tgt/INTERFACE_INCLUDE_DIRECTORIES /prop_tgt/INTERFACE_LINK_LIBRARIES /prop_tgt/INTERFACE_POSITION_INDEPENDENT_CODE + /prop_tgt/INTERFACE_SOURCES /prop_tgt/INTERFACE_SYSTEM_INCLUDE_DIRECTORIES /prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG /prop_tgt/INTERPROCEDURAL_OPTIMIZATION diff --git a/Help/prop_tgt/INTERFACE_SOURCES.rst b/Help/prop_tgt/INTERFACE_SOURCES.rst new file mode 100644 index 000000000..fb28231a3 --- /dev/null +++ b/Help/prop_tgt/INTERFACE_SOURCES.rst @@ -0,0 +1,15 @@ +INTERFACE_SOURCES +----------------- + +List of interface sources to pass to the compiler. + +Targets may populate this property to publish the sources +for consuming targets to compile. Consuming +targets can add entries to their own :prop_tgt:`SOURCES` property +such as ``$`` to use the +sources specified in the interface of ``foo``. + +Contents of ``INTERFACE_SOURCES`` may use "generator expressions" +with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` +manual for available expressions. See the :manual:`cmake-buildsystem(7)` +manual for more on defining buildsystem properties. diff --git a/Help/prop_tgt/SOURCES.rst b/Help/prop_tgt/SOURCES.rst index 833b65a6e..493643e84 100644 --- a/Help/prop_tgt/SOURCES.rst +++ b/Help/prop_tgt/SOURCES.rst @@ -3,5 +3,4 @@ SOURCES Source names specified for a target. -Read-only list of sources specified for a target. The names returned -are suitable for passing to the set_source_files_properties command. +List of sources specified for a target. diff --git a/Help/release/dev/target-INTERFACE_SOURCES.rst b/Help/release/dev/target-INTERFACE_SOURCES.rst new file mode 100644 index 000000000..4e3494321 --- /dev/null +++ b/Help/release/dev/target-INTERFACE_SOURCES.rst @@ -0,0 +1,5 @@ +target-INTERFACE_SOURCES +------------------------ + +* A new :prop_tgt:`INTERFACE_SOURCES` target property was introduced. This is + consumed by dependent targets, which compile and link the listed sources. diff --git a/Help/release/dev/target-SOURCES-write.rst b/Help/release/dev/target-SOURCES-write.rst new file mode 100644 index 000000000..a754a7361 --- /dev/null +++ b/Help/release/dev/target-SOURCES-write.rst @@ -0,0 +1,6 @@ +target-SOURCES-write.rst +------------------------ + +* It is now possible to write and append to the :prop_tgt:`SOURCES` target + property. The :variable:`CMAKE_DEBUG_TARGET_PROPERTIES` variable may be + used to trace the origin of sources. diff --git a/Help/release/dev/target_sources-command.rst b/Help/release/dev/target_sources-command.rst new file mode 100644 index 000000000..abfb303b4 --- /dev/null +++ b/Help/release/dev/target_sources-command.rst @@ -0,0 +1,5 @@ +target_sources-command +---------------------- + +* The :command:`target_sources` command was added to add to the + :prop_tgt:`SOURCES` target property. diff --git a/Help/variable/CMAKE_DEBUG_TARGET_PROPERTIES.rst b/Help/variable/CMAKE_DEBUG_TARGET_PROPERTIES.rst index 11aed0c0b..edd8fa1fc 100644 --- a/Help/variable/CMAKE_DEBUG_TARGET_PROPERTIES.rst +++ b/Help/variable/CMAKE_DEBUG_TARGET_PROPERTIES.rst @@ -6,7 +6,8 @@ Enables tracing output for target properties. This variable can be populated with a list of properties to generate debug output for when evaluating target properties. Currently it can only be used when evaluating the :prop_tgt:`INCLUDE_DIRECTORIES`, -:prop_tgt:`COMPILE_DEFINITIONS`, :prop_tgt:`COMPILE_OPTIONS`, :prop_tgt:`AUTOUIC_OPTIONS`, +:prop_tgt:`COMPILE_DEFINITIONS`, :prop_tgt:`COMPILE_OPTIONS`, +:prop_tgt:`AUTOUIC_OPTIONS`, :prop_tgt:`SOURCES`, :prop_tgt:`POSITION_INDEPENDENT_CODE` target properties and any other property listed in :prop_tgt:`COMPATIBLE_INTERFACE_STRING` and other ``COMPATIBLE_INTERFACE_`` properties. It outputs an origin for each entry in the target property. diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 27d099d40..4c678d8c7 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -348,6 +348,7 @@ foreach(command_file cmTargetCompileDefinitionsCommand cmTargetCompileOptionsCommand cmTargetIncludeDirectoriesCommand + cmTargetSourcesCommand cmUseMangledMesaCommand cmUtilitySourceCommand cmVariableRequiresCommand diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 27fc8620d..eb6245529 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -213,56 +213,42 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // deal with config-specific dependencies. { std::set emitted; - { cmGeneratorTarget* gt = depender->GetMakefile()->GetLocalGenerator() ->GetGlobalGenerator() ->GetGeneratorTarget(depender); - std::vector objectFiles; - gt->GetExternalObjects(objectFiles); - for(std::vector::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(depender)->AddUtility(objLib); - } - } - } - { - std::vector tlibs; - depender->GetDirectLinkLibraries("", tlibs, depender); - // A target should not depend on itself. - emitted.insert(depender->GetName()); - for(std::vector::const_iterator lib = tlibs.begin(); - lib != tlibs.end(); ++lib) - { - // Don't emit the same library twice for this target. - if(emitted.insert(*lib).second) - { - this->AddTargetDepend(depender_index, *lib, true); - this->AddInterfaceDepends(depender_index, *lib, - true, emitted); - } - } - } + std::vector configs; depender->GetMakefile()->GetConfigurations(configs); + if (configs.empty()) + { + configs.push_back(""); + } for (std::vector::const_iterator it = configs.begin(); it != configs.end(); ++it) { + std::vector objectFiles; + gt->GetExternalObjects(objectFiles, *it); + for(std::vector::const_iterator + oi = objectFiles.begin(); oi != objectFiles.end(); ++oi) + { + std::string objLib = (*oi)->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(depender)->AddUtility(objLib); + } + } std::vector tlibs; depender->GetDirectLinkLibraries(*it, tlibs, depender); diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index e99bf0461..6f76dc492 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -399,7 +399,8 @@ void cmExtraCodeBlocksGenerator case cmTarget::UTILITY: // can have sources since 2.6.3 { std::vector sources; - ti->second.GetSourceFiles(sources); + ti->second.GetSourceFiles(sources, + makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); for (std::vector::const_iterator si=sources.begin(); si!=sources.end(); si++) { diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx index 1cbd0577a..33ffc9002 100644 --- a/Source/cmExtraCodeLiteGenerator.cxx +++ b/Source/cmExtraCodeLiteGenerator.cxx @@ -214,7 +214,8 @@ void cmExtraCodeLiteGenerator case cmTarget::MODULE_LIBRARY: { std::vector sources; - ti->second.GetSourceFiles(sources); + ti->second.GetSourceFiles(sources, + makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); for (std::vector::const_iterator si=sources.begin(); si!=sources.end(); si++) { diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index fcb95a0ed..e23551e9f 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -560,7 +560,8 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets( // get the files from the source lists then add them to the groups cmTarget* tgt = const_cast(&ti->second); std::vector files; - tgt->GetSourceFiles(files); + tgt->GetSourceFiles(files, + makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); for(std::vector::const_iterator sfIt = files.begin(); sfIt != files.end(); sfIt++) diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx index ec5ffc291..7fe47c3e4 100644 --- a/Source/cmExtraSublimeTextGenerator.cxx +++ b/Source/cmExtraSublimeTextGenerator.cxx @@ -238,7 +238,8 @@ void cmExtraSublimeTextGenerator:: cmGeneratorTarget *gtgt = this->GlobalGenerator ->GetGeneratorTarget(target); std::vector sourceFiles; - target->GetSourceFiles(sourceFiles); + target->GetSourceFiles(sourceFiles, + makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); std::vector::const_iterator sourceFilesEnd = sourceFiles.end(); for (std::vector::const_iterator iter = diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx index e2b114a16..f7d824347 100644 --- a/Source/cmFLTKWrapUICommand.cxx +++ b/Source/cmFLTKWrapUICommand.cxx @@ -133,7 +133,7 @@ void cmFLTKWrapUICommand::FinalPass() return; } std::vector srcs; - target->GetSourceFiles(srcs); + target->GetSourceFiles(srcs, ""); bool found = false; for (unsigned int i = 0; i < srcs.size(); ++i) { diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index 07efba9bc..7f8e6943a 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -179,6 +179,18 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries(const char *tgt) || strcmp(prop, "INTERFACE_LINK_LIBRARIES") == 0; } +std::string cmGeneratorExpressionDAGChecker::TopTarget() const +{ + const cmGeneratorExpressionDAGChecker *top = this; + const cmGeneratorExpressionDAGChecker *parent = this->Parent; + while (parent) + { + top = parent; + parent = parent->Parent; + } + return top->Target; +} + enum TransitiveProperty { #define DEFINE_ENUM_ENTRY(NAME) NAME, CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(DEFINE_ENUM_ENTRY) diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h index 6cbbd2a07..b3147f7e1 100644 --- a/Source/cmGeneratorExpressionDAGChecker.h +++ b/Source/cmGeneratorExpressionDAGChecker.h @@ -25,7 +25,8 @@ SELECT(F, EvaluatingSystemIncludeDirectories, SYSTEM_INCLUDE_DIRECTORIES) \ SELECT(F, EvaluatingCompileDefinitions, COMPILE_DEFINITIONS) \ SELECT(F, EvaluatingCompileOptions, COMPILE_OPTIONS) \ - SELECT(F, EvaluatingAutoUicOptions, AUTOUIC_OPTIONS) + SELECT(F, EvaluatingAutoUicOptions, AUTOUIC_OPTIONS) \ + SELECT(F, EvaluatingSources, SOURCES) #define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \ CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH) @@ -70,6 +71,8 @@ struct cmGeneratorExpressionDAGChecker void SetTransitivePropertiesOnly() { this->TransitivePropertiesOnly = true; } + std::string TopTarget() const; + private: Result CheckGraph() const; diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 95227d257..a51392142 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -985,7 +985,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode if (propertyName == "LINKER_LANGUAGE") { if (target->LinkLanguagePropagatesToDependents() && - dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries()) + dagCheckerParent && (dagCheckerParent->EvaluatingLinkLibraries() + || dagCheckerParent->EvaluatingSources())) { reportError(context, content->GetOriginalExpression(), "LINKER_LANGUAGE target property can not be used while evaluating " @@ -1282,7 +1283,7 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode } std::vector objectSources; - gt->GetObjectSources(objectSources); + gt->GetObjectSources(objectSources, context->Config); std::map mapping; for(std::vector::const_iterator it @@ -1579,7 +1580,9 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode "Target \"" + name + "\" is not an executable or library."); return std::string(); } - if (dagChecker && dagChecker->EvaluatingLinkLibraries(name.c_str())) + if (dagChecker && (dagChecker->EvaluatingLinkLibraries(name.c_str()) + || (dagChecker->EvaluatingSources() + && name == dagChecker->TopTarget()))) { ::reportError(context, content->GetOriginalExpression(), "Expressions which require the linker language may not " diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 321dd42c5..01fad26e1 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -289,7 +289,7 @@ static void handleSystemIncludesDep(cmMakefile *mf, cmTarget* depTgt, #define IMPLEMENT_VISIT_IMPL(DATA, DATATYPE) \ { \ std::vector sourceFiles; \ - this->Target->GetSourceFiles(sourceFiles); \ + this->Target->GetSourceFiles(sourceFiles, config); \ TagVisitor visitor(this->Target, data); \ for(std::vector::const_iterator si = sourceFiles.begin(); \ si != sourceFiles.end(); ++si) \ @@ -308,7 +308,8 @@ static void handleSystemIncludesDep(cmMakefile *mf, cmTarget* depTgt, //---------------------------------------------------------------------------- void cmGeneratorTarget -::GetObjectSources(std::vector &data) const +::GetObjectSources(std::vector &data, + const std::string& config) const { IMPLEMENT_VISIT(ObjectSources); @@ -332,8 +333,19 @@ void cmGeneratorTarget::ComputeObjectMapping() { return; } - std::vector sourceFiles; - this->GetObjectSources(sourceFiles); + + std::vector configs; + this->Makefile->GetConfigurations(configs); + if (configs.empty()) + { + configs.push_back(""); + } + for(std::vector::const_iterator ci = configs.begin(); + ci != configs.end(); ++ci) + { + std::vector sourceFiles; + this->GetObjectSources(sourceFiles, *ci); + } } //---------------------------------------------------------------------------- @@ -360,7 +372,8 @@ bool cmGeneratorTarget::HasExplicitObjectName(cmSourceFile const* file) const //---------------------------------------------------------------------------- void cmGeneratorTarget -::GetIDLSources(std::vector& data) const +::GetIDLSources(std::vector& data, + const std::string& config) const { IMPLEMENT_VISIT(IDLSources); } @@ -368,14 +381,16 @@ void cmGeneratorTarget //---------------------------------------------------------------------------- void cmGeneratorTarget -::GetHeaderSources(std::vector& data) const +::GetHeaderSources(std::vector& data, + const std::string& config) const { IMPLEMENT_VISIT(HeaderSources); } //---------------------------------------------------------------------------- void cmGeneratorTarget -::GetExtraSources(std::vector& data) const +::GetExtraSources(std::vector& data, + const std::string& config) const { IMPLEMENT_VISIT(ExtraSources); } @@ -383,7 +398,8 @@ void cmGeneratorTarget //---------------------------------------------------------------------------- void cmGeneratorTarget -::GetCustomCommands(std::vector& data) const +::GetCustomCommands(std::vector& data, + const std::string& config) const { IMPLEMENT_VISIT(CustomCommands); } @@ -391,14 +407,16 @@ cmGeneratorTarget //---------------------------------------------------------------------------- void cmGeneratorTarget -::GetExternalObjects(std::vector& data) const +::GetExternalObjects(std::vector& data, + const std::string& config) const { IMPLEMENT_VISIT(ExternalObjects); } //---------------------------------------------------------------------------- void -cmGeneratorTarget::GetExpectedResxHeaders(std::set& srcs) const +cmGeneratorTarget::GetExpectedResxHeaders(std::set& srcs, + const std::string& config) const { ResxData data; IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData) @@ -407,7 +425,8 @@ cmGeneratorTarget::GetExpectedResxHeaders(std::set& srcs) const //---------------------------------------------------------------------------- void cmGeneratorTarget -::GetResxSources(std::vector& srcs) const +::GetResxSources(std::vector& srcs, + const std::string& config) const { ResxData data; IMPLEMENT_VISIT_IMPL(Resx, COMMA cmGeneratorTarget::ResxData) @@ -517,13 +536,15 @@ bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const } //---------------------------------------------------------------------------- -void cmGeneratorTarget::GetSourceFiles(std::vector &files) const +void cmGeneratorTarget::GetSourceFiles(std::vector &files, + const std::string& config) const { - this->Target->GetSourceFiles(files); + this->Target->GetSourceFiles(files, config); } //---------------------------------------------------------------------------- -std::string cmGeneratorTarget::GetModuleDefinitionFile() const +std::string +cmGeneratorTarget::GetModuleDefinitionFile(const std::string& config) const { std::string data; IMPLEMENT_VISIT_IMPL(ModuleDefinitionFile, COMMA std::string) @@ -532,10 +553,11 @@ std::string cmGeneratorTarget::GetModuleDefinitionFile() const //---------------------------------------------------------------------------- void -cmGeneratorTarget::UseObjectLibraries(std::vector& objs) const +cmGeneratorTarget::UseObjectLibraries(std::vector& objs, + const std::string &config) const { std::vector objectFiles; - this->GetExternalObjects(objectFiles); + this->GetExternalObjects(objectFiles, config); std::vector objectLibraries; std::set emitted; for(std::vector::const_iterator @@ -559,7 +581,7 @@ cmGeneratorTarget::UseObjectLibraries(std::vector& objs) const cmGeneratorTarget* ogt = this->GlobalGenerator->GetGeneratorTarget(objLib); std::vector objectSources; - ogt->GetObjectSources(objectSources); + ogt->GetObjectSources(objectSources, config); for(std::vector::const_iterator si = objectSources.begin(); si != objectSources.end(); ++si) @@ -615,11 +637,26 @@ cmTargetTraceDependencies if (this->Target->GetType() != cmTarget::INTERFACE_LIBRARY) { std::vector sources; - this->Target->GetSourceFiles(sources); + std::vector configs; + this->Makefile->GetConfigurations(configs); + if (configs.empty()) + { + configs.push_back(""); + } + for(std::vector::const_iterator ci = configs.begin(); + ci != configs.end(); ++ci) + { + this->Target->GetSourceFiles(sources, *ci); + } + std::set emitted; for(std::vector::const_iterator si = sources.begin(); si != sources.end(); ++si) { - this->QueueSource(*si); + if(emitted.insert(*si).second && this->SourcesQueued.insert(*si).second) + { + this->SourceQueue.push(*si); + this->Makefile->GetOrCreateSource(*si); + } } } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 38e65100a..9d13e6c0b 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -30,21 +30,30 @@ public: std::string GetName() const; const char *GetProperty(const std::string& prop) const; bool GetPropertyAsBool(const std::string& prop) const; - void GetSourceFiles(std::vector& files) const; + void GetSourceFiles(std::vector& files, + const std::string& config) const; - void GetObjectSources(std::vector &) const; + void GetObjectSources(std::vector &, + const std::string& config) const; const std::string& GetObjectName(cmSourceFile const* file); bool HasExplicitObjectName(cmSourceFile const* file) const; void AddExplicitObjectName(cmSourceFile const* sf); - void GetResxSources(std::vector&) const; - void GetIDLSources(std::vector&) const; - void GetExternalObjects(std::vector&) const; - void GetHeaderSources(std::vector&) const; - void GetExtraSources(std::vector&) const; - void GetCustomCommands(std::vector&) const; - void GetExpectedResxHeaders(std::set&) const; + void GetResxSources(std::vector&, + const std::string& config) const; + void GetIDLSources(std::vector&, + const std::string& config) const; + void GetExternalObjects(std::vector&, + const std::string& config) const; + void GetHeaderSources(std::vector&, + const std::string& config) const; + void GetExtraSources(std::vector&, + const std::string& config) const; + void GetCustomCommands(std::vector&, + const std::string& config) const; + void GetExpectedResxHeaders(std::set&, + const std::string& config) const; void ComputeObjectMapping(); @@ -53,14 +62,15 @@ public: cmLocalGenerator* LocalGenerator; cmGlobalGenerator const* GlobalGenerator; - std::string GetModuleDefinitionFile() const; + std::string GetModuleDefinitionFile(const std::string& config) const; /** Full path with trailing slash to the top-level directory holding object files for this target. Includes the build time config name placeholder if needed for the generator. */ std::string ObjectDirectory; - void UseObjectLibraries(std::vector& objs) const; + void UseObjectLibraries(std::vector& objs, + const std::string& config) const; void GetAppleArchs(const std::string& config, std::vector& archVec) const; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index a12b68fae..f09f7b3be 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -2902,10 +2902,25 @@ void cmGlobalGenerator::WriteSummary(cmTarget* target) // List the source files with any per-source labels. fout << "# Source files and their labels\n"; std::vector sources; - target->GetSourceFiles(sources); + std::vector configs; + target->GetMakefile()->GetConfigurations(configs); + if (configs.empty()) + { + configs.push_back(""); + } + for(std::vector::const_iterator ci = configs.begin(); + ci != configs.end(); ++ci) + { + target->GetSourceFiles(sources, *ci); + } + std::set emitted; for(std::vector::const_iterator si = sources.begin(); si != sources.end(); ++si) { + if (!emitted.insert(*si).second) + { + continue; + } cmSourceFile* sf = *si; fout << sf->GetFullPath() << "\n"; if(const char* svalue = sf->GetProperty("LABELS")) diff --git a/Source/cmGlobalKdevelopGenerator.cxx b/Source/cmGlobalKdevelopGenerator.cxx index df3ce108d..89d25c437 100644 --- a/Source/cmGlobalKdevelopGenerator.cxx +++ b/Source/cmGlobalKdevelopGenerator.cxx @@ -139,7 +139,8 @@ bool cmGlobalKdevelopGenerator ti != targets.end(); ti++) { std::vector sources; - ti->second.GetSourceFiles(sources); + ti->second.GetSourceFiles(sources, ti->second.GetMakefile() + ->GetSafeDefinition("CMAKE_BUILD_TYPE")); for (std::vector::const_iterator si=sources.begin(); si!=sources.end(); si++) { diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 3aa293e73..8dae81bb1 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -1081,7 +1081,8 @@ bool cmGlobalUnixMakefileGenerator3 ::NeedRequiresStep(cmTarget const& target) { std::set languages; - target.GetLanguages(languages); + target.GetLanguages(languages, + target.GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE")); for(std::set::const_iterator l = languages.begin(); l != languages.end(); ++l) { diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 38f709f42..c5a0e29e7 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -815,7 +815,15 @@ cmGlobalVisualStudioGenerator::TargetIsFortranOnly(cmTarget const& target) { // check to see if this is a fortran build std::set languages; - target.GetLanguages(languages); + { + // Issue diagnostic if the source files depend on the config. + std::vector sources; + if (!target.GetConfigCommonSourceFiles(sources)) + { + return false; + } + } + target.GetLanguages(languages, ""); if(languages.size() == 1) { if(*languages.begin() == "Fortran") diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index d9d492792..b3975b48a 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -984,7 +984,10 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, // organize the sources std::vector classes; - cmtarget.GetSourceFiles(classes); + if (!cmtarget.GetConfigCommonSourceFiles(classes)) + { + return; + } std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare()); gtgt->ComputeObjectMapping(); @@ -1043,7 +1046,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen, // the externalObjFiles above, except each one is not a cmSourceFile // within the target.) std::vector objs; - gtgt->UseObjectLibraries(objs); + gtgt->UseObjectLibraries(objs, ""); for(std::vector::const_iterator oi = objs.begin(); oi != objs.end(); ++oi) { @@ -1359,7 +1362,10 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases, } std::vector classes; - cmtarget.GetSourceFiles(classes); + if (!cmtarget.GetConfigCommonSourceFiles(classes)) + { + return; + } // add all the sources std::vector commands; for(std::vector::const_iterator i = classes.begin(); @@ -2439,7 +2445,11 @@ cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget) if(cmtarget.GetType() == cmTarget::UTILITY) { std::vector sources; - cmtarget.GetSourceFiles(sources); + if (!cmtarget.GetConfigCommonSourceFiles(sources)) + { + return 0; + } + for(std::vector::const_iterator i = sources.begin(); i != sources.end(); ++i) { @@ -2808,7 +2818,7 @@ void cmGlobalXCodeGenerator std::string linkObjs; const char* sep = ""; std::vector objs; - this->GetGeneratorTarget(cmtarget)->UseObjectLibraries(objs); + this->GetGeneratorTarget(cmtarget)->UseObjectLibraries(objs, ""); for(std::vector::const_iterator oi = objs.begin(); oi != objs.end(); ++oi) { @@ -2943,8 +2953,10 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root, } std::vector classes; - cmtarget.GetSourceFiles(classes); - + if (!cmtarget.GetConfigCommonSourceFiles(classes)) + { + return; + } // Put cmSourceFile instances in proper groups: for(std::vector::const_iterator s = classes.begin(); s != classes.end(); s++) @@ -2962,7 +2974,7 @@ void cmGlobalXCodeGenerator::CreateGroups(cmLocalGenerator* root, // Put OBJECT_LIBRARY objects in proper groups: std::vector objs; - this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs); + this->GetGeneratorTarget(&cmtarget)->UseObjectLibraries(objs, ""); for(std::vector::const_iterator oi = objs.begin(); oi != objs.end(); ++oi) { diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index c840888a1..dcf9f97eb 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -659,7 +659,8 @@ void cmLocalGenerator::AddBuildTargetRule(const std::string& llang, std::vector objVector; // Add all the sources outputs to the depends of the target std::vector classes; - target.GetSourceFiles(classes); + target.GetSourceFiles(classes, + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); for(std::vector::const_iterator i = classes.begin(); i != classes.end(); ++i) { @@ -1641,7 +1642,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, !(this->Makefile->IsOn("CYGWIN") || this->Makefile->IsOn("MINGW"))) { std::vector sources; - target->GetSourceFiles(sources); + target->GetSourceFiles(sources, buildType); for(std::vector::const_iterator i = sources.begin(); i != sources.end(); ++i) { @@ -1689,7 +1690,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, linkFlags += this->Makefile->GetSafeDefinition(build); linkFlags += " "; } - std::string linkLanguage = target->Target->GetLinkerLanguage(); + std::string linkLanguage = target->Target->GetLinkerLanguage(buildType); if(linkLanguage.empty()) { cmSystemTools::Error diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index ff173f5ba..7ffe84d83 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -200,7 +200,8 @@ GetLocalObjectFiles(std::map &localObjectFiles) continue; } std::vector objectSources; - gt->GetObjectSources(objectSources); + gt->GetObjectSources(objectSources, this->Makefile + ->GetSafeDefinition("CMAKE_BUILD_TYPE")); // Compute full path to object file directory for this target. std::string dir; dir += gt->Makefile->GetCurrentOutputDirectory(); @@ -1262,7 +1263,8 @@ cmLocalUnixMakefileGenerator3 { // Get the set of source languages in the target. std::set languages; - target.GetLanguages(languages); + target.GetLanguages(languages, + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); fout << "\n" << "# Per-language clean rules from dependency scanning.\n" << "foreach(lang"; diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index 11e967949..5db735f30 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -317,7 +317,10 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout, // get the classes from the source lists then add them to the groups std::vector classes; - target.GetSourceFiles(classes); + if (!target.GetConfigCommonSourceFiles(classes)) + { + return; + } // now all of the source files have been properly assigned to the target // now stick them into source groups using the reg expressions @@ -1269,7 +1272,20 @@ void cmLocalVisualStudio6Generator if(targetBuilds) { // Get the language to use for linking. - const std::string& linkLanguage = target.GetLinkerLanguage(); + std::vector configs; + target.GetMakefile()->GetConfigurations(configs); + std::vector::const_iterator it = configs.begin(); + const std::string& linkLanguage = target.GetLinkerLanguage(*it); + for ( ; it != configs.end(); ++it) + { + const std::string& configLinkLanguage = target.GetLinkerLanguage(*it); + if (configLinkLanguage != linkLanguage) + { + cmSystemTools::Error + ("Linker language must not vary by configuration for target: ", + target.GetName().c_str()); + } + } if(linkLanguage.empty()) { cmSystemTools::Error @@ -1691,7 +1707,20 @@ void cmLocalVisualStudio6Generator if(target.GetType() >= cmTarget::EXECUTABLE && target.GetType() <= cmTarget::OBJECT_LIBRARY) { - const std::string& linkLanguage = target.GetLinkerLanguage(); + std::vector configs; + target.GetMakefile()->GetConfigurations(configs); + std::vector::const_iterator it = configs.begin(); + const std::string& linkLanguage = target.GetLinkerLanguage(*it); + for ( ; it != configs.end(); ++it) + { + const std::string& configLinkLanguage = target.GetLinkerLanguage(*it); + if (configLinkLanguage != linkLanguage) + { + cmSystemTools::Error + ("Linker language must not vary by configuration for target: ", + target.GetName().c_str()); + } + } if(linkLanguage.empty()) { cmSystemTools::Error @@ -1889,7 +1918,7 @@ void cmLocalVisualStudio6Generator cmGeneratorTarget* gt = this->GlobalGenerator->GetGeneratorTarget(&target); std::vector objs; - gt->UseObjectLibraries(objs); + gt->UseObjectLibraries(objs, ""); for(std::vector::const_iterator oi = objs.begin(); oi != objs.end(); ++oi) { diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 8bac10d74..47f9826a4 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1330,7 +1330,7 @@ cmLocalVisualStudio7GeneratorInternals cmGeneratorTarget* gt = lg->GetGlobalGenerator()->GetGeneratorTarget(t); std::vector objs; - gt->UseObjectLibraries(objs); + gt->UseObjectLibraries(objs, ""); const char* sep = isep? isep : ""; for(std::vector::const_iterator oi = objs.begin(); oi != objs.end(); ++oi) @@ -1397,7 +1397,10 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, // get the classes from the source lists then add them to the groups this->ModuleDefinitionFile = ""; std::vector classes; - target.GetSourceFiles(classes); + if (!target.GetConfigCommonSourceFiles(classes)) + { + return; + } for(std::vector::const_iterator i = classes.begin(); i != classes.end(); i++) { @@ -1438,7 +1441,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, cmGeneratorTarget* gt = this->GlobalGenerator->GetGeneratorTarget(&target); std::vector objs; - gt->UseObjectLibraries(objs); + gt->UseObjectLibraries(objs, ""); if(!objs.empty()) { // TODO: Separate sub-filter for each object library used? diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 5bb7b8b3c..f940ac4d2 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -128,14 +128,15 @@ void cmMakefileTargetGenerator::CreateRuleFile() //---------------------------------------------------------------------------- void cmMakefileTargetGenerator::WriteTargetBuildRules() { + const std::string& config = + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); + // write the custom commands for this target // Look for files registered for cleaning in this directory. if(const char* additional_clean_files = this->Makefile->GetProperty ("ADDITIONAL_MAKE_CLEAN_FILES")) { - const std::string& config = - this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"); cmListFileBacktrace lfbt; cmGeneratorExpression ge(lfbt); cmsys::auto_ptr cge = @@ -154,7 +155,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() // First generate the object rule files. Save a list of all object // files for this target. std::vector customCommands; - this->GeneratorTarget->GetCustomCommands(customCommands); + this->GeneratorTarget->GetCustomCommands(customCommands, config); for(std::vector::const_iterator si = customCommands.begin(); si != customCommands.end(); ++si) @@ -177,17 +178,17 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() } } std::vector headerSources; - this->GeneratorTarget->GetHeaderSources(headerSources); + this->GeneratorTarget->GetHeaderSources(headerSources, config); this->OSXBundleGenerator->GenerateMacOSXContentStatements( headerSources, this->MacOSXContentGenerator); std::vector extraSources; - this->GeneratorTarget->GetExtraSources(extraSources); + this->GeneratorTarget->GetExtraSources(extraSources, config); this->OSXBundleGenerator->GenerateMacOSXContentStatements( extraSources, this->MacOSXContentGenerator); std::vector externalObjects; - this->GeneratorTarget->GetExternalObjects(externalObjects); + this->GeneratorTarget->GetExternalObjects(externalObjects, config); for(std::vector::const_iterator si = externalObjects.begin(); si != externalObjects.end(); ++si) @@ -195,7 +196,7 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() this->ExternalObjects.push_back((*si)->GetFullPath()); } std::vector objectSources; - this->GeneratorTarget->GetObjectSources(objectSources); + this->GeneratorTarget->GetObjectSources(objectSources, config); for(std::vector::const_iterator si = objectSources.begin(); si != objectSources.end(); ++si) { @@ -344,7 +345,8 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() { // write language flags for target std::set languages; - this->Target->GetLanguages(languages); + this->Target->GetLanguages(languages, + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); // put the compiler in the rules.make file so that if it changes // things rebuild for(std::set::const_iterator l = languages.begin(); @@ -1173,7 +1175,8 @@ cmMakefileTargetGenerator { // Depend on all custom command outputs. std::vector sources; - this->Target->GetSourceFiles(sources); + this->Target->GetSourceFiles(sources, + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); for(std::vector::const_iterator source = sources.begin(); source != sources.end(); ++source) { @@ -1653,7 +1656,8 @@ void cmMakefileTargetGenerator this->AppendTargetDepends(depends); // Add a dependency on the link definitions file, if any. - std::string def = this->GeneratorTarget->GetModuleDefinitionFile(); + std::string def = this->GeneratorTarget->GetModuleDefinitionFile( + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); if(!def.empty()) { depends.push_back(def); @@ -2049,7 +2053,7 @@ void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags) { std::vector includes; const std::string& config = - this->Makefile->GetDefinition("CMAKE_BUILD_TYPE"); + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget, "C", config); @@ -2068,7 +2072,8 @@ void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags) //---------------------------------------------------------------------------- void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags) { - std::string def = this->GeneratorTarget->GetModuleDefinitionFile(); + std::string def = this->GeneratorTarget->GetModuleDefinitionFile( + this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE")); if(def.empty()) { return; diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 20ce2c5ab..1d0336a26 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -111,7 +111,8 @@ void cmNinjaNormalTargetGenerator::WriteLanguagesRules() #endif std::set languages; - this->GetTarget()->GetLanguages(languages); + this->GetTarget()->GetLanguages(languages, + this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE")); for(std::set::const_iterator l = languages.begin(); l != languages.end(); ++l) diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index b7eab7d79..56155efd8 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -485,8 +485,9 @@ cmNinjaTargetGenerator << this->GetTargetName() << "\n\n"; + std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); std::vector customCommands; - this->GeneratorTarget->GetCustomCommands(customCommands); + this->GeneratorTarget->GetCustomCommands(customCommands, config); for(std::vector::const_iterator si = customCommands.begin(); si != customCommands.end(); ++si) @@ -495,17 +496,17 @@ cmNinjaTargetGenerator this->GetLocalGenerator()->AddCustomCommandTarget(cc, this->GetTarget()); } std::vector headerSources; - this->GeneratorTarget->GetHeaderSources(headerSources); + this->GeneratorTarget->GetHeaderSources(headerSources, config); this->OSXBundleGenerator->GenerateMacOSXContentStatements( headerSources, this->MacOSXContentGenerator); std::vector extraSources; - this->GeneratorTarget->GetExtraSources(extraSources); + this->GeneratorTarget->GetExtraSources(extraSources, config); this->OSXBundleGenerator->GenerateMacOSXContentStatements( extraSources, this->MacOSXContentGenerator); std::vector externalObjects; - this->GeneratorTarget->GetExternalObjects(externalObjects); + this->GeneratorTarget->GetExternalObjects(externalObjects, config); for(std::vector::const_iterator si = externalObjects.begin(); si != externalObjects.end(); ++si) @@ -513,13 +514,13 @@ cmNinjaTargetGenerator this->Objects.push_back(this->GetSourceFilePath(*si)); } std::vector objectSources; - this->GeneratorTarget->GetObjectSources(objectSources); + this->GeneratorTarget->GetObjectSources(objectSources, config); for(std::vector::const_iterator si = objectSources.begin(); si != objectSources.end(); ++si) { this->WriteObjectBuildStatement(*si); } - std::string def = this->GeneratorTarget->GetModuleDefinitionFile(); + std::string def = this->GeneratorTarget->GetModuleDefinitionFile(config); if(!def.empty()) { this->ModuleDefinitionFile = this->ConvertToNinjaPath(def.c_str()); @@ -565,7 +566,8 @@ cmNinjaTargetGenerator // Add order-only dependencies on custom command outputs. std::vector customCommands; - this->GeneratorTarget->GetCustomCommands(customCommands); + std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); + this->GeneratorTarget->GetCustomCommands(customCommands, config); for(std::vector::const_iterator si = customCommands.begin(); si != customCommands.end(); ++si) diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 0fb40c043..f5d18dc88 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -46,7 +46,9 @@ void cmNinjaUtilityTargetGenerator::Generate() } std::vector sources; - this->GetTarget()->GetSourceFiles(sources); + std::string config = this->GetMakefile() + ->GetSafeDefinition("CMAKE_BUILD_TYPE"); + this->GetTarget()->GetSourceFiles(sources, config); for(std::vector::const_iterator source = sources.begin(); source != sources.end(); ++source) { diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 71c4630e0..ae11462e7 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -472,7 +472,7 @@ void cmQtAutoGenerators::SetupSourceFiles(cmTarget const* target) const char* sepHeaders = ""; std::vector srcFiles; - target->GetSourceFiles(srcFiles); + target->GetConfigCommonSourceFiles(srcFiles); const char *skipMocSep = ""; const char *skipUicSep = ""; @@ -862,7 +862,7 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target) cmMakefile *makefile = target->GetMakefile(); std::vector srcFiles; - target->GetSourceFiles(srcFiles); + target->GetConfigCommonSourceFiles(srcFiles); std::string rccFileFiles; std::string rccFileOptions; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 573b816ed..a87ec3124 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -159,10 +159,13 @@ public: CachedLinkInterfaceCompileOptionsEntries; mutable std::map > CachedLinkInterfaceCompileDefinitionsEntries; + mutable std::map > + CachedLinkInterfaceSourcesEntries; mutable std::map CacheLinkInterfaceIncludeDirectoriesDone; mutable std::map CacheLinkInterfaceCompileDefinitionsDone; mutable std::map CacheLinkInterfaceCompileOptionsDone; + mutable std::map CacheLinkInterfaceSourcesDone; }; //---------------------------------------------------------------------------- @@ -198,6 +201,7 @@ cmTargetInternals::~cmTargetInternals() deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries); deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries); deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries); + deleteAndClear(this->CachedLinkInterfaceSourcesEntries); } //---------------------------------------------------------------------------- @@ -220,6 +224,7 @@ cmTarget::cmTarget() this->DebugIncludesDone = false; this->DebugCompileOptionsDone = false; this->DebugCompileDefinitionsDone = false; + this->DebugSourcesDone = false; } //---------------------------------------------------------------------------- @@ -543,47 +548,253 @@ bool cmTarget::IsBundleOnApple() const } //---------------------------------------------------------------------------- -void cmTarget::GetSourceFiles(std::vector &files) const +static void processSources(cmTarget const* tgt, + const std::vector &entries, + std::vector &srcs, + std::set &uniqueSrcs, + cmGeneratorExpressionDAGChecker *dagChecker, + cmTarget const* head, + std::string const& config, bool debugSources) { - assert(this->GetType() != INTERFACE_LIBRARY); - for(std::vector::const_iterator - si = this->Internal->SourceEntries.begin(); - si != this->Internal->SourceEntries.end(); ++si) - { - std::vector srcs; - cmSystemTools::ExpandListArgument((*si)->ge->Evaluate(this->Makefile, - "", - false, - this), - srcs); + cmMakefile *mf = tgt->GetMakefile(); - for(std::vector::const_iterator i = srcs.begin(); - i != srcs.end(); ++i) + for (std::vector::const_iterator + it = entries.begin(), end = entries.end(); it != end; ++it) + { + bool cacheSources = false; + std::vector entrySources = (*it)->CachedEntries; + if(entrySources.empty()) { - std::string src = *i; - cmSourceFile* sf = this->Makefile->GetOrCreateSource(src); - std::string e; - src = sf->GetFullPath(&e); - if(src.empty()) + cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf, + config, + false, + head ? head : tgt, + tgt, + dagChecker), + entrySources); + if (mf->IsGeneratingBuildSystem() + && !(*it)->ge->GetHadContextSensitiveCondition()) { - if(!e.empty()) - { - cmake* cm = this->Makefile->GetCMakeInstance(); - cm->IssueMessage(cmake::FATAL_ERROR, e, - this->GetBacktrace()); - } - return; + cacheSources = true; } - files.push_back(src); + + for(std::vector::iterator i = entrySources.begin(); + i != entrySources.end(); ++i) + { + std::string& src = *i; + + cmSourceFile* sf = mf->GetOrCreateSource(src); + std::string e; + src = sf->GetFullPath(&e); + if(src.empty()) + { + if(!e.empty()) + { + cmake* cm = mf->GetCMakeInstance(); + cm->IssueMessage(cmake::FATAL_ERROR, e, + tgt->GetBacktrace()); + } + return; + } + } + if (cacheSources) + { + (*it)->CachedEntries = entrySources; + } + } + std::string usedSources; + for(std::vector::iterator + li = entrySources.begin(); li != entrySources.end(); ++li) + { + std::string src = *li; + + if(uniqueSrcs.insert(src).second) + { + srcs.push_back(src); + if (debugSources) + { + usedSources += " * " + src + "\n"; + } + } + } + if (!usedSources.empty()) + { + mf->GetCMakeInstance()->IssueMessage(cmake::LOG, + std::string("Used sources for target ") + + tgt->GetName() + ":\n" + + usedSources, (*it)->ge->GetBacktrace()); } } } //---------------------------------------------------------------------------- -void cmTarget::GetSourceFiles(std::vector &files) const +void cmTarget::GetSourceFiles(std::vector &files, + const std::string& config, + cmTarget const* head) const +{ + assert(this->GetType() != INTERFACE_LIBRARY); + + std::vector debugProperties; + const char *debugProp = + this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); + if (debugProp) + { + cmSystemTools::ExpandListArgument(debugProp, debugProperties); + } + + bool debugSources = !this->DebugSourcesDone + && std::find(debugProperties.begin(), + debugProperties.end(), + "SOURCES") + != debugProperties.end(); + + if (this->Makefile->IsGeneratingBuildSystem()) + { + this->DebugSourcesDone = true; + } + + cmListFileBacktrace lfbt; + + cmGeneratorExpressionDAGChecker dagChecker(lfbt, + this->GetName(), + "SOURCES", 0, 0); + + std::set uniqueSrcs; + processSources(this, + this->Internal->SourceEntries, + files, + uniqueSrcs, + &dagChecker, + head, + config, + debugSources); + + if (!this->Internal->CacheLinkInterfaceSourcesDone[config]) + { + for (std::vector::const_iterator + it = this->Internal->LinkImplementationPropertyEntries.begin(), + end = this->Internal->LinkImplementationPropertyEntries.end(); + it != end; ++it) + { + if (!cmGeneratorExpression::IsValidTargetName(it->Value) + && cmGeneratorExpression::Find(it->Value) == std::string::npos) + { + continue; + } + { + cmGeneratorExpression ge(lfbt); + cmsys::auto_ptr cge = + ge.Parse(it->Value); + std::string targetResult = cge->Evaluate(this->Makefile, config, + false, this, 0, &dagChecker); + if (!this->Makefile->FindTargetToUse(targetResult)) + { + continue; + } + } + std::string sourceGenex = "$Value + ",INTERFACE_SOURCES>"; + if (cmGeneratorExpression::Find(it->Value) != std::string::npos) + { + // Because it->Value is a generator expression, ensure that it + // evaluates to the non-empty string before being used in the + // TARGET_PROPERTY expression. + sourceGenex = "$<$Value + ">:" + sourceGenex + ">"; + } + cmGeneratorExpression ge(it->Backtrace); + cmsys::auto_ptr cge = ge.Parse( + sourceGenex); + + this->Internal + ->CachedLinkInterfaceSourcesEntries[config].push_back( + new cmTargetInternals::TargetPropertyEntry(cge, + it->Value)); + } + } + + processSources(this, + this->Internal->CachedLinkInterfaceSourcesEntries[config], + files, + uniqueSrcs, + &dagChecker, + head, + config, + debugSources); + + if (!this->Makefile->IsGeneratingBuildSystem()) + { + deleteAndClear(this->Internal->CachedLinkInterfaceSourcesEntries); + } + else + { + this->Internal->CacheLinkInterfaceSourcesDone[config] = true; + } +} + +//---------------------------------------------------------------------------- +bool +cmTarget::GetConfigCommonSourceFiles(std::vector& files) const +{ + std::vector configs; + this->Makefile->GetConfigurations(configs); + if (configs.empty()) + { + configs.push_back(""); + } + + std::vector::const_iterator it = configs.begin(); + const std::string& firstConfig = *it; + this->GetSourceFiles(files, firstConfig); + + for ( ; it != configs.end(); ++it) + { + std::vector configFiles; + this->GetSourceFiles(configFiles, *it); + if (configFiles != files) + { + std::string firstConfigFiles; + const char* sep = ""; + for (std::vector::const_iterator fi = files.begin(); + fi != files.end(); ++fi) + { + firstConfigFiles += sep; + firstConfigFiles += (*fi)->GetFullPath(); + sep = "\n "; + } + + std::string thisConfigFiles; + sep = ""; + for (std::vector::const_iterator fi = configFiles.begin(); + fi != configFiles.end(); ++fi) + { + thisConfigFiles += sep; + thisConfigFiles += (*fi)->GetFullPath(); + sep = "\n "; + } + cmOStringStream e; + e << "Target \"" << this->Name << "\" has source files which vary by " + "configuration. This is not supported by the \"" + << this->Makefile->GetLocalGenerator() + ->GetGlobalGenerator()->GetName() + << "\" generator.\n" + "Config \"" << firstConfig << "\":\n" + " " << firstConfigFiles << "\n" + "Config \"" << *it << "\":\n" + " " << thisConfigFiles << "\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; + } + } + return true; +} + +//---------------------------------------------------------------------------- +void cmTarget::GetSourceFiles(std::vector &files, + const std::string& config, + cmTarget const* head) const { std::vector srcs; - this->GetSourceFiles(srcs); + this->GetSourceFiles(srcs, config, head); std::set emitted; @@ -1487,6 +1698,25 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->LinkImplementationPropertyEntries.push_back(entry); return; } + if (prop == "SOURCES") + { + if(this->IsImported()) + { + cmOStringStream e; + e << "SOURCES property can't be set on imported targets (\"" + << this->Name << "\")\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + this->Internal->SourceEntries.clear(); + cmsys::auto_ptr cge = ge.Parse(value); + this->Internal->SourceEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(cge)); + return; + } this->Properties.SetProperty(prop, value, cmProperty::TARGET); this->MaybeInvalidatePropertyCache(prop); } @@ -1554,6 +1784,25 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, this->Internal->LinkImplementationPropertyEntries.push_back(entry); return; } + if (prop == "SOURCES") + { + if(this->IsImported()) + { + cmOStringStream e; + e << "SOURCES property can't be set on imported targets (\"" + << this->Name << "\")\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + + cmListFileBacktrace lfbt; + this->Makefile->GetBacktrace(lfbt); + cmGeneratorExpression ge(lfbt); + cmsys::auto_ptr cge = ge.Parse(value); + this->Internal->SourceEntries.push_back( + new cmTargetInternals::TargetPropertyEntry(cge)); + return; + } this->Properties.AppendProperty(prop, value, cmProperty::TARGET, asString); this->MaybeInvalidatePropertyCache(prop); } @@ -4994,10 +5243,12 @@ bool cmTarget::IsLinkInterfaceDependentNumberMaxProperty(const std::string &p, } //---------------------------------------------------------------------------- -void cmTarget::GetLanguages(std::set& languages) const +void cmTarget::GetLanguages(std::set& languages, + const std::string& config, + cmTarget const* head) const { std::vector sourceFiles; - this->GetSourceFiles(sourceFiles); + this->GetSourceFiles(sourceFiles, config, head); for(std::vector::const_iterator i = sourceFiles.begin(); i != sourceFiles.end(); ++i) { @@ -5038,7 +5289,7 @@ void cmTarget::GetLanguages(std::set& languages) const cmGeneratorTarget* gt = this->Makefile->GetLocalGenerator() ->GetGlobalGenerator() ->GetGeneratorTarget(this); - gt->GetExternalObjects(externalObjects); + gt->GetExternalObjects(externalObjects, config); for(std::vector::const_iterator i = externalObjects.begin(); i != externalObjects.end(); ++i) { @@ -5052,7 +5303,7 @@ void cmTarget::GetLanguages(std::set& languages) const for(std::vector::const_iterator i = objectLibraries.begin(); i != objectLibraries.end(); ++i) { - (*i)->GetLanguages(languages); + (*i)->GetLanguages(languages, config, head); } } @@ -5991,7 +6242,7 @@ cmTarget::GetLinkImplementation(const std::string& config, // Compute the link implementation for this configuration. LinkImplementation impl; this->ComputeLinkImplementation(config, impl, head); - this->ComputeLinkImplementationLanguages(impl); + this->ComputeLinkImplementationLanguages(config, impl, head); // Store the information for this configuration. cmTargetInternals::LinkImplMapType::value_type entry(key, impl); @@ -5999,7 +6250,7 @@ cmTarget::GetLinkImplementation(const std::string& config, } else if (i->second.Languages.empty()) { - this->ComputeLinkImplementationLanguages(i->second); + this->ComputeLinkImplementationLanguages(config, i->second, head); } return &i->second; @@ -6112,12 +6363,14 @@ void cmTarget::ComputeLinkImplementation(const std::string& config, //---------------------------------------------------------------------------- void -cmTarget::ComputeLinkImplementationLanguages(LinkImplementation& impl) const +cmTarget::ComputeLinkImplementationLanguages(const std::string& config, + LinkImplementation& impl, + cmTarget const* head) const { // This target needs runtime libraries for its source languages. std::set languages; // Get languages used in our source files. - this->GetLanguages(languages); + this->GetLanguages(languages, config, head); // Copy the set of langauges to the link implementation. for(std::set::iterator li = languages.begin(); li != languages.end(); ++li) diff --git a/Source/cmTarget.h b/Source/cmTarget.h index fcbff93a9..055e029a2 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -135,8 +135,13 @@ public: /** * Get the list of the source files used by this target */ - void GetSourceFiles(std::vector &files) const; - void GetSourceFiles(std::vector &files) const; + void GetSourceFiles(std::vector &files, + const std::string& config, + cmTarget const* head = 0) const; + void GetSourceFiles(std::vector &files, + const std::string& config, + cmTarget const* head = 0) const; + bool GetConfigCommonSourceFiles(std::vector& files) const; /** * Add sources to the target. @@ -465,7 +470,9 @@ public: // when source file properties are changed and we do not have enough // information to forward these property changes to the targets // until we have per-target object file properties. - void GetLanguages(std::set& languages) const; + void GetLanguages(std::set& languages, + std::string const& config, + cmTarget const* head = 0) const; /** Return whether this target is an executable with symbol exports enabled. */ @@ -703,6 +710,7 @@ private: mutable std::map DebugCompatiblePropertiesDone; mutable bool DebugCompileOptionsDone; mutable bool DebugCompileDefinitionsDone; + mutable bool DebugSourcesDone; mutable std::set LinkImplicitNullProperties; bool BuildInterfaceIncludesAppended; @@ -738,7 +746,9 @@ private: void ComputeLinkImplementation(const std::string& config, LinkImplementation& impl, cmTarget const* head) const; - void ComputeLinkImplementationLanguages(LinkImplementation& impl) const; + void ComputeLinkImplementationLanguages(const std::string& config, + LinkImplementation& impl, + cmTarget const* head) const; void ComputeLinkClosure(const std::string& config, LinkClosure& lc, cmTarget const* head) const; diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx new file mode 100644 index 000000000..e82b36d51 --- /dev/null +++ b/Source/cmTargetSourcesCommand.cxx @@ -0,0 +1,64 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Stephen Kelly + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ +#include "cmTargetSourcesCommand.h" + +#include "cmGeneratorExpression.h" + +//---------------------------------------------------------------------------- +bool cmTargetSourcesCommand +::InitialPass(std::vector const& args, cmExecutionStatus &) +{ + return this->HandleArguments(args, "SOURCES"); +} + +//---------------------------------------------------------------------------- +void cmTargetSourcesCommand +::HandleImportedTarget(const std::string &tgt) +{ + cmOStringStream e; + e << "Cannot specify sources for imported target \"" + << tgt << "\"."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +//---------------------------------------------------------------------------- +void cmTargetSourcesCommand +::HandleMissingTarget(const std::string &name) +{ + cmOStringStream e; + e << "Cannot specify sources for target \"" << name << "\" " + "which is not built by this project."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); +} + +//---------------------------------------------------------------------------- +std::string cmTargetSourcesCommand +::Join(const std::vector &content) +{ + std::string srcs; + std::string sep; + for(std::vector::const_iterator it = content.begin(); + it != content.end(); ++it) + { + srcs += sep + *it; + sep = ";"; + } + return srcs; +} + +//---------------------------------------------------------------------------- +void cmTargetSourcesCommand +::HandleDirectContent(cmTarget *tgt, const std::vector &content, + bool, bool) +{ + tgt->AppendProperty("SOURCES", this->Join(content).c_str()); +} diff --git a/Source/cmTargetSourcesCommand.h b/Source/cmTargetSourcesCommand.h new file mode 100644 index 000000000..dae78c490 --- /dev/null +++ b/Source/cmTargetSourcesCommand.h @@ -0,0 +1,55 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2014 Stephen Kelly + + Distributed under the OSI-approved BSD License (the "License"); + see accompanying file Copyright.txt for details. + + This software is distributed WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the License for more information. +============================================================================*/ + +#ifndef cmTargetSourcesCommand_h +#define cmTargetSourcesCommand_h + +#include "cmTargetPropCommandBase.h" + +//---------------------------------------------------------------------------- +class cmTargetSourcesCommand : public cmTargetPropCommandBase +{ +public: + /** + * This is a virtual constructor for the command. + */ + virtual cmCommand* Clone() + { + return new cmTargetSourcesCommand; + } + + /** + * This is called when the command is first encountered in + * the CMakeLists.txt file. + */ + virtual bool InitialPass(std::vector const& args, + cmExecutionStatus &status); + + /** + * The name of the command as specified in CMakeList.txt. + */ + virtual std::string GetName() const { return "target_sources";} + + cmTypeMacro(cmTargetSourcesCommand, cmTargetPropCommandBase); + +private: + virtual void HandleImportedTarget(const std::string &tgt); + virtual void HandleMissingTarget(const std::string &name); + + virtual void HandleDirectContent(cmTarget *tgt, + const std::vector &content, + bool prepend, bool system); + + virtual std::string Join(const std::vector &content); +}; + +#endif diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 8d10e7c66..a999b2d46 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -379,7 +379,7 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences() void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup() { std::vector resxObjs; - this->GeneratorTarget->GetResxSources(resxObjs); + this->GeneratorTarget->GetResxSources(resxObjs, ""); if(!resxObjs.empty()) { this->WriteString("\n", 1); @@ -553,7 +553,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommands() { this->SourcesVisited.clear(); std::vector customCommands; - this->GeneratorTarget->GetCustomCommands(customCommands); + this->GeneratorTarget->GetCustomCommands(customCommands, ""); for(std::vector::const_iterator si = customCommands.begin(); si != customCommands.end(); ++si) @@ -704,7 +704,10 @@ void cmVisualStudio10TargetGenerator::WriteGroups() std::vector sourceGroups = this->Makefile->GetSourceGroups(); std::vector classes; - this->Target->GetSourceFiles(classes); + if (!this->Target->GetConfigCommonSourceFiles(classes)) + { + return; + } std::set groupsUsed; for(std::vector::const_iterator s = classes.begin(); @@ -749,7 +752,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() } std::vector resxObjs; - this->GeneratorTarget->GetResxSources(resxObjs); + this->GeneratorTarget->GetResxSources(resxObjs, ""); if(!resxObjs.empty()) { this->WriteString("\n", 1); @@ -768,7 +771,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() // Add object library contents as external objects. std::vector objs; - this->GeneratorTarget->UseObjectLibraries(objs); + this->GeneratorTarget->UseObjectLibraries(objs, ""); if(!objs.empty()) { this->WriteString("\n", 1); @@ -1005,14 +1008,14 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() this->WriteString("\n", 1); std::vector headerSources; - this->GeneratorTarget->GetHeaderSources(headerSources); + this->GeneratorTarget->GetHeaderSources(headerSources, ""); this->WriteSources("ClInclude", headerSources); std::vector idlSources; - this->GeneratorTarget->GetIDLSources(idlSources); + this->GeneratorTarget->GetIDLSources(idlSources, ""); this->WriteSources("Midl", idlSources); std::vector objectSources; - this->GeneratorTarget->GetObjectSources(objectSources); + this->GeneratorTarget->GetObjectSources(objectSources, ""); for(std::vector::const_iterator si = objectSources.begin(); si != objectSources.end(); ++si) @@ -1053,7 +1056,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() } std::vector externalObjects; - this->GeneratorTarget->GetExternalObjects(externalObjects); + this->GeneratorTarget->GetExternalObjects(externalObjects, ""); for(std::vector::iterator si = externalObjects.begin(); si != externalObjects.end(); ) @@ -1088,12 +1091,12 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() } std::vector extraSources; - this->GeneratorTarget->GetExtraSources(extraSources); + this->GeneratorTarget->GetExtraSources(extraSources, ""); this->WriteSources("None", extraSources); // Add object library contents as external objects. std::vector objs; - this->GeneratorTarget->UseObjectLibraries(objs); + this->GeneratorTarget->UseObjectLibraries(objs, ""); for(std::vector::const_iterator oi = objs.begin(); oi != objs.end(); ++oi) { @@ -1694,7 +1697,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config) linkOptions.AddFlag("ImportLibrary", imLib.c_str()); linkOptions.AddFlag("ProgramDataBaseFile", pdb.c_str()); linkOptions.Parse(flags.c_str()); - std::string def = this->GeneratorTarget->GetModuleDefinitionFile(); + std::string def = this->GeneratorTarget->GetModuleDefinitionFile(""); if(!def.empty()) { linkOptions.AddFlag("ModuleDefinitionFile", def.c_str()); @@ -1924,7 +1927,7 @@ bool cmVisualStudio10TargetGenerator:: IsResxHeader(const std::string& headerFile) { std::set expectedResxHeaders; - this->GeneratorTarget->GetExpectedResxHeaders(expectedResxHeaders); + this->GeneratorTarget->GetExpectedResxHeaders(expectedResxHeaders, ""); std::set::const_iterator it = expectedResxHeaders.find(headerFile); diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 726e79022..1c474ab13 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -278,6 +278,11 @@ if(BUILD_TESTING) ADD_TEST_MACRO(AliasTarget AliasTarget) ADD_TEST_MACRO(StagingPrefix StagingPrefix) ADD_TEST_MACRO(InterfaceLibrary InterfaceLibrary) + if (CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]") + set(ConfigSources_BUILD_OPTIONS -DCMAKE_BUILD_TYPE=Debug) + ADD_TEST_MACRO(ConfigSources ConfigSources) + endif() + ADD_TEST_MACRO(SourcesProperty SourcesProperty) set_tests_properties(EmptyLibrary PROPERTIES PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target: test") ADD_TEST_MACRO(CrossCompile CrossCompile) diff --git a/Tests/ConfigSources/CMakeLists.txt b/Tests/ConfigSources/CMakeLists.txt new file mode 100644 index 000000000..c272257ca --- /dev/null +++ b/Tests/ConfigSources/CMakeLists.txt @@ -0,0 +1,17 @@ + +cmake_minimum_required(VERSION 3.0) + +project(ConfigSources) + +add_library(iface INTERFACE) +set_property(TARGET iface PROPERTY INTERFACE_SOURCES + iface_src.cpp + $<$:iface_debug_src.cpp> + $<$:does_not_exist.cpp> +) + +add_executable(ConfigSources + $<$:main.cpp> + $<$:does_not_exist.cpp> +) +target_link_libraries(ConfigSources iface) diff --git a/Tests/ConfigSources/iface_debug.h b/Tests/ConfigSources/iface_debug.h new file mode 100644 index 000000000..a23d7374b --- /dev/null +++ b/Tests/ConfigSources/iface_debug.h @@ -0,0 +1,4 @@ + +int iface_src(); + +int iface_debug(); diff --git a/Tests/ConfigSources/iface_debug_src.cpp b/Tests/ConfigSources/iface_debug_src.cpp new file mode 100644 index 000000000..63b22fcd1 --- /dev/null +++ b/Tests/ConfigSources/iface_debug_src.cpp @@ -0,0 +1,7 @@ + +#include "iface_debug.h" + +int iface_debug() +{ + return 0; +} diff --git a/Tests/ConfigSources/iface_src.cpp b/Tests/ConfigSources/iface_src.cpp new file mode 100644 index 000000000..c3a0c8f1e --- /dev/null +++ b/Tests/ConfigSources/iface_src.cpp @@ -0,0 +1,5 @@ + +int iface_src() +{ + return 0; +} diff --git a/Tests/ConfigSources/main.cpp b/Tests/ConfigSources/main.cpp new file mode 100644 index 000000000..71af72f70 --- /dev/null +++ b/Tests/ConfigSources/main.cpp @@ -0,0 +1,7 @@ + +#include "iface_debug.h" + +int main(int argc, char** argv) +{ + return iface_src() + iface_debug(); +} diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index d2116aa92..39736539b 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -64,9 +64,15 @@ add_custom_command( DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/myotherinterface.h.in" ) +message("CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}") +if (CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]" AND NOT CMAKE_CONFIGURATION_TYPES) + set(debug_srcs "$<$:debug_class.cpp>" $<$:debug_resource.qrc>) + add_definitions(-DTEST_DEBUG_CLASS) +endif() + add_executable(QtAutogen main.cpp calwidget.cpp second_widget.cpp foo.cpp blub.cpp bar.cpp abc.cpp xyz.cpp yaf.cpp gadget.cpp $ - test.qrc second_resource.qrc resourcetester.cpp generated.cpp + test.qrc second_resource.qrc resourcetester.cpp generated.cpp ${debug_srcs} ) set_property(TARGET QtAutogen APPEND PROPERTY AUTOGEN_TARGET_DEPENDS generate_moc_input "${CMAKE_CURRENT_BINARY_DIR}/myotherinterface.h") diff --git a/Tests/QtAutogen/debug_class.cpp b/Tests/QtAutogen/debug_class.cpp new file mode 100644 index 000000000..58e72e46c --- /dev/null +++ b/Tests/QtAutogen/debug_class.cpp @@ -0,0 +1,9 @@ + +#include "debug_class.h" +#include "ui_debug_class.h" + +DebugClass::DebugClass(QWidget *parent) + : QWidget(parent), ui(new Ui::DebugClass) +{ + ui->setupUi(this); +} diff --git a/Tests/QtAutogen/debug_class.h b/Tests/QtAutogen/debug_class.h new file mode 100644 index 000000000..71bc1045a --- /dev/null +++ b/Tests/QtAutogen/debug_class.h @@ -0,0 +1,20 @@ + +#include + +namespace Ui +{ +class DebugClass; +} + +class DebugClass : public QWidget +{ + Q_OBJECT +public: + explicit DebugClass(QWidget *parent = 0); + +signals: + void someSignal(); + +private: + Ui::DebugClass *ui; +}; diff --git a/Tests/QtAutogen/debug_class.ui b/Tests/QtAutogen/debug_class.ui new file mode 100644 index 000000000..dc2e1ac18 --- /dev/null +++ b/Tests/QtAutogen/debug_class.ui @@ -0,0 +1,45 @@ + + + DebugClass + + + + 0 + 0 + 400 + 300 + + + + DebugClass + + + + + 50 + 20 + 82 + 21 + + + + CheckBox + + + + + + 40 + 70 + 94 + 24 + + + + PushButton + + + + + + diff --git a/Tests/QtAutogen/debug_resource.qrc b/Tests/QtAutogen/debug_resource.qrc new file mode 100644 index 000000000..db98b9bc1 --- /dev/null +++ b/Tests/QtAutogen/debug_resource.qrc @@ -0,0 +1,5 @@ + + + debug_class.ui + + diff --git a/Tests/QtAutogen/main.cpp b/Tests/QtAutogen/main.cpp index c8a036e2b..eb596650e 100644 --- a/Tests/QtAutogen/main.cpp +++ b/Tests/QtAutogen/main.cpp @@ -51,6 +51,11 @@ #include "yaf.h" #include "libC.h" #include "resourcetester.h" +#ifdef TEST_DEBUG_CLASS +#include "debug_class.h" +#include +#endif + int main(int argv, char **args) { @@ -81,5 +86,9 @@ int main(int argv, char **args) QTimer::singleShot(0, &rt, SLOT(doTest())); +#ifdef TEST_DEBUG_CLASS + std::cout << DebugClass::staticMetaObject.className() << std::endl; +#endif + return app.exec(); } diff --git a/Tests/QtAutogen/resourcetester.cpp b/Tests/QtAutogen/resourcetester.cpp index 0c64d80af..043ec75fc 100644 --- a/Tests/QtAutogen/resourcetester.cpp +++ b/Tests/QtAutogen/resourcetester.cpp @@ -18,6 +18,10 @@ void ResourceTester::doTest() qApp->exit(EXIT_FAILURE); if (!QFile::exists(":/main.cpp")) qApp->exit(EXIT_FAILURE); +#ifdef TEST_DEBUG_CLASS + if (!QFile::exists(":/debug_class.ui")) + qApp->exit(EXIT_FAILURE); +#endif QTimer::singleShot(0, qApp, SLOT(quit())); } diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 4f059d65f..851de429d 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -51,6 +51,7 @@ add_RunCMake_test(TargetPropertyGeneratorExpressions) add_RunCMake_test(Languages) add_RunCMake_test(ObjectLibrary) add_RunCMake_test(TargetObjects) +add_RunCMake_test(TargetSources) add_RunCMake_test(find_dependency) if(NOT WIN32) add_RunCMake_test(PositionIndependentCode) diff --git a/Tests/RunCMake/TargetSources/CMakeLists.txt b/Tests/RunCMake/TargetSources/CMakeLists.txt new file mode 100644 index 000000000..12cd3c775 --- /dev/null +++ b/Tests/RunCMake/TargetSources/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 2.8.4) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/TargetSources/ConfigNotAllowed-result.txt b/Tests/RunCMake/TargetSources/ConfigNotAllowed-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/TargetSources/ConfigNotAllowed-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/TargetSources/ConfigNotAllowed-stderr.txt b/Tests/RunCMake/TargetSources/ConfigNotAllowed-stderr.txt new file mode 100644 index 000000000..1de5dd72e --- /dev/null +++ b/Tests/RunCMake/TargetSources/ConfigNotAllowed-stderr.txt @@ -0,0 +1,14 @@ +CMake Error in CMakeLists.txt: + Target "somelib" has source files which vary by configuration. This is not + supported by the "[^"]+" generator. + + Config "Debug": + + .*/Tests/RunCMake/TargetSources/empty_1.cpp + .*/Tests/RunCMake/TargetSources/empty_2.cpp + .*/Tests/RunCMake/TargetSources/CMakeLists.txt + + Config "Release": + + .*/Tests/RunCMake/TargetSources/empty_1.cpp + .*/Tests/RunCMake/TargetSources/CMakeLists.txt diff --git a/Tests/RunCMake/TargetSources/ConfigNotAllowed.cmake b/Tests/RunCMake/TargetSources/ConfigNotAllowed.cmake new file mode 100644 index 000000000..02af37972 --- /dev/null +++ b/Tests/RunCMake/TargetSources/ConfigNotAllowed.cmake @@ -0,0 +1,2 @@ + +add_library(somelib empty_1.cpp $<$:empty_2.cpp>) diff --git a/Tests/RunCMake/TargetSources/OriginDebug-result.txt b/Tests/RunCMake/TargetSources/OriginDebug-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/TargetSources/OriginDebug-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/TargetSources/OriginDebug-stderr.txt b/Tests/RunCMake/TargetSources/OriginDebug-stderr.txt new file mode 100644 index 000000000..0200dcb09 --- /dev/null +++ b/Tests/RunCMake/TargetSources/OriginDebug-stderr.txt @@ -0,0 +1,31 @@ +CMake Debug Log at OriginDebug.cmake:13 \(add_library\): + Used sources for target OriginDebug: + + \* .*Tests/RunCMake/TargetSources/empty_2.cpp + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Debug Log at OriginDebug.cmake:16 \(set_property\): + Used sources for target OriginDebug: + + \* .*Tests/RunCMake/TargetSources/empty_3.cpp + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Debug Log at OriginDebug.cmake:20 \(target_sources\): + Used sources for target OriginDebug: + + \* .*Tests/RunCMake/TargetSources/empty_4.cpp + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) ++ +CMake Debug Log at OriginDebug.cmake:14 \(target_link_libraries\): + Used sources for target OriginDebug: + + \* .*Tests/RunCMake/TargetSources/empty_1.cpp + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/TargetSources/OriginDebug.cmake b/Tests/RunCMake/TargetSources/OriginDebug.cmake new file mode 100644 index 000000000..5fe9ba75b --- /dev/null +++ b/Tests/RunCMake/TargetSources/OriginDebug.cmake @@ -0,0 +1,20 @@ + +cmake_minimum_required(VERSION 3.0) + +project(OriginDebug) + +set(CMAKE_DEBUG_TARGET_PROPERTIES SOURCES) + +add_library(iface INTERFACE) +set_property(TARGET iface PROPERTY INTERFACE_SOURCES + empty_1.cpp +) + +add_library(OriginDebug empty_2.cpp) +target_link_libraries(OriginDebug iface) + +set_property(TARGET OriginDebug APPEND PROPERTY SOURCES + empty_3.cpp +) + +target_sources(OriginDebug PRIVATE empty_4.cpp) diff --git a/Tests/RunCMake/TargetSources/OriginDebugIDE-result.txt b/Tests/RunCMake/TargetSources/OriginDebugIDE-result.txt new file mode 100644 index 000000000..573541ac9 --- /dev/null +++ b/Tests/RunCMake/TargetSources/OriginDebugIDE-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/TargetSources/OriginDebugIDE-stderr.txt b/Tests/RunCMake/TargetSources/OriginDebugIDE-stderr.txt new file mode 100644 index 000000000..fad7073c6 --- /dev/null +++ b/Tests/RunCMake/TargetSources/OriginDebugIDE-stderr.txt @@ -0,0 +1,40 @@ +CMake Debug Log at OriginDebug.cmake:13 \(add_library\): + Used sources for target OriginDebug: + + \* .*Tests/RunCMake/TargetSources/empty_2.cpp + +Call Stack \(most recent call first\): + OriginDebugIDE.cmake:4 \(include\) + CMakeLists.txt:3 \(include\) ++ +CMake Debug Log at OriginDebug.cmake:16 \(set_property\): + Used sources for target OriginDebug: + + \* .*Tests/RunCMake/TargetSources/empty_3.cpp + +Call Stack \(most recent call first\): + OriginDebugIDE.cmake:4 \(include\) + CMakeLists.txt:3 \(include\) ++ +CMake Debug Log at OriginDebug.cmake:20 \(target_sources\): + Used sources for target OriginDebug: + + \* .*Tests/RunCMake/TargetSources/empty_4.cpp + +Call Stack \(most recent call first\): + OriginDebugIDE.cmake:4 \(include\) + CMakeLists.txt:3 \(include\) ++ +CMake Debug Log: + Used sources for target OriginDebug: + + * .*CMakeLists.txt ++ +CMake Debug Log at OriginDebug.cmake:14 \(target_link_libraries\): + Used sources for target OriginDebug: + + \* .*Tests/RunCMake/TargetSources/empty_1.cpp + +Call Stack \(most recent call first\): + OriginDebugIDE.cmake:4 \(include\) + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/TargetSources/OriginDebugIDE.cmake b/Tests/RunCMake/TargetSources/OriginDebugIDE.cmake new file mode 100644 index 000000000..a3cc3a8ed --- /dev/null +++ b/Tests/RunCMake/TargetSources/OriginDebugIDE.cmake @@ -0,0 +1,4 @@ + +# Separate test for the IDEs, because they show the CMakeLists.txt file +# as a source file. +include(${CMAKE_CURRENT_LIST_DIR}/OriginDebug.cmake) diff --git a/Tests/RunCMake/TargetSources/RunCMakeTest.cmake b/Tests/RunCMake/TargetSources/RunCMakeTest.cmake new file mode 100644 index 000000000..b9095f9b5 --- /dev/null +++ b/Tests/RunCMake/TargetSources/RunCMakeTest.cmake @@ -0,0 +1,9 @@ +include(RunCMake) + +if(RunCMake_GENERATOR MATCHES Xcode + OR RunCMake_GENERATOR MATCHES "Visual Studio") + run_cmake(ConfigNotAllowed) + run_cmake(OriginDebugIDE) +else() + run_cmake(OriginDebug) +endif() diff --git a/Tests/RunCMake/TargetSources/empty_1.cpp b/Tests/RunCMake/TargetSources/empty_1.cpp new file mode 100644 index 000000000..bfbbddeb9 --- /dev/null +++ b/Tests/RunCMake/TargetSources/empty_1.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty() +{ + return 0; +} diff --git a/Tests/RunCMake/TargetSources/empty_2.cpp b/Tests/RunCMake/TargetSources/empty_2.cpp new file mode 100644 index 000000000..bfbbddeb9 --- /dev/null +++ b/Tests/RunCMake/TargetSources/empty_2.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty() +{ + return 0; +} diff --git a/Tests/RunCMake/TargetSources/empty_3.cpp b/Tests/RunCMake/TargetSources/empty_3.cpp new file mode 100644 index 000000000..bfbbddeb9 --- /dev/null +++ b/Tests/RunCMake/TargetSources/empty_3.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty() +{ + return 0; +} diff --git a/Tests/RunCMake/TargetSources/empty_4.cpp b/Tests/RunCMake/TargetSources/empty_4.cpp new file mode 100644 index 000000000..bfbbddeb9 --- /dev/null +++ b/Tests/RunCMake/TargetSources/empty_4.cpp @@ -0,0 +1,7 @@ +#ifdef _WIN32 +__declspec(dllexport) +#endif +int empty() +{ + return 0; +} diff --git a/Tests/SourcesProperty/CMakeLists.txt b/Tests/SourcesProperty/CMakeLists.txt new file mode 100644 index 000000000..6c99e0074 --- /dev/null +++ b/Tests/SourcesProperty/CMakeLists.txt @@ -0,0 +1,12 @@ + +cmake_minimum_required(VERSION 3.0) + +project(SourcesProperty) + +add_library(iface INTERFACE) +set_property(TARGET iface PROPERTY INTERFACE_SOURCES iface.cpp) + +add_executable(SourcesProperty main.cpp) +target_link_libraries(SourcesProperty iface) + +set_property(TARGET SourcesProperty APPEND PROPERTY SOURCES prop.cpp) diff --git a/Tests/SourcesProperty/iface.cpp b/Tests/SourcesProperty/iface.cpp new file mode 100644 index 000000000..e38ac3778 --- /dev/null +++ b/Tests/SourcesProperty/iface.cpp @@ -0,0 +1,5 @@ + +int iface() +{ + return 0; +} diff --git a/Tests/SourcesProperty/iface.h b/Tests/SourcesProperty/iface.h new file mode 100644 index 000000000..6da80a4ed --- /dev/null +++ b/Tests/SourcesProperty/iface.h @@ -0,0 +1,4 @@ + +int iface(); + +int prop(); diff --git a/Tests/SourcesProperty/main.cpp b/Tests/SourcesProperty/main.cpp new file mode 100644 index 000000000..33a97f4be --- /dev/null +++ b/Tests/SourcesProperty/main.cpp @@ -0,0 +1,7 @@ + +#include "iface.h" + +int main(int argc, char** argv) +{ + return iface() + prop(); +} diff --git a/Tests/SourcesProperty/prop.cpp b/Tests/SourcesProperty/prop.cpp new file mode 100644 index 000000000..e34343175 --- /dev/null +++ b/Tests/SourcesProperty/prop.cpp @@ -0,0 +1,5 @@ + +int prop() +{ + return 0; +}