From 1714c27a74c1616e5998a1a51fe42848a1f1c389 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 25 Jan 2013 09:26:35 +0100 Subject: [PATCH 01/18] Process generator expressions for 'system' include directories. Since commit 08cb4fa4 (Process generator expressions in the INCLUDE_DIRECTORIES property., 2012-09-18), it is possible to use generator expressions with the include_directories command. As that command can also have a SYSTEM argument, ensure that the result of using that argument with generator expressions gives a sane result. --- Source/cmLocalGenerator.cxx | 5 +++-- Source/cmLocalGenerator.h | 3 ++- Source/cmMakefile.cxx | 21 ++++++++++++++++++--- Source/cmMakefile.h | 2 +- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index ecf6b413a..dc39fdc8d 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1212,7 +1212,8 @@ cmLocalGenerator::ConvertToIncludeReference(std::string const& path) //---------------------------------------------------------------------------- std::string cmLocalGenerator::GetIncludeFlags( const std::vector &includes, - const char* lang, bool forResponseFile) + const char* lang, bool forResponseFile, + const char *config) { if(!lang) { @@ -1285,7 +1286,7 @@ std::string cmLocalGenerator::GetIncludeFlags( if(!flagUsed || repeatFlag) { if(sysIncludeFlag && - this->Makefile->IsSystemIncludeDirectory(i->c_str())) + this->Makefile->IsSystemIncludeDirectory(i->c_str(), config)) { includeFlags << sysIncludeFlag; } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index b2ff0c48f..84cf6caee 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -149,7 +149,8 @@ public: virtual void AppendFlags(std::string& flags, const char* newFlags); ///! Get the include flags for the current makefile and language std::string GetIncludeFlags(const std::vector &includes, - const char* lang, bool forResponseFile = false); + const char* lang, bool forResponseFile = false, + const char *config = 0); /** * Encode a list of preprocessor definitions for the compiler diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index e7a1500d2..58e3f8ed4 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -23,6 +23,7 @@ #include "cmListFileCache.h" #include "cmCommandArgumentParserHelper.h" #include "cmDocumentCompileDefinitions.h" +#include "cmGeneratorExpression.h" #include "cmTest.h" #ifdef CMAKE_BUILD_WITH_CMAKE # include "cmVariableWatch.h" @@ -1665,10 +1666,24 @@ cmMakefile::AddSystemIncludeDirectories(const std::set &incs) } //---------------------------------------------------------------------------- -bool cmMakefile::IsSystemIncludeDirectory(const char* dir) +bool cmMakefile::IsSystemIncludeDirectory(const char* dir, const char *config) { - return (this->SystemIncludeDirectories.find(dir) != - this->SystemIncludeDirectories.end()); + for (std::set::const_iterator + it = this->SystemIncludeDirectories.begin(); + it != this->SystemIncludeDirectories.end(); ++it) + { + cmListFileBacktrace lfbt; + cmGeneratorExpression ge(lfbt); + + std::vector incs; + cmSystemTools::ExpandListArgument(ge.Parse(*it) + ->Evaluate(this, config, false), incs); + if (std::find(incs.begin(), incs.end(), dir) != incs.end()) + { + return true; + } + } + return false; } void cmMakefile::AddDefinition(const char* name, const char* value) diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index a2783f296..c0020bf6b 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -547,7 +547,7 @@ public: * Mark include directories as system directories. */ void AddSystemIncludeDirectories(const std::set &incs); - bool IsSystemIncludeDirectory(const char* dir); + bool IsSystemIncludeDirectory(const char* dir, const char *config); /** Expand out any arguements in the vector that have ; separated * strings into multiple arguements. A new vector is created From 92e98dd909bd399f508ff7c2f9657095ddc766cc Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 6 Feb 2013 13:18:10 +0100 Subject: [PATCH 02/18] Deduplicate the isGeneratorExpression method. This API seems like the most appropriate. --- Source/cmExportFileGenerator.cxx | 10 +--------- Source/cmGeneratorExpression.cxx | 13 +++++++++++++ Source/cmGeneratorExpression.h | 2 ++ Source/cmTarget.cxx | 10 +--------- Source/cmTargetIncludeDirectoriesCommand.cxx | 10 +--------- Source/cmTargetLinkLibrariesCommand.cxx | 10 +--------- 6 files changed, 19 insertions(+), 36 deletions(-) diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 7e4c3dfe5..fbed95a8b 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -314,14 +314,6 @@ cmExportFileGenerator::AddTargetNamespace(std::string &input, return true; } -//---------------------------------------------------------------------------- -static bool isGeneratorExpression(const std::string &lib) -{ - const std::string::size_type openpos = lib.find("$<"); - return (openpos != std::string::npos) - && (lib.find(">", openpos) != std::string::npos); -} - //---------------------------------------------------------------------------- void cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( @@ -344,7 +336,7 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( for(std::vector::iterator li = parts.begin(); li != parts.end(); ++li) { - if (!isGeneratorExpression(*li)) + if (cmGeneratorExpression::Find(*li) == std::string::npos) { this->AddTargetNamespace(*li, target, missingTargets); } diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 7add1bf39..c9f784be4 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -365,3 +365,16 @@ std::string cmGeneratorExpression::Preprocess(const std::string &input, assert(!"cmGeneratorExpression::Preprocess called with invalid args"); return std::string(); } + +//---------------------------------------------------------------------------- +std::string::size_type cmGeneratorExpression::Find(const std::string &input) +{ + const std::string::size_type openpos = input.find("$<"); + if (openpos != std::string::npos + && input.find(">", openpos) != std::string::npos) + { + return openpos; + } + } + return std::string::npos; +} diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 700fe033b..d487919e1 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -62,6 +62,8 @@ public: static void Split(const std::string &input, std::vector &output); + static std::string::size_type Find(const std::string &input); + private: cmGeneratorExpression(const cmGeneratorExpression &); void operator=(const cmGeneratorExpression &); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index ca0e24b53..2eaf1c129 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2269,14 +2269,6 @@ static std::string targetNameGenex(const char *lib) return std::string("$"; } -//---------------------------------------------------------------------------- -static bool isGeneratorExpression(const std::string &lib) -{ - const std::string::size_type openpos = lib.find("$<"); - return (openpos != std::string::npos) - && (lib.find(">", openpos) != std::string::npos); -} - //---------------------------------------------------------------------------- void cmTarget::AddLinkLibrary(cmMakefile& mf, const char *target, const char* lib, @@ -2300,7 +2292,7 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, llt).c_str()); } - if (isGeneratorExpression(lib)) + if (cmGeneratorExpression::Find(lib) != std::string::npos) { return; } diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index eaacfa9e7..808806a3a 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -40,14 +40,6 @@ void cmTargetIncludeDirectoriesCommand this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); } -//---------------------------------------------------------------------------- -static bool isGeneratorExpression(const std::string &lib) -{ - const std::string::size_type openpos = lib.find("$<"); - return (openpos != std::string::npos) - && (lib.find(">", openpos) != std::string::npos); -} - //---------------------------------------------------------------------------- std::string cmTargetIncludeDirectoriesCommand ::Join(const std::vector &content) @@ -59,7 +51,7 @@ std::string cmTargetIncludeDirectoriesCommand it != content.end(); ++it) { if (cmSystemTools::FileIsFullPath(it->c_str()) - || isGeneratorExpression(*it)) + || cmGeneratorExpression::Find(*it) != std::string::npos) { dirs += sep + *it; } diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index cb913f57a..fab3306cc 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -264,20 +264,12 @@ static std::string compileProperty(cmTarget *tgt, const std::string &lib, return tgt->GetDebugGeneratorExpressions(value, llt); } -//---------------------------------------------------------------------------- -static bool isGeneratorExpression(const std::string &lib) -{ - const std::string::size_type openpos = lib.find("$<"); - return (openpos != std::string::npos) - && (lib.find(">", openpos) != std::string::npos); -} - //---------------------------------------------------------------------------- void cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt) { - const bool isGenex = isGeneratorExpression(lib); + const bool isGenex = cmGeneratorExpression::Find(lib) != std::string::npos; cmsys::RegularExpression targetNameValidator; targetNameValidator.compile("^[A-Za-z0-9_.:-]+$"); From 7c0ec75cfa6860b53036fe46c005b84277cdbc24 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 6 Feb 2013 13:32:15 +0100 Subject: [PATCH 03/18] De-duplicate validation of genex target names. --- Source/cmGeneratorExpression.cxx | 18 ++++++++++++++---- Source/cmGeneratorExpression.h | 2 ++ Source/cmGeneratorExpressionEvaluator.cxx | 11 ++--------- Source/cmTargetLinkLibrariesCommand.cxx | 7 ++++--- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index c9f784be4..60bf17925 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -371,10 +371,20 @@ std::string::size_type cmGeneratorExpression::Find(const std::string &input) { const std::string::size_type openpos = input.find("$<"); if (openpos != std::string::npos - && input.find(">", openpos) != std::string::npos) - { - return openpos; - } + && input.find(">", openpos) != std::string::npos) + { + return openpos; } return std::string::npos; } + +//---------------------------------------------------------------------------- +bool cmGeneratorExpression::IsValidTargetName(const std::string &input) +{ + cmsys::RegularExpression targetNameValidator; + // The ':' is supported to allow use with IMPORTED targets. At least + // Qt 4 and 5 IMPORTED targets use ':' as the namespace delimiter. + targetNameValidator.compile("^[A-Za-z0-9_.:-]+$"); + + return targetNameValidator.find(input.c_str()); +} diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index d487919e1..4eab2ddf7 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -64,6 +64,8 @@ public: static std::string::size_type Find(const std::string &input); + static bool IsValidTargetName(const std::string &input); + private: cmGeneratorExpression(const cmGeneratorExpression &); void operator=(const cmGeneratorExpression &); diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 5d9471883..4779b1153 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -333,10 +333,6 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode "$ expression requires one or two parameters"); return std::string(); } - cmsys::RegularExpression targetNameValidator; - // The ':' is supported to allow use with IMPORTED targets. At least - // Qt 4 and 5 IMPORTED targets use ':' as the namespace delimiter. - targetNameValidator.compile("^[A-Za-z0-9_.:-]+$"); cmsys::RegularExpression propertyNameValidator; propertyNameValidator.compile("^[A-Za-z0-9_]+$"); @@ -372,7 +368,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode std::string targetName = parameters.front(); propertyName = parameters[1]; - if (!targetNameValidator.find(targetName.c_str())) + if (!cmGeneratorExpression::IsValidTargetName(targetName)) { if (!propertyNameValidator.find(propertyName.c_str())) { @@ -867,10 +863,7 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode // Lookup the referenced target. std::string name = *parameters.begin(); - cmsys::RegularExpression targetValidator; - // The ':' is supported to allow use with IMPORTED targets. - targetValidator.compile("^[A-Za-z0-9_.:-]+$"); - if (!targetValidator.find(name.c_str())) + if (!cmGeneratorExpression::IsValidTargetName(name)) { ::reportError(context, content->GetOriginalExpression(), "Expression syntax not recognized."); diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index fab3306cc..9dd0e5be2 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -11,6 +11,8 @@ ============================================================================*/ #include "cmTargetLinkLibrariesCommand.h" +#include "cmGeneratorExpression.h" + const char* cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[3] = { "general", @@ -271,9 +273,8 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib, { const bool isGenex = cmGeneratorExpression::Find(lib) != std::string::npos; - cmsys::RegularExpression targetNameValidator; - targetNameValidator.compile("^[A-Za-z0-9_.:-]+$"); - const bool potentialTargetName = targetNameValidator.find(lib); + const bool potentialTargetName + = cmGeneratorExpression::IsValidTargetName(lib); if (potentialTargetName || isGenex) { From 5f926a58026c3c750738e26975834b662fc85727 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Tue, 5 Feb 2013 10:24:39 +0100 Subject: [PATCH 04/18] Test printing origin of include dirs from tll(). --- .../include_directories/DebugIncludes-stderr.txt | 16 ++++++++++++---- .../include_directories/DebugIncludes.cmake | 5 +++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt b/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt index 736fe6967..c17e0ae02 100644 --- a/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt +++ b/Tests/RunCMake/include_directories/DebugIncludes-stderr.txt @@ -23,13 +23,21 @@ CMake Debug Log at DebugIncludes.cmake:18 \(include_directories\): Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) + -CMake Debug Log at DebugIncludes.cmake:25 \(set_property\): +CMake Debug Log at DebugIncludes.cmake:26 \(target_link_libraries\): Used includes for target lll: \* .*/Tests/RunCMake/include_directories/five - \* .*/Tests/RunCMake/include_directories/six Call Stack \(most recent call first\): - DebugIncludes.cmake:35 \(some_macro\) - DebugIncludes.cmake:38 \(some_function\) + CMakeLists.txt:3 \(include\) ++ +CMake Debug Log at DebugIncludes.cmake:29 \(set_property\): + Used includes for target lll: + + \* .*/Tests/RunCMake/include_directories/six + \* .*/Tests/RunCMake/include_directories/seven + +Call Stack \(most recent call first\): + DebugIncludes.cmake:40 \(some_macro\) + DebugIncludes.cmake:43 \(some_function\) CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/include_directories/DebugIncludes.cmake b/Tests/RunCMake/include_directories/DebugIncludes.cmake index 51daf7480..794a85253 100644 --- a/Tests/RunCMake/include_directories/DebugIncludes.cmake +++ b/Tests/RunCMake/include_directories/DebugIncludes.cmake @@ -21,6 +21,10 @@ include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/four" ) +add_library(foo "${CMAKE_CURRENT_BINARY_DIR}/DebugIncludes.cpp") +target_include_directories(foo INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/five") +target_link_libraries(lll foo) + macro(some_macro) set_property(TARGET lll APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/one" @@ -28,6 +32,7 @@ macro(some_macro) "${CMAKE_CURRENT_SOURCE_DIR}/four" "${CMAKE_CURRENT_SOURCE_DIR}/five" "${CMAKE_CURRENT_SOURCE_DIR}/six" + "${CMAKE_CURRENT_SOURCE_DIR}/seven" ) endmacro() From 46e28960a58a25bbf0124b6ab95eda24cc4fe1a4 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 7 Feb 2013 00:43:54 +0100 Subject: [PATCH 05/18] The COMPATIBLE_INTERFACE does not affect the target it is set on. Test and document this. --- Source/cmTarget.cxx | 24 ++++++++++++------------ Tests/CompatibleInterface/CMakeLists.txt | 15 +++++++++++++++ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 2eaf1c129..4109929ca 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -900,24 +900,24 @@ void cmTarget::DefineProperties(cmake *cm) "Properties which must be compatible with their link interface", "The COMPATIBLE_INTERFACE_BOOL property may contain a list of properties" "for this target which must be consistent when evaluated as a boolean " - "in the INTERFACE of all linked dependencies. For example, if a " - "property \"FOO\" appears in the list, then the \"INTERFACE_FOO\" " - "property content in all dependencies must be consistent with each " - "other, and with the \"FOO\" property in this target. " - "Consistency in this sense has the meaning that if the property is set," - "then it must have the same boolean value as all others, and if the " - "property is not set, then it is ignored."); + "in the INTERFACE of all linked dependees. For example, if a " + "property \"FOO\" appears in the list, then for each dependee, the " + "\"INTERFACE_FOO\" property content in all of its dependencies must be " + "consistent with each other, and with the \"FOO\" property in the " + "dependee. Consistency in this sense has the meaning that if the " + "property is set, then it must have the same boolean value as all " + "others, and if the property is not set, then it is ignored."); cm->DefineProperty ("COMPATIBLE_INTERFACE_STRING", cmProperty::TARGET, "Properties which must be string-compatible with their link interface", "The COMPATIBLE_INTERFACE_STRING property may contain a list of " "properties for this target which must be the same when evaluated as " - "a string in the INTERFACE of all linked dependencies. For example, " - "if a property \"FOO\" appears in the list, then the \"INTERFACE_FOO\" " - "property content in all dependencies must be equal with each " - "other, and with the \"FOO\" property in this target. If the " - "property is not set, then it is ignored."); + "a string in the INTERFACE of all linked dependees. For example, " + "if a property \"FOO\" appears in the list, then for each dependee, the " + "\"INTERFACE_FOO\" property content in all of its dependencies must be " + "equal with each other, and with the \"FOO\" property in the dependee. " + "If the property is not set, then it is ignored."); cm->DefineProperty ("POST_INSTALL_SCRIPT", cmProperty::TARGET, diff --git a/Tests/CompatibleInterface/CMakeLists.txt b/Tests/CompatibleInterface/CMakeLists.txt index 329510b05..cd0a37d20 100644 --- a/Tests/CompatibleInterface/CMakeLists.txt +++ b/Tests/CompatibleInterface/CMakeLists.txt @@ -67,3 +67,18 @@ target_compile_definitions(CompatibleInterface PRIVATE $<$>:SOME_DEFINE> ) + +# The COMPATIBLE_INTERFACE_* properties are only read from dependencies +# in the interface. Populating it on the CompatibleInterface target does +# not have any affect on the interpretation of the INTERFACE variants +# in dependencies. +set_property(TARGET iface1 PROPERTY + INTERFACE_NON_RELEVANT_PROP ON +) +set_property(TARGET iface2 PROPERTY + INTERFACE_NON_RELEVANT_PROP ON +) +set_property(TARGET CompatibleInterface APPEND PROPERTY + COMPATIBLE_INTERFACE_BOOL + NON_RELEVANT_PROP +) From 655e98bf7149eb3757a0587409076326edeb9c04 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 7 Feb 2013 00:47:31 +0100 Subject: [PATCH 06/18] Ensure type specific compatible interface properties do not intersect. Before, the boolean version would always win, and the string one would be ignored. --- Source/cmTarget.cxx | 34 ++++++++++++++++--- .../InterfaceString-Bool-Conflict-result.txt | 1 + .../InterfaceString-Bool-Conflict-stderr.txt | 5 +++ .../InterfaceString-Bool-Conflict.cmake | 9 +++++ .../CompatibleInterface/RunCMakeTest.cmake | 1 + 5 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 Tests/RunCMake/CompatibleInterface/InterfaceString-Bool-Conflict-result.txt create mode 100644 Tests/RunCMake/CompatibleInterface/InterfaceString-Bool-Conflict-stderr.txt create mode 100644 Tests/RunCMake/CompatibleInterface/InterfaceString-Bool-Conflict.cmake diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 4109929ca..b92bf775c 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -906,7 +906,10 @@ void cmTarget::DefineProperties(cmake *cm) "consistent with each other, and with the \"FOO\" property in the " "dependee. Consistency in this sense has the meaning that if the " "property is set, then it must have the same boolean value as all " - "others, and if the property is not set, then it is ignored."); + "others, and if the property is not set, then it is ignored. Note that " + "for each dependee, the set of properties from this property must not " + "intersect with the set of properties from the " + "COMPATIBLE_INTERFACE_STRING property."); cm->DefineProperty ("COMPATIBLE_INTERFACE_STRING", cmProperty::TARGET, @@ -917,7 +920,10 @@ void cmTarget::DefineProperties(cmake *cm) "if a property \"FOO\" appears in the list, then for each dependee, the " "\"INTERFACE_FOO\" property content in all of its dependencies must be " "equal with each other, and with the \"FOO\" property in the dependee. " - "If the property is not set, then it is ignored."); + "If the property is not set, then it is ignored. Note that for each " + "dependee, the set of properties from this property must not intersect " + "with the set of properties from the COMPATIBLE_INTERFACE_BOOL " + "property."); cm->DefineProperty ("POST_INSTALL_SCRIPT", cmProperty::TARGET, @@ -5616,7 +5622,8 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, { const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); - std::set emitted; + std::set emittedBools; + std::set emittedStrings; for(cmComputeLinkInformation::ItemVector::const_iterator li = deps.begin(); @@ -5629,19 +5636,36 @@ void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info, checkPropertyConsistency(this, li->Target, "COMPATIBLE_INTERFACE_BOOL", - emitted, config, 0); + emittedBools, config, 0); if (cmSystemTools::GetErrorOccuredFlag()) { return; } checkPropertyConsistency(this, li->Target, "COMPATIBLE_INTERFACE_STRING", - emitted, config, 0); + emittedStrings, config, 0); if (cmSystemTools::GetErrorOccuredFlag()) { return; } } + + for(std::set::const_iterator li = emittedBools.begin(); + li != emittedBools.end(); ++li) + { + const std::set::const_iterator si = emittedStrings.find(*li); + if (si != emittedStrings.end()) + { + cmOStringStream e; + e << "Property \"" << *li << "\" appears in both the " + "COMPATIBLE_INTERFACE_BOOL and the COMPATIBLE_INTERFACE_STRING " + "property in the dependencies of target \"" << this->GetName() << + "\". This is not allowed. A property may only require compatibility " + "in a boolean interpretation or a string interpretation, but not both."; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + break; + } + } } //---------------------------------------------------------------------------- diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-Bool-Conflict-result.txt b/Tests/RunCMake/CompatibleInterface/InterfaceString-Bool-Conflict-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-Bool-Conflict-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-Bool-Conflict-stderr.txt b/Tests/RunCMake/CompatibleInterface/InterfaceString-Bool-Conflict-stderr.txt new file mode 100644 index 000000000..5a8f99df2 --- /dev/null +++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-Bool-Conflict-stderr.txt @@ -0,0 +1,5 @@ +CMake Error in CMakeLists.txt: + Property "SOMETHING" appears in both the COMPATIBLE_INTERFACE_BOOL and the + COMPATIBLE_INTERFACE_STRING property in the dependencies of target "user". + This is not allowed. A property may only require compatibility in a + boolean interpretation or a string interpretation, but not both. diff --git a/Tests/RunCMake/CompatibleInterface/InterfaceString-Bool-Conflict.cmake b/Tests/RunCMake/CompatibleInterface/InterfaceString-Bool-Conflict.cmake new file mode 100644 index 000000000..711368a80 --- /dev/null +++ b/Tests/RunCMake/CompatibleInterface/InterfaceString-Bool-Conflict.cmake @@ -0,0 +1,9 @@ + +add_library(foo UNKNOWN IMPORTED) +add_library(bar UNKNOWN IMPORTED) + +set_property(TARGET foo APPEND PROPERTY COMPATIBLE_INTERFACE_BOOL SOMETHING) +set_property(TARGET foo APPEND PROPERTY COMPATIBLE_INTERFACE_STRING SOMETHING) + +add_executable(user main.cpp) +target_link_libraries(user foo bar) diff --git a/Tests/RunCMake/CompatibleInterface/RunCMakeTest.cmake b/Tests/RunCMake/CompatibleInterface/RunCMakeTest.cmake index 922ad7fc7..976815111 100644 --- a/Tests/RunCMake/CompatibleInterface/RunCMakeTest.cmake +++ b/Tests/RunCMake/CompatibleInterface/RunCMakeTest.cmake @@ -8,3 +8,4 @@ run_cmake(InterfaceString-mismatch-depends) run_cmake(InterfaceString-mismatch-depend-self) run_cmake(InterfaceString-mismatched-use) run_cmake(InterfaceString-builtin-prop) +run_cmake(InterfaceString-Bool-Conflict) From 3a298c0bf4e3e86f4705b9255bf032cf70d5cadb Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 7 Feb 2013 01:49:17 +0100 Subject: [PATCH 07/18] Fix generation of COMPILE_DEFINITIONS in DependInfo.cmake. As INTERFACE_COMPILE_DEFINITIONS are now possible, we can have situations like this: add_library(foo ...) add_library(bar ...) target_link_libraries(foo bar) target_compile_definitions(bar INTERFACE SOME_DEF) The INTERFACE_COMPILE_DEFINITIONS of bar determine how foo should be compiled, and if they change, foo should be rebuilt. Additionally, as of commit d1446ca7 (Append the COMPILE_DEFINITIONS from the Makefile to all targets., 2012-09-17), we don't need to read definitions from the makefile if we read them from the target, so also de-duplicate the cached info. The DependInfo for INTERFACE_INCLUDE_DIRECTORIES is already handled correctly. --- Source/cmLocalUnixMakefileGenerator3.cxx | 27 +++++------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index d629e7135..f6ab0d051 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -1961,34 +1961,17 @@ void cmLocalUnixMakefileGenerator3 } // Build a list of preprocessor definitions for the target. - std::vector defines; - { - std::string defPropName = "COMPILE_DEFINITIONS_"; - defPropName += cmSystemTools::UpperCase(this->ConfigurationName); - if(const char* ddefs = this->Makefile->GetProperty("COMPILE_DEFINITIONS")) - { - cmSystemTools::ExpandListArgument(ddefs, defines); - } - if(const char* cdefs = target.GetProperty("COMPILE_DEFINITIONS")) - { - cmSystemTools::ExpandListArgument(cdefs, defines); - } - if(const char* dcdefs = this->Makefile->GetProperty(defPropName.c_str())) - { - cmSystemTools::ExpandListArgument(dcdefs, defines); - } - if(const char* ccdefs = target.GetProperty(defPropName.c_str())) - { - cmSystemTools::ExpandListArgument(ccdefs, defines); - } - } + std::set defines; + this->AppendDefines(defines, target.GetCompileDefinitions()); + this->AppendDefines(defines, target.GetCompileDefinitions( + this->ConfigurationName.c_str())); if(!defines.empty()) { cmakefileStream << "\n" << "# Preprocessor definitions for this target.\n" << "SET(CMAKE_TARGET_DEFINITIONS\n"; - for(std::vector::const_iterator di = defines.begin(); + for(std::set::const_iterator di = defines.begin(); di != defines.end(); ++di) { cmakefileStream From 4cf161a5e7af6f32d76263ac751600577e4d7bd3 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 7 Feb 2013 12:31:18 +0100 Subject: [PATCH 08/18] Fix determination of evaluating link libraries. Added in commit 6fbe3ce4 (Exclude the LINK_LIBRARIES related properties from INTERFACE evaluation., 2013-01-23) --- Source/cmGeneratorExpressionDAGChecker.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx index b9069ef60..0ac1a483d 100644 --- a/Source/cmGeneratorExpressionDAGChecker.cxx +++ b/Source/cmGeneratorExpressionDAGChecker.cxx @@ -148,8 +148,8 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries() return (strcmp(prop, "LINK_LIBRARIES") == 0 || strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0 || strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0 - || strncmp(prop, "LINK_INTERFACE_LIBRARIES_", 26) == 0 - || strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 35) == 0); + || strncmp(prop, "LINK_INTERFACE_LIBRARIES_", 25) == 0 + || strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 34) == 0); } //---------------------------------------------------------------------------- From 57175d559ee2bdd56c360a3b45aacf13b15b9270 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 7 Feb 2013 12:33:20 +0100 Subject: [PATCH 09/18] Only use early evaluation termination for transitive properties. We need to make sure expressions which evaluate TARGET_PROPERTY:TYPE multiple times for example get the correct result each time, and not an empty string instead. --- Source/cmGeneratorExpressionEvaluator.cxx | 13 +++++++++++-- .../target_link_libraries/CMakeLists.txt | 5 ++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 4779b1153..0ac1e7615 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -434,8 +434,17 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode // No error. We just skip cyclic references. return std::string(); case cmGeneratorExpressionDAGChecker::ALREADY_SEEN: - // No error. We're not going to find anything new here. - return std::string(); + for (size_t i = 0; + i < (sizeof(targetPropertyTransitiveWhitelist) / + sizeof(*targetPropertyTransitiveWhitelist)); + ++i) + { + if (targetPropertyTransitiveWhitelist[i] == propertyName) + { + // No error. We're not going to find anything new here. + return std::string(); + } + } case cmGeneratorExpressionDAGChecker::DAG: break; } diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt index cd0fe1129..19ee59f41 100644 --- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt @@ -103,4 +103,7 @@ target_compile_definitions(depG INTERFACE ) add_executable(targetC targetC.cpp) -target_link_libraries(targetC depG) +# Creates a generator expression for include directories like +# $<$,EXECUTABLE>:depG>>:\ +# $,EXECUTABLE>:depG>,INTERFACE_INCLUDE_DIRECTORIES>> +target_link_libraries(targetC $<$,EXECUTABLE>:depG>) From 1fb545ad3a8f6d263c9f01300bce978e81b6fe8c Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 7 Feb 2013 13:13:44 +0100 Subject: [PATCH 10/18] Move a special case for PIC from the genex to the cmTarget code. --- Source/cmGeneratorExpressionEvaluator.cxx | 6 ------ Source/cmTarget.cxx | 3 ++- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index 0ac1e7615..f601ea394 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -460,12 +460,6 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode { return std::string(); } - if (propertyName == "POSITION_INDEPENDENT_CODE") - { - context->HadContextSensitiveCondition = true; - return target->GetLinkInterfaceDependentBoolProperty( - "POSITION_INDEPENDENT_CODE", context->Config) ? "1" : "0"; - } if (target->IsLinkInterfaceDependentBoolProperty(propertyName, context->Config)) { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index b92bf775c..6f197b82a 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -4797,7 +4797,8 @@ bool isLinkDependentProperty(cmTarget *tgt, const std::string &p, bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p, const char *config) { - return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_BOOL", + return (p == "POSITION_INDEPENDENT_CODE") || + isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_BOOL", config); } From d4e5c6787c40e27394c336730f59d878a81d1991 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 7 Feb 2013 13:04:46 +0100 Subject: [PATCH 11/18] Don't keep track of content determined by target property values. This tracking was added during the development of commit 042ecf04 (Add API to calculate link-interface-dependent bool properties or error., 2013-01-06), but was never used. It was not necessary to use the content because what is really useful in that logic is to determine if a property has been implied to be null by appearing in a LINK_LIBRARIES genex. I think the motivating usecase for developing the feature of keeping track of the targets relevant to a property was that I thought it would make it possible to allow requiring granular compatibility of interface properties only for targets which depended on the interface property. Eg: add_library(foo ...) add_library(bar ...) add_executable(user ...) # Read the INTERFACE_POSITION_INDEPENDENT_CODE from bar, but not # from foo: target_link_libraries(user foo $<$:bar>) This obviously doesn't make sense. We require that INTERFACE properties are consistent across all linked targets instead. --- Source/cmGeneratorExpression.cxx | 5 ++- Source/cmGeneratorExpression.h | 4 +-- Source/cmGeneratorExpressionEvaluator.cxx | 3 +- Source/cmTarget.cxx | 43 +++++------------------ Source/cmTarget.h | 7 ---- 5 files changed, 15 insertions(+), 47 deletions(-) diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx index 60bf17925..5d162fe03 100644 --- a/Source/cmGeneratorExpression.cxx +++ b/Source/cmGeneratorExpression.cxx @@ -95,14 +95,13 @@ const char *cmCompiledGeneratorExpression::Evaluate( for ( ; it != end; ++it) { - const std::string result = (*it)->Evaluate(&context, dagChecker); - this->Output += result; + this->Output += (*it)->Evaluate(&context, dagChecker); for(std::set::const_iterator p = context.SeenTargetProperties.begin(); p != context.SeenTargetProperties.end(); ++p) { - this->SeenTargetProperties[*p] += result + ";"; + this->SeenTargetProperties.insert(*p); } if (context.HadError) { diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h index 4eab2ddf7..489b052e9 100644 --- a/Source/cmGeneratorExpression.h +++ b/Source/cmGeneratorExpression.h @@ -90,7 +90,7 @@ public: std::set const& GetTargets() const { return this->Targets; } - std::map const& GetSeenTargetProperties() const + std::set const& GetSeenTargetProperties() const { return this->SeenTargetProperties; } ~cmCompiledGeneratorExpression(); @@ -124,7 +124,7 @@ private: bool NeedsParsing; mutable std::set Targets; - mutable std::map SeenTargetProperties; + mutable std::set SeenTargetProperties; mutable std::string Output; mutable bool HadContextSensitiveCondition; }; diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index f601ea394..d2dbf11e6 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -398,7 +398,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode { // Keep track of the properties seen while processing. // The evaluation of the LINK_LIBRARIES generator expressions - // will check this to ensure that properties form a DAG. + // will check this to ensure that properties have one consistent + // value for all evaluations. context->SeenTargetProperties.insert(propertyName); } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 6f197b82a..f55999f90 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2233,7 +2233,15 @@ void cmTarget::GetDirectLinkLibraries(const char *config, &dagChecker), libs); - this->AddLinkDependentTargetsForProperties(cge->GetSeenTargetProperties()); + std::set seenProps = cge->GetSeenTargetProperties(); + for (std::set::const_iterator it = seenProps.begin(); + it != seenProps.end(); ++it) + { + if (!this->GetProperty(it->c_str())) + { + this->LinkImplicitNullProperties.insert(*it); + } + } } } @@ -4519,18 +4527,6 @@ const char* cmTarget::GetExportMacro() } } -//---------------------------------------------------------------------------- -void cmTarget::GetLinkDependentTargetsForProperty(const std::string &p, - std::set &targets) -{ - const std::map >::const_iterator findIt - = this->LinkDependentProperties.find(p); - if (findIt != this->LinkDependentProperties.end()) - { - targets = findIt->second; - } -} - //---------------------------------------------------------------------------- bool cmTarget::IsNullImpliedByLinkLibraries(const std::string &p) { @@ -4538,24 +4534,6 @@ bool cmTarget::IsNullImpliedByLinkLibraries(const std::string &p) != this->LinkImplicitNullProperties.end(); } -//---------------------------------------------------------------------------- -void cmTarget::AddLinkDependentTargetsForProperties( - const std::map &map) -{ - for (std::map::const_iterator it = map.begin(); - it != map.end(); ++it) - { - std::vector targets; - cmSystemTools::ExpandListArgument(it->second.c_str(), targets); - this->LinkDependentProperties[it->first].insert(targets.begin(), - targets.end()); - if (!this->GetProperty(it->first.c_str())) - { - this->LinkImplicitNullProperties.insert(it->first); - } - } -} - //---------------------------------------------------------------------------- template PropertyType getTypedProperty(cmTarget *tgt, const char *prop, @@ -4611,9 +4589,6 @@ PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt, const bool explicitlySet = tgt->GetProperties() .find(p.c_str()) != tgt->GetProperties().end(); - std::set dependentTargets; - tgt->GetLinkDependentTargetsForProperty(p, - dependentTargets); const bool impliedByUse = tgt->IsNullImpliedByLinkLibraries(p); assert((impliedByUse ^ explicitlySet) diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 7577a5941..fb1496fa2 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -498,17 +498,12 @@ public: void AppendBuildInterfaceIncludes(); - void GetLinkDependentTargetsForProperty(const std::string &p, - std::set &targets); bool IsNullImpliedByLinkLibraries(const std::string &p); bool IsLinkInterfaceDependentBoolProperty(const std::string &p, const char *config); bool IsLinkInterfaceDependentStringProperty(const std::string &p, const char *config); - void AddLinkDependentTargetsForProperties( - const std::map &map); - bool GetLinkInterfaceDependentBoolProperty(const std::string &p, const char *config); @@ -627,8 +622,6 @@ private: bool IsApple; bool IsImportedTarget; bool DebugIncludesDone; - mutable std::map > - LinkDependentProperties; mutable std::set LinkImplicitNullProperties; bool BuildInterfaceIncludesAppended; From df74bc34d4219a8d6e63ec7e41a9ca4fbe355581 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 7 Feb 2013 19:31:23 +0100 Subject: [PATCH 12/18] Only append build interface include dirs to particular targets. We shouldn't set the property on all custom targets. --- Source/cmDocumentVariables.cxx | 7 ++++--- Source/cmTarget.cxx | 7 +++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx index 08b3ef168..dd138a377 100644 --- a/Source/cmDocumentVariables.cxx +++ b/Source/cmDocumentVariables.cxx @@ -1150,9 +1150,10 @@ void cmDocumentVariables::DefineVariables(cmake* cm) ("CMAKE_BUILD_INTERFACE_INCLUDES", cmProperty::VARIABLE, "Automatically add the current source- and build directories " "to the INTERFACE_INCLUDE_DIRECTORIES.", - "If this variable is enabled, CMake automatically adds for each " - "target ${CMAKE_CURRENT_SOURCE_DIR} and ${CMAKE_CURRENT_BINARY_DIR} " - "to the INTERFACE_INCLUDE_DIRECTORIES." + "If this variable is enabled, CMake automatically adds for each shared " + "library target, static library target, module target and executable " + "target, ${CMAKE_CURRENT_SOURCE_DIR} and ${CMAKE_CURRENT_BINARY_DIR} to " + "the INTERFACE_INCLUDE_DIRECTORIES." "By default CMAKE_BUILD_INTERFACE_INCLUDES is OFF.", false, "Variables that Control the Build"); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index f55999f90..2945173d7 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2714,6 +2714,13 @@ void cmTarget::AppendProperty(const char* prop, const char* value, //---------------------------------------------------------------------------- void cmTarget::AppendBuildInterfaceIncludes() { + if(this->GetType() != cmTarget::SHARED_LIBRARY && + this->GetType() != cmTarget::STATIC_LIBRARY && + this->GetType() != cmTarget::MODULE_LIBRARY && + !this->IsExecutableWithExports()) + { + return; + } if (this->BuildInterfaceIncludesAppended) { return; From 4de71786e89ba35190e23ae9e1c05f902c5350ff Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 7 Feb 2013 19:35:00 +0100 Subject: [PATCH 13/18] Ensure that the build interface includes have been added. This is needed in the case that Automoc is used, as that calls GetIncludeDirectories, which may cache the resulting include dirs too early in the generate step. Also, because the automoc step is so early, we can't cache the include directories at that point. At that point the build interface of all dependencies are not populated yet, so we'd be caching the includes before appending the build interface. Only start caching when we're definitely generating the buildsystem. At that point, the includes should be stable. We still need to invoke AppendBuildInterfaceIncludes in the GlobalGenerator because the build interface includes affect mostly the dependencies of targets (such as the automoc targets), rather than the targets themselves, so the build interface needs to be appended for all targets before generation is done. --- Source/cmTarget.cxx | 4 +++- Tests/QtAutomoc/Adir/CMakeLists.txt | 8 ++++++++ Tests/QtAutomoc/Adir/libA.cpp | 13 +++++++++++++ Tests/QtAutomoc/Adir/libA.h | 18 ++++++++++++++++++ Tests/QtAutomoc/Bdir/CMakeLists.txt | 10 ++++++++++ Tests/QtAutomoc/Bdir/libB.cpp | 13 +++++++++++++ Tests/QtAutomoc/Bdir/libB.h | 21 +++++++++++++++++++++ Tests/QtAutomoc/CMakeLists.txt | 16 +++++++++++++++- Tests/QtAutomoc/libC.cpp | 13 +++++++++++++ Tests/QtAutomoc/libC.h | 22 ++++++++++++++++++++++ Tests/QtAutomoc/main.cpp | 4 ++++ 11 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 Tests/QtAutomoc/Adir/CMakeLists.txt create mode 100644 Tests/QtAutomoc/Adir/libA.cpp create mode 100644 Tests/QtAutomoc/Adir/libA.h create mode 100644 Tests/QtAutomoc/Bdir/CMakeLists.txt create mode 100644 Tests/QtAutomoc/Bdir/libB.cpp create mode 100644 Tests/QtAutomoc/Bdir/libB.h create mode 100644 Tests/QtAutomoc/libC.cpp create mode 100644 Tests/QtAutomoc/libC.h diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 2945173d7..59afcb650 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2767,6 +2767,7 @@ std::vector cmTarget::GetIncludeDirectories(const char *config) this->GetName(), "INCLUDE_DIRECTORIES", 0, 0); + this->AppendBuildInterfaceIncludes(); std::vector debugProperties; const char *debugProp = @@ -2808,7 +2809,8 @@ std::vector cmTarget::GetIncludeDirectories(const char *config) this, &dagChecker), entryIncludes); - if (!(*it)->ge->GetHadContextSensitiveCondition()) + if (this->Makefile->IsGeneratingBuildSystem() + && !(*it)->ge->GetHadContextSensitiveCondition()) { cacheIncludes = true; } diff --git a/Tests/QtAutomoc/Adir/CMakeLists.txt b/Tests/QtAutomoc/Adir/CMakeLists.txt new file mode 100644 index 000000000..abd328e76 --- /dev/null +++ b/Tests/QtAutomoc/Adir/CMakeLists.txt @@ -0,0 +1,8 @@ + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_BUILD_INTERFACE_INCLUDES ON) + +add_library(libA SHARED libA.cpp) +target_link_libraries(libA LINK_PUBLIC Qt4::QtCore) +generate_export_header(libA) diff --git a/Tests/QtAutomoc/Adir/libA.cpp b/Tests/QtAutomoc/Adir/libA.cpp new file mode 100644 index 000000000..3968c4415 --- /dev/null +++ b/Tests/QtAutomoc/Adir/libA.cpp @@ -0,0 +1,13 @@ + +#include "libA.h" + +LibA::LibA(QObject *parent) + : QObject(parent) +{ + +} + +int LibA::foo() +{ + return 0; +} diff --git a/Tests/QtAutomoc/Adir/libA.h b/Tests/QtAutomoc/Adir/libA.h new file mode 100644 index 000000000..03ad1e006 --- /dev/null +++ b/Tests/QtAutomoc/Adir/libA.h @@ -0,0 +1,18 @@ + +#ifndef LIBA_H +#define LIBA_H + +#include "liba_export.h" + +#include + +class LIBA_EXPORT LibA : public QObject +{ + Q_OBJECT +public: + explicit LibA(QObject *parent = 0); + + int foo(); +}; + +#endif diff --git a/Tests/QtAutomoc/Bdir/CMakeLists.txt b/Tests/QtAutomoc/Bdir/CMakeLists.txt new file mode 100644 index 000000000..549710571 --- /dev/null +++ b/Tests/QtAutomoc/Bdir/CMakeLists.txt @@ -0,0 +1,10 @@ + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_AUTOMOC ON) +set(CMAKE_BUILD_INTERFACE_INCLUDES ON) + +add_library(libB SHARED libB.cpp) +generate_export_header(libB) + +# set_property(TARGET libB APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) +target_link_libraries(libB LINK_PUBLIC libA) diff --git a/Tests/QtAutomoc/Bdir/libB.cpp b/Tests/QtAutomoc/Bdir/libB.cpp new file mode 100644 index 000000000..72f2cfae9 --- /dev/null +++ b/Tests/QtAutomoc/Bdir/libB.cpp @@ -0,0 +1,13 @@ + +#include "libB.h" + +LibB::LibB(QObject *parent) + : QObject(parent) +{ + +} + +int LibB::foo() +{ + return a.foo(); +} diff --git a/Tests/QtAutomoc/Bdir/libB.h b/Tests/QtAutomoc/Bdir/libB.h new file mode 100644 index 000000000..510c17f8f --- /dev/null +++ b/Tests/QtAutomoc/Bdir/libB.h @@ -0,0 +1,21 @@ + +#ifndef LIBB_H +#define LIBB_H + +#include "libb_export.h" + +#include +#include "libA.h" + +class LIBB_EXPORT LibB : public QObject +{ + Q_OBJECT +public: + explicit LibB(QObject *parent = 0); + + int foo(); +private: + LibA a; +}; + +#endif diff --git a/Tests/QtAutomoc/CMakeLists.txt b/Tests/QtAutomoc/CMakeLists.txt index 855fcf0f5..530818e9c 100644 --- a/Tests/QtAutomoc/CMakeLists.txt +++ b/Tests/QtAutomoc/CMakeLists.txt @@ -23,4 +23,18 @@ add_executable(foo main.cpp calwidget.cpp foo.cpp blub.cpp bar.cpp abc.cpp set_target_properties(foo codeeditorLib privateSlot PROPERTIES AUTOMOC TRUE) -target_link_libraries(foo codeeditorLib ${QT_LIBRARIES} ) +include(GenerateExportHeader) +# The order is relevant here. B depends on A, and B headers depend on A +# headers both subdirectories use CMAKE_BUILD_INTERFACE_INCLUDES and we +# test that CMAKE_AUTOMOC successfully reads the include directories +# for the build interface from those targets. There has previously been +# a bug where caching of the include directories happened before +# extracting the includes to pass to moc. +add_subdirectory(Bdir) +add_subdirectory(Adir) +add_library(libC SHARED libC.cpp) +set_target_properties(libC PROPERTIES AUTOMOC TRUE) +generate_export_header(libC) +target_link_libraries(libC LINK_PUBLIC libB) + +target_link_libraries(foo codeeditorLib ${QT_LIBRARIES} libC) diff --git a/Tests/QtAutomoc/libC.cpp b/Tests/QtAutomoc/libC.cpp new file mode 100644 index 000000000..8d61cb1bf --- /dev/null +++ b/Tests/QtAutomoc/libC.cpp @@ -0,0 +1,13 @@ + +#include "libC.h" + +LibC::LibC(QObject *parent) + : QObject(parent) +{ + +} + +int LibC::foo() +{ + return b.foo(); +} diff --git a/Tests/QtAutomoc/libC.h b/Tests/QtAutomoc/libC.h new file mode 100644 index 000000000..4fb4a2cf4 --- /dev/null +++ b/Tests/QtAutomoc/libC.h @@ -0,0 +1,22 @@ + +#ifndef LIBC_H +#define LIBC_H + +#include "libc_export.h" + +#include +#include "libB.h" + +class LIBC_EXPORT LibC : public QObject +{ + Q_OBJECT +public: + explicit LibC(QObject *parent = 0); + + + int foo(); +private: + LibB b; +}; + +#endif diff --git a/Tests/QtAutomoc/main.cpp b/Tests/QtAutomoc/main.cpp index 738f67720..d952171b5 100644 --- a/Tests/QtAutomoc/main.cpp +++ b/Tests/QtAutomoc/main.cpp @@ -48,6 +48,7 @@ #include "abc.h" #include "xyz.h" #include "yaf.h" +#include "libC.h" int main(int argv, char **args) { @@ -78,5 +79,8 @@ int main(int argv, char **args) Yaf yaf; yaf.doYaf(); + LibC lc; + lc.foo(); + return app.exec(); } From 510fdcb18801076e2041eaae2941375eecc93ec2 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 8 Feb 2013 19:12:45 +0100 Subject: [PATCH 14/18] Whitelist target types in target_{include_directories,compile_definitions} Setting include directories or compile definitions on a target created with add_custom_target does not make sense. --- Source/cmTargetPropCommandBase.cxx | 9 +++++++++ Tests/ObjectLibrary/A/CMakeLists.txt | 2 +- Tests/RunCMake/include_directories/RunCMakeTest.cmake | 1 + .../include_directories/TID-bad-target-result.txt | 1 + .../include_directories/TID-bad-target-stderr.txt | 4 ++++ Tests/RunCMake/include_directories/TID-bad-target.cmake | 6 ++++++ 6 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 Tests/RunCMake/include_directories/TID-bad-target-result.txt create mode 100644 Tests/RunCMake/include_directories/TID-bad-target-stderr.txt create mode 100644 Tests/RunCMake/include_directories/TID-bad-target.cmake diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx index 18a1d2a9f..771097ca2 100644 --- a/Source/cmTargetPropCommandBase.cxx +++ b/Source/cmTargetPropCommandBase.cxx @@ -38,6 +38,15 @@ bool cmTargetPropCommandBase this->HandleMissingTarget(args[0]); return false; } + if ((this->Target->GetType() != cmTarget::SHARED_LIBRARY) + && (this->Target->GetType() != cmTarget::STATIC_LIBRARY) + && (this->Target->GetType() != cmTarget::OBJECT_LIBRARY) + && (this->Target->GetType() != cmTarget::MODULE_LIBRARY) + && (this->Target->GetType() != cmTarget::EXECUTABLE)) + { + this->SetError("called with non-compilable target type"); + return false; + } unsigned int argIndex = 1; diff --git a/Tests/ObjectLibrary/A/CMakeLists.txt b/Tests/ObjectLibrary/A/CMakeLists.txt index 36c86e7e9..55778eabf 100644 --- a/Tests/ObjectLibrary/A/CMakeLists.txt +++ b/Tests/ObjectLibrary/A/CMakeLists.txt @@ -13,6 +13,6 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/a1.c.in ${CMAKE_CURRENT_BINARY_DIR}/a1.c ) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_library(A OBJECT a1.c a2.c) +target_include_directories(A PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/Tests/RunCMake/include_directories/RunCMakeTest.cmake b/Tests/RunCMake/include_directories/RunCMakeTest.cmake index de3725226..ddf268c1e 100644 --- a/Tests/RunCMake/include_directories/RunCMakeTest.cmake +++ b/Tests/RunCMake/include_directories/RunCMakeTest.cmake @@ -2,3 +2,4 @@ include(RunCMake) run_cmake(NotFoundContent) run_cmake(DebugIncludes) +run_cmake(TID-bad-target) diff --git a/Tests/RunCMake/include_directories/TID-bad-target-result.txt b/Tests/RunCMake/include_directories/TID-bad-target-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/include_directories/TID-bad-target-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/include_directories/TID-bad-target-stderr.txt b/Tests/RunCMake/include_directories/TID-bad-target-stderr.txt new file mode 100644 index 000000000..481e358b2 --- /dev/null +++ b/Tests/RunCMake/include_directories/TID-bad-target-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at TID-bad-target.cmake:6 \(target_include_directories\): + target_include_directories called with non-compilable target type +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/include_directories/TID-bad-target.cmake b/Tests/RunCMake/include_directories/TID-bad-target.cmake new file mode 100644 index 000000000..32201c1fb --- /dev/null +++ b/Tests/RunCMake/include_directories/TID-bad-target.cmake @@ -0,0 +1,6 @@ + +add_custom_target(check ALL + COMMAND ${CMAKE_COMMAND} -E echo check +) + +target_include_directories(check PRIVATE somedir) From faa927e273e04b9aadc13fb1f2b8b307b7383cd2 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 8 Feb 2013 20:10:22 +0100 Subject: [PATCH 15/18] Make sure INTERFACE properties work with OBJECT libraries. --- Source/cmTarget.cxx | 8 ++++++++ Tests/ObjectLibrary/B/CMakeLists.txt | 6 +++++- Tests/ObjectLibrary/B/b.h | 7 +++++++ Tests/ObjectLibrary/CMakeLists.txt | 8 ++++++++ Tests/ObjectLibrary/mainAB.c | 8 +++----- 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 59afcb650..bf918d52e 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -4781,6 +4781,10 @@ bool isLinkDependentProperty(cmTarget *tgt, const std::string &p, bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p, const char *config) { + if (this->TargetTypeValue == OBJECT_LIBRARY) + { + return false; + } return (p == "POSITION_INDEPENDENT_CODE") || isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_BOOL", config); @@ -4790,6 +4794,10 @@ bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p, bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p, const char *config) { + if (this->TargetTypeValue == OBJECT_LIBRARY) + { + return false; + } return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_STRING", config); } diff --git a/Tests/ObjectLibrary/B/CMakeLists.txt b/Tests/ObjectLibrary/B/CMakeLists.txt index 32d8cebf6..a567f960b 100644 --- a/Tests/ObjectLibrary/B/CMakeLists.txt +++ b/Tests/ObjectLibrary/B/CMakeLists.txt @@ -10,7 +10,11 @@ if(CMAKE_SHARED_LIBRARY_C_FLAGS AND NOT WATCOM) set(CMAKE_C_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS} ${CMAKE_C_FLAGS}") endif() -add_definitions(-DB_DEF) add_library(B OBJECT b1.c b2.c) +target_include_directories(B PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_definitions(B PUBLIC B_DEF) + add_library(Bexport OBJECT b1${vs6}.c b2${vs6}.c) set_property(TARGET Bexport PROPERTY COMPILE_DEFINITIONS Bexport) +target_include_directories(Bexport PRIVATE $) +target_compile_definitions(Bexport PRIVATE $) diff --git a/Tests/ObjectLibrary/B/b.h b/Tests/ObjectLibrary/B/b.h index 11b22f427..3489c7105 100644 --- a/Tests/ObjectLibrary/B/b.h +++ b/Tests/ObjectLibrary/B/b.h @@ -4,8 +4,15 @@ #ifndef B_DEF # error "B_DEF not defined" #endif + #if defined(_WIN32) && defined(Bexport) # define EXPORT_B __declspec(dllexport) #else # define EXPORT_B #endif + +#if defined(_WIN32) && defined(SHARED_B) +# define IMPORT_B __declspec(dllimport) +#else +# define IMPORT_B +#endif diff --git a/Tests/ObjectLibrary/CMakeLists.txt b/Tests/ObjectLibrary/CMakeLists.txt index 87234159f..13a07b44a 100644 --- a/Tests/ObjectLibrary/CMakeLists.txt +++ b/Tests/ObjectLibrary/CMakeLists.txt @@ -26,6 +26,9 @@ endif() # Test static library without its own sources. add_library(ABstatic STATIC ${dummy} $ $) +target_include_directories(ABstatic PUBLIC $) +target_compile_definitions(ABstatic PUBLIC $) + add_executable(UseABstatic mainAB.c) target_link_libraries(UseABstatic ABstatic) @@ -41,12 +44,17 @@ endif() # Test shared library without its own sources. add_library(ABshared SHARED ${dummy} ${ABshared_SRCS}) +target_include_directories(ABshared PUBLIC $) +target_compile_definitions(ABshared PUBLIC $) + add_executable(UseABshared mainAB.c) set_property(TARGET UseABshared PROPERTY COMPILE_DEFINITIONS SHARED_B ${NO_A}) target_link_libraries(UseABshared ABshared) # Test executable without its own sources. add_library(ABmain OBJECT mainAB.c) +target_include_directories(ABmain PUBLIC $) +target_compile_definitions(ABmain PUBLIC $) add_executable(UseABinternal ${dummy} $ $ $ ) diff --git a/Tests/ObjectLibrary/mainAB.c b/Tests/ObjectLibrary/mainAB.c index 556898b83..38db20520 100644 --- a/Tests/ObjectLibrary/mainAB.c +++ b/Tests/ObjectLibrary/mainAB.c @@ -1,8 +1,6 @@ -#if defined(_WIN32) && defined(SHARED_B) -# define IMPORT_B __declspec(dllimport) -#else -# define IMPORT_B -#endif + +#include "b.h" + extern IMPORT_B int b1(void); extern IMPORT_B int b2(void); #ifndef NO_A From 9712362b4580fb92394ecf8ff57be186571f4319 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 8 Feb 2013 20:20:53 +0100 Subject: [PATCH 16/18] Don't allow utility or global targets in the LINKED expression. The LINKED expression is exclusively for handling INTERFACE content and it does not make sense for utility targets to have INTERFACE content. --- Source/cmGeneratorExpressionEvaluator.cxx | 8 ++++++++ .../BadLinked-UtilityTarget-result.txt | 1 + .../BadLinked-UtilityTarget-stderr.txt | 8 ++++++++ .../BadLinked-UtilityTarget.cmake | 7 +++++++ .../TargetPropertyGeneratorExpressions/RunCMakeTest.cmake | 1 + .../RunCMake/TargetPropertyGeneratorExpressions/empty.cpp | 1 + 6 files changed, 26 insertions(+) create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-UtilityTarget-result.txt create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-UtilityTarget-stderr.txt create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-UtilityTarget.cmake create mode 100644 Tests/RunCMake/TargetPropertyGeneratorExpressions/empty.cpp diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx index d2dbf11e6..98e0ada67 100644 --- a/Source/cmGeneratorExpressionEvaluator.cxx +++ b/Source/cmGeneratorExpressionEvaluator.cxx @@ -702,6 +702,14 @@ private: { return std::string(); } + if(target->GetType() >= cmTarget::UTILITY && + target->GetType() != cmTarget::UNKNOWN_LIBRARY) + { + ::reportError(context, content->GetOriginalExpression(), + "Target \"" + item + + "\" is not an executable or library."); + return std::string(); + } std::string propertyName = "INTERFACE_" + prop; const char *propContent = target->GetProperty(propertyName.c_str()); if (!propContent) diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-UtilityTarget-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-UtilityTarget-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-UtilityTarget-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-UtilityTarget-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-UtilityTarget-stderr.txt new file mode 100644 index 000000000..fb065540b --- /dev/null +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-UtilityTarget-stderr.txt @@ -0,0 +1,8 @@ +CMake Error at BadLinked-UtilityTarget.cmake:7 \(set_property\): + Error evaluating generator expression: + + \$ + + Target "check" is not an executable or library. +Call Stack \(most recent call first\): + CMakeLists.txt:8 \(include\) diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-UtilityTarget.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-UtilityTarget.cmake new file mode 100644 index 000000000..d114c8fc6 --- /dev/null +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadLinked-UtilityTarget.cmake @@ -0,0 +1,7 @@ + +add_custom_target(check ALL + COMMAND ${CMAKE_COMMAND} -E echo check +) + +add_library(foo STATIC empty.cpp) +set_property(TARGET foo PROPERTY INCLUDE_DIRECTORIES $) diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake index ea48f61a8..84039c437 100644 --- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake @@ -16,3 +16,4 @@ run_cmake(BadInvalidName6) run_cmake(BadInvalidName7) run_cmake(BadInvalidName8) run_cmake(BadLinked) +run_cmake(BadLinked-UtilityTarget) diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/empty.cpp b/Tests/RunCMake/TargetPropertyGeneratorExpressions/empty.cpp new file mode 100644 index 000000000..8b1a39374 --- /dev/null +++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/empty.cpp @@ -0,0 +1 @@ +// empty From deb51a711369c9e5cce19bc3626e87273c6b5ac4 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 9 Feb 2013 10:24:32 +0100 Subject: [PATCH 17/18] Remove unused forward declarations. --- Source/cmExportInstallFileGenerator.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index 7a704311e..20dd57ad1 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -15,10 +15,7 @@ #include "cmExportFileGenerator.h" class cmInstallExportGenerator; -class cmInstallFilesGenerator; class cmInstallTargetGenerator; -class cmTargetExport; -class cmExportSet; /** \class cmExportInstallFileGenerator * \brief Generate a file exporting targets from an install tree. From ba48e63f1e68a22dd46b6c33d283190bf8aa0aed Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Sat, 9 Feb 2013 10:20:14 +0100 Subject: [PATCH 18/18] Generate config-specific interface link libraries propeties. All other properties we generate are config-specific, so it makes sense to do so here too. --- Modules/FindQt4.cmake | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Modules/FindQt4.cmake b/Modules/FindQt4.cmake index 35420b48b..5baee01cb 100644 --- a/Modules/FindQt4.cmake +++ b/Modules/FindQt4.cmake @@ -985,11 +985,19 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) endmacro() macro(_qt4_add_target_depends _QT_MODULE) - _qt4_add_target_depends_internal(${_QT_MODULE} IMPORTED_LINK_INTERFACE_LIBRARIES ${ARGN}) + get_target_property(_configs Qt4::${_QT_MODULE} IMPORTED_CONFIGURATIONS) + foreach(_config ${_configs}) + _qt4_add_target_depends_internal(${_QT_MODULE} IMPORTED_LINK_INTERFACE_LIBRARIES_${_config} ${ARGN}) + endforeach() + set(_configs) endmacro() macro(_qt4_add_target_private_depends _QT_MODULE) - _qt4_add_target_depends_internal(${_QT_MODULE} IMPORTED_LINK_DEPENDENT_LIBRARIES ${ARGN}) + get_target_property(_configs ${_QT_MODULE} IMPORTED_CONFIGURATIONS) + foreach(_config ${_configs}) + _qt4_add_target_depends_internal(${_QT_MODULE} IMPORTED_LINK_DEPENDENT_LIBRARIES_${_config} ${ARGN}) + endforeach() + set(_configs) endmacro() @@ -1067,10 +1075,14 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION) set(_isWin32 $>) set(_isNotExcluded $>>) set(_isPolicyNEW $) - set_property(TARGET Qt4::QtCore APPEND PROPERTY - IMPORTED_LINK_INTERFACE_LIBRARIES - $<$:Qt4::qtmain> - ) + get_target_property(_configs Qt4::QtCore IMPORTED_CONFIGURATIONS) + foreach(_config ${_configs}) + set_property(TARGET Qt4::QtCore APPEND PROPERTY + IMPORTED_LINK_INTERFACE_LIBRARIES_${_config} + $<$:Qt4::qtmain> + ) + endforeach() + unset(_configs) unset(_isExe) unset(_isWin32) unset(_isNotExcluded)