[Cmake-commits] CMake branch, next, updated. v2.8.10.1-1003-g4672f15
Stephen Kelly
steveire at gmail.com
Fri Nov 23 12:31:21 EST 2012
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".
The branch, next has been updated
via 4672f15930d767b611eec2fbed1bce06110f902a (commit)
via eb1674ec92e11ae5b881dbc20ff56ee432f43a6b (commit)
via 73cbbc0b265b20fc0f54b932cedd5668275eed4f (commit)
via 7cde1eaaae7eb9c35d453fd4d1d2274cd498409b (commit)
via 92ae560f62734ba4915812bf58b09608208e9308 (commit)
via d0abe0f7c10044447f312eada840ba38855794a5 (commit)
via 906fe771697aa7c7b026b5c9f35b6a7f4f3a5f05 (commit)
from 49ba670b61f2e8438b33fe6667d9c50da2a8d556 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4672f15930d767b611eec2fbed1bce06110f902a
commit 4672f15930d767b611eec2fbed1bce06110f902a
Merge: 49ba670 eb1674e
Author: Stephen Kelly <steveire at gmail.com>
AuthorDate: Fri Nov 23 12:31:12 2012 -0500
Commit: CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Fri Nov 23 12:31:12 2012 -0500
Merge topic 'tll-set-include-and-defines-requirements' into next
eb1674e Add includes and compile definitions with target_link_libraries.
73cbbc0 Add the TARGET_DEFINED generator expression
7cde1ea Handle INTERFACE properties transitively for includes and defines.
92ae560 Keep track of INCLUDE_DIRECTORIES as a vector of structs.
d0abe0f Use cmsys::auto_ptr to manage cmCompiledGeneratorExpressions
906fe77 Genex: Add INTERFACE_LINK_LIBRARIES property
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=eb1674ec92e11ae5b881dbc20ff56ee432f43a6b
commit eb1674ec92e11ae5b881dbc20ff56ee432f43a6b
Author: Stephen Kelly <steveire at gmail.com>
AuthorDate: Mon Nov 5 12:43:28 2012 +0100
Commit: Stephen Kelly <steveire at gmail.com>
CommitDate: Fri Nov 23 17:50:16 2012 +0100
Add includes and compile definitions with target_link_libraries.
The compile-related properties are required for linking so it makes
sense to add the interface includes for dependencies.
This requires adding a policy to handle the change in behavior of
code such as:
add_executable(foo ...)
target_link_libraries(foo bar bat)
include_directories(${bat_INCLUDE_DIRS} ${bar_INCLUDE_DIRS})
which will change order of generated includes after this patch if
bar or bat are TARGETS with an INTERFACE_INCLUDE_DIRECTORIES
property.
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 8498d72..5fa10f2 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -1665,8 +1665,14 @@ void cmMakefile::AddIncludeDirectory(const char* inc, bool before)
l != this->Targets.end(); ++l)
{
cmTarget &t = l->second;
- prop = t.GetProperties().GetOrCreateProperty("INCLUDE_DIRECTORIES");
- AddStringToProperty(prop, "INCLUDE_DIRECTORIES", inc, before);
+ if (before)
+ {
+ t.PrependTLLIncludeDirectories(inc);
+ }
+ else
+ {
+ t.AppendTLLIncludeDirectories(inc);
+ }
}
}
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 4c89dd6..13e36c8 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -511,6 +511,23 @@ cmPolicies::cmPolicies()
"the value of the (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? target "
"property",
2,8,11,0, cmPolicies::WARN);
+
+ this->DefinePolicy(
+ CMP0020, "CMP0020",
+ "Use INCLUDE_DIRECTORIES order implied by target_link_libraries.",
+ "CMake 2.8.11 introduced a feature where using target_link_libraries "
+ "can read the INTERFACE_INCLUDE_DIRECTORIES property of a target and "
+ "use the value as include directories when compiling. Because the "
+ "target_link_libraries call might occur before the include_directories "
+ "call, this could change the order of includes in the compile step."
+ "\n"
+ "The OLD behavior for this policy is to let the include_directories call "
+ "determine the order of includes."
+ "\n"
+ "The NEW behavior for this policy is to use the order of includes "
+ "determined by the order of all calls to target_link_libraries and "
+ "include_directories",
+ 2,8,11,0, cmPolicies::WARN);
}
cmPolicies::~cmPolicies()
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index b6b8e39..94154ee 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -69,6 +69,7 @@ public:
/// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C}
/// instead.
CMP0019, ///< Use new-style INTERFACE_LINK_LIBRARIES
+ CMP0020, ///< Use INCLUDE_DIRECTORIES order from target_link_libraries
/** \brief Always the last entry.
*
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 451b84b..717ebbb 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -121,10 +121,13 @@ public:
SourceEntriesType SourceEntries;
struct IncludeDirectoriesEntry {
- IncludeDirectoriesEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge)
- : ge(cge)
+ IncludeDirectoriesEntry(
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
+ bool tllEntry = false)
+ : ge(cge), ImpliedByTargetLinkLibraries(tllEntry)
{}
const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
+ const bool ImpliedByTargetLinkLibraries;
};
std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries;
std::string IncludeDirectoriesString;
@@ -2522,6 +2525,29 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
}
//----------------------------------------------------------------------------
+void cmTarget::AppendTLLIncludeDirectories(const std::string &includes)
+{
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+ this->Internal->IncludeDirectoriesEntries.push_back(
+ new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(includes),
+ true)
+ );
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::PrependTLLIncludeDirectories(const std::string &includes)
+{
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+ this->Internal->IncludeDirectoriesEntries.insert(
+ this->Internal->IncludeDirectoriesEntries.begin(),
+ new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(includes),
+ true)
+ );
+}
+
+//----------------------------------------------------------------------------
std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
{
std::set<std::string> fromTll;
@@ -2554,8 +2580,44 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
cmSystemTools::ConvertToUnixSlashes(inc);
}
+ if (!(*it)->ImpliedByTargetLinkLibraries)
+ {
+ if (fromTll.find(*li) != fromTll.end())
+ {
+ switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0020))
+ {
+ case cmPolicies::WARN:
+ {
+ cmOStringStream e;
+ e << "The include directory " << *li << " was specified "
+ "implicitly by an earlier call to target_link_libraries. "
+ "Preserving the order of includes as if the earlier use of "
+ "target_link_libraries had not added it."
+ << this->Makefile->GetPolicies()->GetPolicyWarning(
+ cmPolicies::CMP0020);
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ }
+ // Fall through to OLD behavior
+ case cmPolicies::OLD:
+ includes.erase(std::remove(includes.begin(),
+ includes.end(), *li),
+ includes.end());
+ fromTll.erase(*li);
+ includes.push_back(*li);
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ break;
+ }
+ }
+ }
if(uniqueIncludes.insert(inc).second)
{
+ if ((*it)->ImpliedByTargetLinkLibraries)
+ {
+ fromTll.insert(*li);
+ }
includes.push_back(*li);
}
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 60a105e..a6090e5 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -478,6 +478,9 @@ public:
/** @return the Mac framework directory without the base. */
std::string GetFrameworkDirectory(const char* config = 0);
+ void AppendTLLIncludeDirectories(const std::string &includes);
+ void PrependTLLIncludeDirectories(const std::string &includes);
+
std::vector<std::string> GetIncludeDirectories(const char *config);
private:
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index d7a1443..2ccdc01 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -273,10 +273,52 @@ static std::string generatorIface(const std::string &value,
}
//----------------------------------------------------------------------------
+static std::string compileProperty(const std::string &lib,
+ const std::string &property,
+ cmTarget::LinkLibraryType llt)
+{
+ return generatorIface(std::string("$<$<TARGET_DEFINED:" + lib + ">"
+ ":$<TARGET_PROPERTY:")
+ + lib
+ + ",INTERFACE_" + property + ">>", 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);
+}
+
+//----------------------------------------------------------------------------
+static bool isList(const char *lib)
+{
+ std::vector<std::string> result;
+ cmSystemTools::ExpandListArgument(lib, result);
+ return result.size() > 1;
+}
+
+//----------------------------------------------------------------------------
void
cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
cmTarget::LinkLibraryType llt)
{
+ cmTarget *tgt = this->Makefile->FindTargetToUse(lib);
+ const bool isNonImportedTarget = tgt && !tgt->IsImported();
+ const bool isGenex = isGeneratorExpression(lib);
+ const std::string nsLib =
+ std::string(isNonImportedTarget && !isList(lib)
+ ? "$<EXPORT_NAMESPACE>" : "") + lib;
+ if (tgt || isGenex)
+ {
+ this->Target->AppendTLLIncludeDirectories(compileProperty(nsLib,
+ "INCLUDE_DIRECTORIES", llt));
+ this->Target->AppendProperty("COMPILE_DEFINITIONS",
+ compileProperty(nsLib,
+ "COMPILE_DEFINITIONS", llt).c_str());
+ }
+
// Handle normal case first.
if(this->CurrentProcessingState != ProcessingLinkInterface)
{
@@ -290,7 +332,13 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
}
this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
- generatorIface(lib, llt).c_str());
+ generatorIface(nsLib, llt).c_str());
+ this->Target->AppendProperty("INTERFACE_COMPILE_DEFINITIONS",
+ compileProperty(nsLib,
+ "COMPILE_DEFINITIONS", llt).c_str());
+ this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
+ compileProperty(nsLib,
+ "INCLUDE_DIRECTORIES", llt).c_str());
// Get the list of configurations considered to be DEBUG.
std::vector<std::string> const& debugConfigs =
diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
index 95cfd15..92c9338 100644
--- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
@@ -74,3 +74,27 @@ add_executable(targetB targetB.cpp)
target_link_libraries(targetB depD depE)
# cmake_policy(POP)
+
+
+macro(create_header _name)
+ file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_name}")
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_name}/${_name}.h" "//${_name}.h\n")
+endmacro()
+
+create_header(foo)
+create_header(bar)
+
+add_library(depF SHARED depF.cpp)
+generate_export_header(depF)
+set_property(TARGET depF PROPERTY
+ INTERFACE_INCLUDE_DIRECTORIES
+ ${CMAKE_CURRENT_BINARY_DIR}/foo
+ ${CMAKE_CURRENT_BINARY_DIR}/bar
+)
+set_property(TARGET depF PROPERTY
+ INTERFACE_COMPILE_DEFINITIONS
+ TEST_DEF
+)
+
+add_library(targetC targetC.cpp)
+target_link_libraries(targetC depF)
diff --git a/Tests/CMakeCommands/target_link_libraries/depF.cpp b/Tests/CMakeCommands/target_link_libraries/depF.cpp
new file mode 100644
index 0000000..1fd29c4
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depF.cpp
@@ -0,0 +1,7 @@
+
+#include "depF.h"
+
+int DepF::foo()
+{
+ return 0;
+}
diff --git a/Tests/CMakeCommands/target_link_libraries/depF.h b/Tests/CMakeCommands/target_link_libraries/depF.h
new file mode 100644
index 0000000..95d6b14
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depF.h
@@ -0,0 +1,7 @@
+
+#include "depf_export.h"
+
+struct DEPF_EXPORT DepF
+{
+ int foo();
+};
diff --git a/Tests/CMakeCommands/target_link_libraries/targetC.cpp b/Tests/CMakeCommands/target_link_libraries/targetC.cpp
new file mode 100644
index 0000000..ac33c67
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/targetC.cpp
@@ -0,0 +1,16 @@
+
+#include "depF.h"
+
+#include "foo.h"
+#include "bar.h"
+
+#ifndef TEST_DEF
+#error Expected TEST_DEF definition
+#endif
+
+int main(int argc, char **argv)
+{
+ DepF f;
+
+ return f.foo();
+}
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=73cbbc0b265b20fc0f54b932cedd5668275eed4f
commit 73cbbc0b265b20fc0f54b932cedd5668275eed4f
Author: Stephen Kelly <steveire at gmail.com>
AuthorDate: Mon Nov 19 23:56:12 2012 +0100
Commit: Stephen Kelly <steveire at gmail.com>
CommitDate: Fri Nov 23 17:50:04 2012 +0100
Add the TARGET_DEFINED generator expression
This tests whether the parameter is a usable target.
diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h
index 445fd0e..4866f0d 100644
--- a/Source/cmDocumentGeneratorExpressions.h
+++ b/Source/cmDocumentGeneratorExpressions.h
@@ -27,6 +27,7 @@
" $<COMMA> = A literal ','. Used to compare " \
"strings which contain a ',' for example.\n" \
" $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \
+ " $<TARGET_DEFINED:tgt> = '1' if tgt is a target, else '0'\n" \
" $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \
" $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n" \
"where \"tgt\" is the name of a target. " \
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 57d75e0..9c6ea23 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -286,6 +286,23 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
} configurationTestNode;
//----------------------------------------------------------------------------
+static const struct TargetTestNode : public cmGeneratorExpressionNode
+{
+ TargetTestNode() {}
+
+ virtual int NumExpectedParameters() const { return 1; }
+
+ std::string Evaluate(const std::vector<std::string> ¶meters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return context->Makefile->FindTargetToUse(parameters.front().c_str())
+ ? "1" : "0";
+ }
+} targetTestNode;
+
+//----------------------------------------------------------------------------
static const char* targetPropertyTransitiveWhitelist[] = {
"INTERFACE_INCLUDE_DIRECTORIES"
, "INTERFACE_COMPILE_DEFINITIONS"
@@ -648,6 +665,8 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &installInterfaceNode;
else if (identifier == "EXPORT_NAMESPACE")
return &nullNode;
+ else if (identifier == "TARGET_DEFINED")
+ return &targetTestNode;
return 0;
}
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7cde1eaaae7eb9c35d453fd4d1d2274cd498409b
commit 7cde1eaaae7eb9c35d453fd4d1d2274cd498409b
Author: Stephen Kelly <steveire at gmail.com>
AuthorDate: Sun Sep 23 13:45:17 2012 +0200
Commit: Stephen Kelly <steveire at gmail.com>
CommitDate: Fri Nov 23 17:50:03 2012 +0100
Handle INTERFACE properties transitively for includes and defines.
Contextually, the behavior is as if the properties content from another
target is included in the string and then the result is evaluated.
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index f8f412a..f943584 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -51,6 +51,12 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
{
ImportPropertyMap properties;
+ this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", te,
+ cmGeneratorExpression::BuildInterface,
+ properties);
+ this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te,
+ cmGeneratorExpression::BuildInterface,
+ properties);
this->PopulateInterfaceProperty("INTERFACE_LINK_LIBRARIES", te,
cmGeneratorExpression::BuildInterface,
properties);
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 4d99866..40606be 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -68,6 +68,14 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
{
ImportPropertyMap properties;
+ this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES",
+ te->Target,
+ cmGeneratorExpression::InstallInterface,
+ properties);
+ this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS",
+ te->Target,
+ cmGeneratorExpression::InstallInterface,
+ properties);
this->PopulateInterfaceProperty("INTERFACE_LINK_LIBRARIES",
te->Target,
cmGeneratorExpression::InstallInterface,
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 07f46be..57d75e0 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -286,6 +286,12 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
} configurationTestNode;
//----------------------------------------------------------------------------
+static const char* targetPropertyTransitiveWhitelist[] = {
+ "INTERFACE_INCLUDE_DIRECTORIES"
+ , "INTERFACE_COMPILE_DEFINITIONS"
+};
+
+//----------------------------------------------------------------------------
static const struct TargetPropertyNode : public cmGeneratorExpressionNode
{
TargetPropertyNode() {}
@@ -387,7 +393,27 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
}
const char *prop = target->GetProperty(propertyName.c_str());
- return prop ? prop : "";
+ if (!prop)
+ {
+ return std::string();
+ }
+
+ for (size_t i = 0;
+ i < (sizeof(targetPropertyTransitiveWhitelist) /
+ sizeof(*targetPropertyTransitiveWhitelist));
+ ++i)
+ {
+ if (targetPropertyTransitiveWhitelist[i] == propertyName)
+ {
+ cmGeneratorExpression ge(context->Backtrace);
+ return ge.Parse(prop)->Evaluate(context->Makefile,
+ context->Config,
+ context->Quiet,
+ context->Target,
+ &dagChecker);
+ }
+ }
+ return prop;
}
} targetPropertyNode;
diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
index 7cb1b42..4e79d1f 100644
--- a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
@@ -45,3 +45,23 @@ set_property(TARGET TargetIncludeDirectories
APPEND PROPERTY INCLUDE_DIRECTORIES
"$<TARGET_PROPERTY:somelib::withcolons,INTERFACE_INCLUDE_DIRECTORIES>"
)
+
+create_header(fee)
+create_header(fiy)
+create_header(foh)
+create_header(fum)
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib1.cpp" "#include \"fee.h\"")
+add_library(lib1 "${CMAKE_CURRENT_BINARY_DIR}/lib1.cpp")
+set_property(TARGET lib1 APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fee")
+set_property(TARGET lib1 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fiy")
+set_property(TARGET lib1 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:${CMAKE_CURRENT_BINARY_DIR}/foh>")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/lib2.cpp" "#include \"fiy.h\"")
+add_library(lib2 "${CMAKE_CURRENT_BINARY_DIR}/lib2.cpp")
+set_property(TARGET lib2 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/fum;$<TARGET_PROPERTY:lib1,INTERFACE_INCLUDE_DIRECTORIES>")
+set_property(TARGET lib2 APPEND PROPERTY INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:lib1,INTERFACE_INCLUDE_DIRECTORIES>")
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main3.cpp" "#include \"fiy.h\"\n#include \"foh.h\"\n#include \"fum.h\"\nint main(int,char**) { return 0; }\n")
+add_executable(exe3 "${CMAKE_CURRENT_BINARY_DIR}/main3.cpp")
+set_property(TARGET exe3 APPEND PROPERTY INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:lib2,INTERFACE_INCLUDE_DIRECTORIES>")
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=92ae560f62734ba4915812bf58b09608208e9308
commit 92ae560f62734ba4915812bf58b09608208e9308
Author: Stephen Kelly <steveire at gmail.com>
AuthorDate: Mon Nov 19 22:47:30 2012 +0100
Commit: Stephen Kelly <steveire at gmail.com>
CommitDate: Fri Nov 23 17:50:03 2012 +0100
Keep track of INCLUDE_DIRECTORIES as a vector of structs.
The struct can keep track of where the include came from, which gives
us proper backtraces, and will allow us to implement a policy later
relating to order of include directories.
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 55507dd..62ee26a 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -252,45 +252,7 @@ const char* cmGeneratorTarget::GetCreateRuleVariable()
std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
const char *config)
{
- std::vector<std::string> includes;
- const char *prop = this->Target->GetProperty("INCLUDE_DIRECTORIES");
- if(!prop)
- {
- return includes;
- }
-
- cmListFileBacktrace lfbt;
- cmGeneratorExpression ge(lfbt);
-
- cmGeneratorExpressionDAGChecker dagChecker(lfbt,
- this->GetName(),
- "INCLUDE_DIRECTORIES", 0, 0);
-
- cmSystemTools::ExpandListArgument(ge.Parse(prop)
- ->Evaluate(this->Makefile,
- config,
- false,
- this->Target,
- &dagChecker),
- includes);
-
- std::set<std::string> uniqueIncludes;
- std::vector<std::string> orderedAndUniqueIncludes;
- for(std::vector<std::string>::const_iterator
- li = includes.begin(); li != includes.end(); ++li)
- {
- std::string inc = *li;
- if (!cmSystemTools::IsOff(inc.c_str()))
- {
- cmSystemTools::ConvertToUnixSlashes(inc);
- }
- if(uniqueIncludes.insert(inc).second)
- {
- orderedAndUniqueIncludes.push_back(inc);
- }
- }
-
- return orderedAndUniqueIncludes;
+ return this->Target->GetIncludeDirectories(config);
}
//----------------------------------------------------------------------------
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 0e83878..451b84b 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -119,6 +119,15 @@ public:
struct SourceEntry { std::vector<cmSourceFile*> Depends; };
typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType;
SourceEntriesType SourceEntries;
+
+ struct IncludeDirectoriesEntry {
+ IncludeDirectoriesEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge)
+ : ge(cge)
+ {}
+ const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
+ };
+ std::vector<IncludeDirectoriesEntry*> IncludeDirectoriesEntries;
+ std::string IncludeDirectoriesString;
};
//----------------------------------------------------------------------------
@@ -2478,6 +2487,16 @@ void cmTarget::SetProperty(const char* prop, const char* value)
return;
}
+ if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
+ {
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+ this->Internal->IncludeDirectoriesEntries.clear();
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
+ this->Internal->IncludeDirectoriesEntries.push_back(
+ new cmTargetInternals::IncludeDirectoriesEntry(cge));
+ return;
+ }
this->Properties.SetProperty(prop, value, cmProperty::TARGET);
this->MaybeInvalidatePropertyCache(prop);
}
@@ -2490,11 +2509,61 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
{
return;
}
+ if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
+ {
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+ this->Internal->IncludeDirectoriesEntries.push_back(
+ new cmTargetInternals::IncludeDirectoriesEntry(ge.Parse(value)));
+ return;
+ }
this->Properties.AppendProperty(prop, value, cmProperty::TARGET, asString);
this->MaybeInvalidatePropertyCache(prop);
}
//----------------------------------------------------------------------------
+std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
+{
+ std::set<std::string> fromTll;
+ std::vector<std::string> includes;
+ std::set<std::string> uniqueIncludes;
+ cmListFileBacktrace lfbt;
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ "INCLUDE_DIRECTORIES", 0, 0);
+
+ for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
+ it = this->Internal->IncludeDirectoriesEntries.begin(),
+ end = this->Internal->IncludeDirectoriesEntries.end();
+ it != end; ++it)
+ {
+ std::vector<std::string> entryIncludes;
+ cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(this->Makefile,
+ config,
+ false,
+ this,
+ &dagChecker),
+ entryIncludes);
+ for(std::vector<std::string>::const_iterator
+ li = entryIncludes.begin(); li != entryIncludes.end(); ++li)
+ {
+ std::string inc = *li;
+ if (!cmSystemTools::IsOff(inc.c_str()))
+ {
+ cmSystemTools::ConvertToUnixSlashes(inc);
+ }
+
+ if(uniqueIncludes.insert(inc).second)
+ {
+ includes.push_back(*li);
+ }
+ }
+ }
+ return includes;
+}
+
+//----------------------------------------------------------------------------
void cmTarget::MaybeInvalidatePropertyCache(const char* prop)
{
// Wipe out maps caching information affected by this property.
@@ -2820,6 +2889,23 @@ const char *cmTarget::GetProperty(const char* prop,
}
}
}
+ if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
+ {
+ this->Internal->IncludeDirectoriesString = "";
+ std::string sep;
+ typedef cmTargetInternals::IncludeDirectoriesEntry
+ IncludeDirectoriesEntry;
+ for (std::vector<IncludeDirectoriesEntry*>::const_iterator
+ it = this->Internal->IncludeDirectoriesEntries.begin(),
+ end = this->Internal->IncludeDirectoriesEntries.end();
+ it != end; ++it)
+ {
+ this->Internal->IncludeDirectoriesString += sep;
+ this->Internal->IncludeDirectoriesString += (*it)->ge->GetInput();
+ sep = ";";
+ }
+ return this->Internal->IncludeDirectoriesString.c_str();
+ }
}
if (strcmp(prop,"IMPORTED") == 0)
@@ -5086,6 +5172,13 @@ cmTargetInternalPointer
//----------------------------------------------------------------------------
cmTargetInternalPointer::~cmTargetInternalPointer()
{
+ for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
+ it = this->Pointer->IncludeDirectoriesEntries.begin(),
+ end = this->Pointer->IncludeDirectoriesEntries.end();
+ it != end; ++it)
+ {
+ delete *it;
+ }
delete this->Pointer;
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 7c55933..60a105e 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -478,6 +478,8 @@ public:
/** @return the Mac framework directory without the base. */
std::string GetFrameworkDirectory(const char* config = 0);
+ std::vector<std::string> GetIncludeDirectories(const char *config);
+
private:
/**
* A list of direct dependencies. Use in conjunction with DependencyMap.
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d0abe0f7c10044447f312eada840ba38855794a5
commit d0abe0f7c10044447f312eada840ba38855794a5
Author: Stephen Kelly <steveire at gmail.com>
AuthorDate: Mon Nov 19 19:30:56 2012 +0100
Commit: Stephen Kelly <steveire at gmail.com>
CommitDate: Fri Nov 23 17:50:02 2012 +0100
Use cmsys::auto_ptr to manage cmCompiledGeneratorExpressions
The compiled generator expressions need to outlive the creating
type. For the same reason, store the input string in a std::string.
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 07df7d5..f2f77ee 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -47,7 +47,7 @@ std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
{
return target->GetLocation(this->Config);
}
- return this->GE->Parse(argv0).Evaluate(this->Makefile, this->Config);
+ return this->GE->Parse(argv0)->Evaluate(this->Makefile, this->Config);
}
//----------------------------------------------------------------------------
@@ -58,7 +58,7 @@ cmCustomCommandGenerator
cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c];
for(unsigned int j=1;j < commandLine.size(); ++j)
{
- std::string arg = this->GE->Parse(commandLine[j]).Evaluate(this->Makefile,
+ std::string arg = this->GE->Parse(commandLine[j])->Evaluate(this->Makefile,
this->Config);
cmd += " ";
if(this->OldStyle)
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 2bcced1..97a0581 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -25,44 +25,29 @@
//----------------------------------------------------------------------------
cmGeneratorExpression::cmGeneratorExpression(
cmListFileBacktrace const& backtrace):
- Backtrace(backtrace), CompiledExpression(0)
+ Backtrace(backtrace)
{
}
//----------------------------------------------------------------------------
-const cmCompiledGeneratorExpression &
+cmsys::auto_ptr<cmCompiledGeneratorExpression>
cmGeneratorExpression::Parse(std::string const& input)
{
return this->Parse(input.c_str());
}
//----------------------------------------------------------------------------
-const cmCompiledGeneratorExpression &
+cmsys::auto_ptr<cmCompiledGeneratorExpression>
cmGeneratorExpression::Parse(const char* input)
{
- cmGeneratorExpressionLexer l;
- std::vector<cmGeneratorExpressionToken> tokens = l.Tokenize(input);
- bool needsParsing = l.GetSawGeneratorExpression();
- std::vector<cmGeneratorExpressionEvaluator*> evaluators;
-
- if (needsParsing)
- {
- cmGeneratorExpressionParser p(tokens);
- p.Parse(evaluators);
- }
-
- delete this->CompiledExpression;
- this->CompiledExpression = new cmCompiledGeneratorExpression(
- this->Backtrace,
- evaluators,
- input,
- needsParsing);
- return *this->CompiledExpression;
+ return cmsys::auto_ptr<cmCompiledGeneratorExpression>(
+ new cmCompiledGeneratorExpression(
+ this->Backtrace,
+ input));
}
cmGeneratorExpression::~cmGeneratorExpression()
{
- delete this->CompiledExpression;
}
//----------------------------------------------------------------------------
@@ -73,7 +58,7 @@ const char *cmCompiledGeneratorExpression::Evaluate(
{
if (!this->NeedsParsing)
{
- return this->Input;
+ return this->Input.c_str();
}
this->Output = "";
@@ -108,12 +93,19 @@ const char *cmCompiledGeneratorExpression::Evaluate(
cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
cmListFileBacktrace const& backtrace,
- const std::vector<cmGeneratorExpressionEvaluator*> &evaluators,
- const char *input, bool needsParsing)
- : Backtrace(backtrace), Evaluators(evaluators), Input(input),
- NeedsParsing(needsParsing)
+ const char *input)
+ : Backtrace(backtrace), Input(input ? input : "")
{
+ cmGeneratorExpressionLexer l;
+ std::vector<cmGeneratorExpressionToken> tokens =
+ l.Tokenize(this->Input.c_str());
+ this->NeedsParsing = l.GetSawGeneratorExpression();
+ if (this->NeedsParsing)
+ {
+ cmGeneratorExpressionParser p(tokens);
+ p.Parse(this->Evaluators);
+ }
}
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index 5e3352b..c3daf84 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -14,10 +14,12 @@
#define cmGeneratorExpression_h
#include "cmStandardIncludes.h"
+#include "cmListFileCache.h"
#include <stack>
#include <cmsys/RegularExpression.hxx>
+#include <cmsys/auto_ptr.hxx>
class cmTarget;
class cmMakefile;
@@ -44,8 +46,9 @@ public:
cmGeneratorExpression(cmListFileBacktrace const& backtrace);
~cmGeneratorExpression();
- const cmCompiledGeneratorExpression& Parse(std::string const& input);
- const cmCompiledGeneratorExpression& Parse(const char* input);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> Parse(
+ std::string const& input);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> Parse(const char* input);
enum PreprocessContext {
StripAllGeneratorExpressions,
@@ -62,7 +65,6 @@ private:
void operator=(const cmGeneratorExpression &);
cmListFileBacktrace const& Backtrace;
- cmCompiledGeneratorExpression *CompiledExpression;
};
class cmCompiledGeneratorExpression
@@ -79,20 +81,24 @@ public:
~cmCompiledGeneratorExpression();
+ std::string GetInput() const
+ {
+ return this->Input;
+ }
+
private:
cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace,
- const std::vector<cmGeneratorExpressionEvaluator*> &evaluators,
- const char *input, bool needsParsing);
+ const char *input);
friend class cmGeneratorExpression;
cmCompiledGeneratorExpression(const cmCompiledGeneratorExpression &);
void operator=(const cmCompiledGeneratorExpression &);
- cmListFileBacktrace const& Backtrace;
- const std::vector<cmGeneratorExpressionEvaluator*> Evaluators;
- const char* const Input;
- const bool NeedsParsing;
+ cmListFileBacktrace Backtrace;
+ std::vector<cmGeneratorExpressionEvaluator*> Evaluators;
+ const std::string Input;
+ bool NeedsParsing;
mutable std::set<cmTarget*> Targets;
mutable std::string Output;
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index de8b5e3..55507dd 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -267,7 +267,7 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
"INCLUDE_DIRECTORIES", 0, 0);
cmSystemTools::ExpandListArgument(ge.Parse(prop)
- .Evaluate(this->Makefile,
+ ->Evaluate(this->Makefile,
config,
false,
this->Target,
@@ -315,7 +315,7 @@ std::string cmGeneratorTarget::GetCompileDefinitions(const char *config)
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
this->GetName(),
defPropName, 0, 0);
- return ge.Parse(prop).Evaluate(this->Makefile,
+ return ge.Parse(prop)->Evaluate(this->Makefile,
config,
false,
this->Target,
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 59b8f0a..0e83878 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -1732,9 +1732,10 @@ cmTargetTraceDependencies
for(cmCustomCommandLine::const_iterator cli = cit->begin();
cli != cit->end(); ++cli)
{
- const cmCompiledGeneratorExpression &cge = ge.Parse(*cli);
- cge.Evaluate(this->Makefile, 0, true);
- std::set<cmTarget*> geTargets = cge.GetTargets();
+ const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge
+ = ge.Parse(*cli);
+ cge->Evaluate(this->Makefile, 0, true);
+ std::set<cmTarget*> geTargets = cge->GetTargets();
for(std::set<cmTarget*>::const_iterator it = geTargets.begin();
it != geTargets.end(); ++it)
{
@@ -4478,7 +4479,7 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
this->GetName(),
"INTERFACE_LINK_LIBRARIES", 0, 0);
cmSystemTools::ExpandListArgument(ge.Parse(newStyleLibsProp)
- .Evaluate(this->Makefile,
+ ->Evaluate(this->Makefile,
desired_config.c_str(),
false,
this,
@@ -4666,7 +4667,7 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
this->GetName(),
"INTERFACE_LINK_LIBRARIES", 0, 0);
- cmSystemTools::ExpandListArgument(ge.Parse(newLibrariesProp).Evaluate(
+ cmSystemTools::ExpandListArgument(ge.Parse(newLibrariesProp)->Evaluate(
this->Makefile,
config,
false,
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index 2f650e7..42f511e 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -112,7 +112,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
else
{
// Use the command name given.
- exe = ge.Parse(exe.c_str()).Evaluate(mf, config);
+ exe = ge.Parse(exe.c_str())->Evaluate(mf, config);
cmSystemTools::ConvertToUnixSlashes(exe);
}
@@ -122,7 +122,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
for(std::vector<std::string>::const_iterator ci = command.begin()+1;
ci != command.end(); ++ci)
{
- os << " " << lg->EscapeForCMake(ge.Parse(*ci).Evaluate(mf, config));
+ os << " " << lg->EscapeForCMake(ge.Parse(*ci)->Evaluate(mf, config));
}
// Finish the test command.
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=906fe771697aa7c7b026b5c9f35b6a7f4f3a5f05
commit 906fe771697aa7c7b026b5c9f35b6a7f4f3a5f05
Author: Stephen Kelly <steveire at gmail.com>
AuthorDate: Thu Nov 1 00:32:10 2012 +0100
Commit: Stephen Kelly <steveire at gmail.com>
CommitDate: Fri Nov 23 17:49:34 2012 +0100
Genex: Add INTERFACE_LINK_LIBRARIES property
This new property is a replacement for
the (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? properties as
it can contain generator expressions. It is also part of the generated
IMPORTED targets generated by the export() and install(EXPORT) commands.
User code may already populate
the (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? properties, so
policy CMP0019 is added to handle that.
If the policy is NEW, the old properties are ignored and
the INTERFACE_LINK_LIBRARIES property is used.
Otherwise if the policy is OLD the old properties are used and the
new INTERFACE_LINK_LIBRARIES is ignored.
The policy emits a warning if the old-style property and new-style
property differ in their content.
The policy also affects the IMPORTED targets generated by export()
and install(EXPORT). If the policy is NEW, that means that the user
has bumped their cmake requirement to 2.8.11. As we'll therefore be
generating INTERFACE_LINK_LIBRARIES properties in the IMPORTED
targets, we need to ensure that consumers can use the new property,
so 2.8.11 will be required for the consumers too.
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index fb3f39f..f8f412a 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -12,6 +12,7 @@
#include "cmExportBuildFileGenerator.h"
#include "cmExportCommand.h"
+#include "cmGeneratorExpression.h"
//----------------------------------------------------------------------------
cmExportBuildFileGenerator::cmExportBuildFileGenerator()
@@ -27,10 +28,35 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
tei = this->Exports->begin();
tei != this->Exports->end(); ++tei)
{
+ if ((*tei)->GetPolicyStatusCMP0019() == cmPolicies::NEW)
+ {
+ os << "IF(NOT POLICY CMP0019)\n"
+ << " MESSAGE(FATAL_ERROR \"CMake >= 2.8.11 required to use "
+ "IMPORTED targets containing generator expressions\")\n"
+ << "ENDIF(NOT POLICY CMP0019)\n";
+ break;
+ }
+ }
+
+ for(std::vector<cmTarget*>::const_iterator
+ tei = this->Exports->begin();
+ tei != this->Exports->end(); ++tei)
+ {
cmTarget* te = *tei;
if(this->ExportedTargets.insert(te).second)
{
this->GenerateImportTargetCode(os, te);
+
+ if ((*tei)->GetPolicyStatusCMP0019() == cmPolicies::NEW)
+ {
+ ImportPropertyMap properties;
+
+ this->PopulateInterfaceProperty("INTERFACE_LINK_LIBRARIES", te,
+ cmGeneratorExpression::BuildInterface,
+ properties);
+
+ this->GenerateInterfaceProperties(te, os, properties);
+ }
}
else
{
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 8dffae4..50db180 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -125,6 +125,50 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
}
//----------------------------------------------------------------------------
+void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
+ cmTarget *target,
+ cmGeneratorExpression::PreprocessContext preprocessRule,
+ ImportPropertyMap &properties)
+{
+ const char *input = target->GetProperty(propName);
+ if (input)
+ {
+ if (!*input)
+ {
+ // Set to empty
+ properties[propName] = "";
+ return;
+ }
+ std::string prepro = cmGeneratorExpression::Preprocess(input,
+ preprocessRule,
+ this->Namespace.c_str());
+ if (!prepro.empty())
+ {
+ properties[propName] = prepro;
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
+ std::ostream& os,
+ const ImportPropertyMap &properties)
+{
+ if (!properties.empty())
+ {
+ std::string targetName = this->Namespace;
+ targetName += target->GetName();
+ os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n";
+ for(ImportPropertyMap::const_iterator pi = properties.begin();
+ pi != properties.end(); ++pi)
+ {
+ os << " " << pi->first << " \"" << pi->second << "\"\n";
+ }
+ os << ")\n\n";
+ }
+}
+
+//----------------------------------------------------------------------------
void
cmExportFileGenerator
::SetImportDetailProperties(const char* config, std::string const& suffix,
@@ -167,9 +211,13 @@ cmExportFileGenerator
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LANGUAGES",
iface->Languages, properties, missingTargets);
- this->SetImportLinkProperty(suffix, target,
+
+ if(target->GetPolicyStatusCMP0019() != cmPolicies::NEW)
+ {
+ this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LIBRARIES",
iface->Libraries, properties, missingTargets);
+ }
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_DEPENDENT_LIBRARIES",
iface->SharedDeps, properties, missingTargets);
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 70bc65d..3aee1b8 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -13,6 +13,7 @@
#define cmExportFileGenerator_h
#include "cmCommand.h"
+#include "cmGeneratorExpression.h"
/** \class cmExportFileGenerator
* \brief Generate a file exporting targets from a build or install tree.
@@ -91,6 +92,12 @@ protected:
cmMakefile* mf,
cmTarget* depender,
cmTarget* dependee) = 0;
+ void PopulateInterfaceProperty(const char *,
+ cmTarget *target,
+ cmGeneratorExpression::PreprocessContext,
+ ImportPropertyMap &properties);
+ void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
+ const ImportPropertyMap &properties);
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 7841731..4d99866 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -19,6 +19,7 @@
#include "cmInstallExportGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmTargetExport.h"
+#include "cmGeneratorExpression.h"
//----------------------------------------------------------------------------
cmExportInstallFileGenerator
@@ -39,6 +40,20 @@ std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
//----------------------------------------------------------------------------
bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
{
+ for(std::vector<cmTargetExport*>::const_iterator
+ tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
+ tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei)
+ {
+ if ((*tei)->Target->GetPolicyStatusCMP0019() == cmPolicies::NEW)
+ {
+ os << "IF(NOT POLICY CMP0019)\n"
+ << " MESSAGE(FATAL_ERROR \"CMake >= 2.8.11 required to use "
+ "IMPORTED targets containing generator expressions\")\n"
+ << "ENDIF(NOT POLICY CMP0019)\n";
+ break;
+ }
+ }
+
// Create all the imported targets.
for(std::vector<cmTargetExport*>::const_iterator
tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
@@ -48,6 +63,18 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
if(this->ExportedTargets.insert(te->Target).second)
{
this->GenerateImportTargetCode(os, te->Target);
+
+ if ((*tei)->Target->GetPolicyStatusCMP0019() == cmPolicies::NEW)
+ {
+ ImportPropertyMap properties;
+
+ this->PopulateInterfaceProperty("INTERFACE_LINK_LIBRARIES",
+ te->Target,
+ cmGeneratorExpression::InstallInterface,
+ properties);
+
+ this->GenerateInterfaceProperties(te->Target, os, properties);
+ }
}
else
{
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 6aef502..4c89dd6 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -491,6 +491,26 @@ cmPolicies::cmPolicies()
"CMAKE_SHARED_LIBRARY_<Lang>_FLAGS whether it is modified or not and "
"honor the POSITION_INDEPENDENT_CODE target property.",
2,8,9,0, cmPolicies::WARN);
+
+ this->DefinePolicy(
+ CMP0019, "CMP0019",
+ "Use INTERFACE_LINK_LIBRARIES instead of LINK_INTERFACE_LIBRARIES.",
+ "CMake 2.8.10 used the (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? "
+ "properties to determine the link interface. CMake 2.8.11 and higher "
+ "prefer instead to use the INTERFACE_LINK_LIBRARIES target property to "
+ "determine the link interface, while ignoring "
+ "(IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? completely. The new "
+ "INTERFACE_LINK_LIBRARIES target property can use generator expressions "
+ "to specify config-specific link libraries."
+ "\n"
+ "The OLD behavior for this policy is to ignore the "
+ "INTERFACE_LINK_LIBRARIES property for all targets and use the "
+ "value of (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? instead."
+ "\n"
+ "The NEW behavior for this policy is to ignore "
+ "the value of the (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? target "
+ "property",
+ 2,8,11,0, cmPolicies::WARN);
}
cmPolicies::~cmPolicies()
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 6932565..b6b8e39 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -68,6 +68,7 @@ public:
CMP0018, ///< Ignore language flags for shared libs, and adhere to
/// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C}
/// instead.
+ CMP0019, ///< Use new-style INTERFACE_LINK_LIBRARIES
/** \brief Always the last entry.
*
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index be20464..59b8f0a 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -21,6 +21,7 @@
#include "cmDocumentLocationUndefined.h"
#include "cmListFileCache.h"
#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionDAGChecker.h"
#include <cmsys/RegularExpression.hxx>
#include <map>
#include <set>
@@ -127,6 +128,7 @@ cmTarget::cmTarget()
this->PolicyStatusCMP0003 = cmPolicies::WARN;
this->PolicyStatusCMP0004 = cmPolicies::WARN;
this->PolicyStatusCMP0008 = cmPolicies::WARN;
+ this->PolicyStatusCMP0019 = cmPolicies::WARN;
this->LinkLibrariesAnalyzed = false;
this->HaveInstallRule = false;
this->DLLPlatform = false;
@@ -1409,6 +1411,8 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->Makefile->GetPolicyStatus(cmPolicies::CMP0004);
this->PolicyStatusCMP0008 =
this->Makefile->GetPolicyStatus(cmPolicies::CMP0008);
+ this->PolicyStatusCMP0019 =
+ this->Makefile->GetPolicyStatus(cmPolicies::CMP0019);
}
//----------------------------------------------------------------------------
@@ -4238,6 +4242,28 @@ cmTarget::GetImportInfo(const char* config)
return &i->second;
}
+
+bool handleCMP0019(const std::vector<std::string> &newLinkLibraries,
+ const std::vector<std::string> &oldLinkLibraries)
+{
+ if (newLinkLibraries.size() != oldLinkLibraries.size())
+ {
+ return false;
+ }
+ for(std::vector<std::string>::const_iterator
+ oll = oldLinkLibraries.begin(), nll = newLinkLibraries.begin();
+ oll != oldLinkLibraries.end() && nll != newLinkLibraries.end();
+ ++oll, ++nll)
+ {
+ if (*oll != *nll)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+
//----------------------------------------------------------------------------
void cmTarget::ComputeImportInfo(std::string const& desired_config,
ImportInfo& info)
@@ -4441,21 +4467,79 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
// Get the link interface.
{
+ std::vector<std::string> newInterfaceLibs;
+ const char* newStyleLibsProp = this->GetProperty("INTERFACE_LINK_LIBRARIES");
+ if(newStyleLibsProp)
+ {
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ "INTERFACE_LINK_LIBRARIES", 0, 0);
+ cmSystemTools::ExpandListArgument(ge.Parse(newStyleLibsProp)
+ .Evaluate(this->Makefile,
+ desired_config.c_str(),
+ false,
+ this,
+ &dagChecker),
+ newInterfaceLibs);
+ }
+
std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
- linkProp += suffix;
- if(const char* config_libs = this->GetProperty(linkProp.c_str()))
+ std::vector<std::string> oldInterfaceLibs;
+ const char *oldProp = this->GetProperty((linkProp + suffix).c_str());
+ if(oldProp)
{
- cmSystemTools::ExpandListArgument(config_libs,
- info.LinkInterface.Libraries);
+ linkProp += suffix;
+ cmSystemTools::ExpandListArgument(oldProp,
+ oldInterfaceLibs);
}
- else if(const char* libs =
- this->GetProperty("IMPORTED_LINK_INTERFACE_LIBRARIES"))
+ else
+ {
+ oldProp = this->GetProperty("IMPORTED_LINK_INTERFACE_LIBRARIES");
+ if(oldProp)
+ {
+ cmSystemTools::ExpandListArgument(oldProp,
+ oldInterfaceLibs);
+ }
+ }
+
+ std::vector<std::string> usedLinkLibraries;
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0019))
{
- cmSystemTools::ExpandListArgument(libs,
- info.LinkInterface.Libraries);
+ case cmPolicies::WARN:
+ {
+ if (newStyleLibsProp && oldProp
+ && !handleCMP0019(newInterfaceLibs, oldInterfaceLibs))
+ {
+ cmOStringStream e;
+ e << "The " << linkProp << " and "
+ "LINK_INTERFACE_LIBRARIES are not the same for target \""
+ << this->GetName() << "\". NEW content is \""
+ << (newStyleLibsProp ? newStyleLibsProp : "(unset)") << "\"\n"
+ "OLD content is \""
+ << (oldProp ? oldProp : "(unset)") << "\"\n"
+ << this->Makefile->GetPolicies()->GetPolicyWarning(
+ cmPolicies::CMP0019);
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ }
+ // fall through to OLD behaviour
+ }
+ case cmPolicies::OLD:
+ usedLinkLibraries = oldInterfaceLibs;
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ default:
+ usedLinkLibraries = newInterfaceLibs;
}
+ info.LinkInterface.Libraries.insert(info.LinkInterface.Libraries.end(),
+ usedLinkLibraries.begin(), usedLinkLibraries.end());
}
+
// Get the link dependencies.
{
std::string linkProp = "IMPORTED_LINK_DEPENDENT_LIBRARIES";
@@ -4562,21 +4646,82 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
// An explicit list of interface libraries may be set for shared
// libraries and executables that export symbols.
- const char* explicitLibraries = 0;
+ bool explicitLibraries = false;
+ std::vector<std::string> usedLinkLibraries;
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
this->IsExecutableWithExports())
{
+ const char *newLibrariesProp =
+ this->GetProperty("INTERFACE_LINK_LIBRARIES");
+
+ std::vector<std::string> newInterfaceLibs;
+ std::vector<std::string> oldInterfaceLibs;
+
+ if(newLibrariesProp)
+ {
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ "INTERFACE_LINK_LIBRARIES", 0, 0);
+
+ cmSystemTools::ExpandListArgument(ge.Parse(newLibrariesProp).Evaluate(
+ this->Makefile,
+ config,
+ false,
+ this,
+ &dagChecker), newInterfaceLibs);
+ }
// Lookup the per-configuration property.
std::string propName = "LINK_INTERFACE_LIBRARIES";
propName += suffix;
- explicitLibraries = this->GetProperty(propName.c_str());
+ const char *oldLibrariesProp = this->GetProperty(propName.c_str());
// If not set, try the generic property.
- if(!explicitLibraries)
+ if(!oldLibrariesProp)
+ {
+ oldLibrariesProp = this->GetProperty("LINK_INTERFACE_LIBRARIES");
+ }
+ if(oldLibrariesProp)
+ {
+ cmSystemTools::ExpandListArgument(oldLibrariesProp, oldInterfaceLibs);
+ }
+
+ {
+ switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0019))
{
- explicitLibraries = this->GetProperty("LINK_INTERFACE_LIBRARIES");
+ case cmPolicies::WARN:
+ {
+ if (newLibrariesProp && oldLibrariesProp
+ && !handleCMP0019(newInterfaceLibs, oldInterfaceLibs))
+ {
+ cmOStringStream e;
+ e << "The INTERFACE_LINK_LIBRARIES and LINK_INTERFACE_LIBRARIES are "
+ "not the same for target \"" << this->GetName() << "\".\n"
+ "NEW content is \""
+ << (newLibrariesProp ? newLibrariesProp : "(unset)") << "\"\n"
+ "OLD content is \""
+ << (oldLibrariesProp ? oldLibrariesProp : "(unset)") << "\"\n"
+ << this->Makefile->GetPolicies()->GetPolicyWarning(
+ cmPolicies::CMP0019);
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
+ }
+ // fall through to OLD behaviour
+ }
+ case cmPolicies::OLD:
+ explicitLibraries = oldLibrariesProp ? true : false;
+ usedLinkLibraries = oldInterfaceLibs;
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ default:
+ usedLinkLibraries = newInterfaceLibs;
+ explicitLibraries = newLibrariesProp ? true : false;
}
}
+ }
// There is no implicit link interface for executables or modules
// so if none was explicitly set then there is no link interface.
@@ -4592,7 +4737,8 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface)
if(explicitLibraries)
{
// The interface libraries have been explicitly set.
- cmSystemTools::ExpandListArgument(explicitLibraries, iface.Libraries);
+ iface.Libraries.insert(iface.Libraries.end(),
+ usedLinkLibraries.begin(), usedLinkLibraries.end());
if(this->GetType() == cmTarget::SHARED_LIBRARY)
{
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 9efd638..7c55933 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -99,6 +99,10 @@ public:
cmPolicies::PolicyStatus GetPolicyStatusCMP0008() const
{ return this->PolicyStatusCMP0008; }
+ /** Get the status of policy CMP0019 when the target was created. */
+ cmPolicies::PolicyStatus GetPolicyStatusCMP0019() const
+ { return this->PolicyStatusCMP0019; }
+
/**
* Get the list of the custom commands for this target
*/
@@ -618,6 +622,7 @@ private:
cmPolicies::PolicyStatus PolicyStatusCMP0003;
cmPolicies::PolicyStatus PolicyStatusCMP0004;
cmPolicies::PolicyStatus PolicyStatusCMP0008;
+ cmPolicies::PolicyStatus PolicyStatusCMP0019;
// Internal representation details.
friend class cmTargetInternals;
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index f42b0f6..d7a1443 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -232,7 +232,11 @@ bool cmTargetLinkLibrariesCommand
{
this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
}
-
+ if(this->CurrentProcessingState != ProcessingLinkLibraries &&
+ !this->Target->GetProperty("INTERFACE_LINK_LIBRARIES"))
+ {
+ this->Target->SetProperty("INTERFACE_LINK_LIBRARIES", "");
+ }
return true;
}
@@ -250,6 +254,25 @@ cmTargetLinkLibrariesCommand
}
//----------------------------------------------------------------------------
+static std::string generatorIface(const std::string &value,
+ cmTarget::LinkLibraryType llt)
+{
+ if (llt == cmTarget::DEBUG)
+ {
+ return "$<$<CONFIG:Debug>:"
+ + value
+ + ">";
+ }
+ else if (llt == cmTarget::OPTIMIZED)
+ {
+ return "$<$<NOT:$<CONFIG:Debug>>:"
+ + value
+ + ">";
+ }
+ return value;
+}
+
+//----------------------------------------------------------------------------
void
cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
cmTarget::LinkLibraryType llt)
@@ -266,6 +289,9 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
}
}
+ this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
+ generatorIface(lib, llt).c_str());
+
// Get the list of configurations considered to be DEBUG.
std::vector<std::string> const& debugConfigs =
this->Makefile->GetCMakeInstance()->GetDebugConfigs();
diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
index 1faa888..95cfd15 100644
--- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt
@@ -56,3 +56,21 @@ assert_property(targetA LINK_INTERFACE_LIBRARIES "")
target_link_libraries(targetA depB depC)
assert_property(targetA LINK_INTERFACE_LIBRARIES "")
+
+# cmake_policy(PUSH)
+
+cmake_policy(SET CMP0019 NEW)
+
+add_library(depD SHARED depD.cpp)
+generate_export_header(depD)
+set_property(TARGET depD APPEND PROPERTY INTERFACE_LINK_LIBRARIES $<1:depA>)
+
+add_library(depE SHARED depE.cpp)
+generate_export_header(depE)
+target_link_libraries(depE LINK_PRIVATE depB)
+target_link_libraries(depE LINK_INTERFACE_LIBRARIES $<1:depB>)
+
+add_executable(targetB targetB.cpp)
+target_link_libraries(targetB depD depE)
+
+# cmake_policy(POP)
diff --git a/Tests/CMakeCommands/target_link_libraries/depD.cpp b/Tests/CMakeCommands/target_link_libraries/depD.cpp
new file mode 100644
index 0000000..b02c76c
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depD.cpp
@@ -0,0 +1,13 @@
+
+#include "depD.h"
+
+int DepD::foo()
+{
+ return 0;
+}
+
+DepA DepD::getA()
+{
+ DepA a;
+ return a;
+}
diff --git a/Tests/CMakeCommands/target_link_libraries/depD.h b/Tests/CMakeCommands/target_link_libraries/depD.h
new file mode 100644
index 0000000..d24ff5f
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depD.h
@@ -0,0 +1,11 @@
+
+#include "depd_export.h"
+
+#include "depA.h"
+
+struct DEPD_EXPORT DepD
+{
+ int foo();
+
+ DepA getA();
+};
diff --git a/Tests/CMakeCommands/target_link_libraries/depE.cpp b/Tests/CMakeCommands/target_link_libraries/depE.cpp
new file mode 100644
index 0000000..1a3da4a
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depE.cpp
@@ -0,0 +1,13 @@
+
+#include "depE.h"
+
+int DepE::foo()
+{
+ return 0;
+}
+
+DepB DepE::getB()
+{
+ DepB a;
+ return a;
+}
diff --git a/Tests/CMakeCommands/target_link_libraries/depE.h b/Tests/CMakeCommands/target_link_libraries/depE.h
new file mode 100644
index 0000000..2273e17
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/depE.h
@@ -0,0 +1,11 @@
+
+#include "depe_export.h"
+
+#include "depB.h"
+
+struct DEPE_EXPORT DepE
+{
+ int foo();
+
+ DepB getB();
+};
diff --git a/Tests/CMakeCommands/target_link_libraries/targetB.cpp b/Tests/CMakeCommands/target_link_libraries/targetB.cpp
new file mode 100644
index 0000000..c6a1264
--- /dev/null
+++ b/Tests/CMakeCommands/target_link_libraries/targetB.cpp
@@ -0,0 +1,14 @@
+
+#include "depD.h"
+#include "depE.h"
+
+int main(int argc, char **argv)
+{
+ DepD d;
+ DepA a = d.getA();
+
+ DepE e;
+ DepB b = e.getB();
+
+ return d.foo() + a.foo() + e.foo() + b.foo();
+}
-----------------------------------------------------------------------
Summary of changes:
hooks/post-receive
--
CMake
More information about the Cmake-commits
mailing list