summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Modules/FindJNI.cmake2
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/cmArchiveWrite.cxx26
-rw-r--r--Source/cmFileCommand.cxx12
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx13
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx7
-rw-r--r--Source/cmSystemTools.cxx38
-rw-r--r--Source/cmTarget.cxx30
-rw-r--r--Source/cmTimestamp.cxx8
-rw-r--r--Tests/CMakeLists.txt2
-rw-r--r--Tests/CTestTestMemcheck/CMakeLists.txt.in2
-rw-r--r--Tests/ObjectLibrary/CMakeLists.txt6
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1-result.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1-stderr.txt10
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1.cmake8
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2-result.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2-stderr.txt10
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2.cmake8
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3-result.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3-stderr.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3.cmake10
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4-result.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4-stderr.txt8
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4.cmake14
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5-result.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5-stderr.txt8
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5.cmake10
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6-result.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6-stderr.txt8
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6.cmake14
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake6
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/empty.cpp7
32 files changed, 248 insertions, 28 deletions
diff --git a/Modules/FindJNI.cmake b/Modules/FindJNI.cmake
index 6a496af..3dcb0d0 100644
--- a/Modules/FindJNI.cmake
+++ b/Modules/FindJNI.cmake
@@ -55,7 +55,7 @@ macro(java_append_library_directories _var)
# endianess of the underlying system.
set(_java_libarch "${CMAKE_SYSTEM_PROCESSOR}" "mips" "mipsel" "mipseb")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64le")
- set(_java_libarch "ppc64le")
+ set(_java_libarch "ppc64" "ppc64le")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)64")
set(_java_libarch "ppc64" "ppc")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index f5e0bc1..27405be 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 0)
-set(CMake_VERSION_PATCH 20140701)
+set(CMake_VERSION_PATCH 20140702)
#set(CMake_VERSION_RC 1)
diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx
index 58f7573..3b0ead5 100644
--- a/Source/cmArchiveWrite.cxx
+++ b/Source/cmArchiveWrite.cxx
@@ -25,6 +25,28 @@ static std::string cm_archive_error_string(struct archive* a)
}
//----------------------------------------------------------------------------
+static void cm_archive_entry_copy_pathname(struct archive_entry* e,
+ const std::string& dest)
+{
+#if cmsys_STL_HAS_WSTRING
+ archive_entry_copy_pathname_w(e, cmsys::Encoding::ToWide(dest).c_str());
+#else
+ archive_entry_copy_pathname(e, dest.c_str());
+#endif
+}
+
+//----------------------------------------------------------------------------
+static void cm_archive_entry_copy_sourcepath(struct archive_entry* e,
+ const std::string& file)
+{
+#if cmsys_STL_HAS_WSTRING
+ archive_entry_copy_sourcepath_w(e, cmsys::Encoding::ToWide(file).c_str());
+#else
+ archive_entry_copy_sourcepath(e, file.c_str());
+#endif
+}
+
+//----------------------------------------------------------------------------
class cmArchiveWrite::Entry
{
struct archive_entry* Object;
@@ -237,8 +259,8 @@ bool cmArchiveWrite::AddFile(const char* file,
std::cout << dest << "\n";
}
Entry e;
- archive_entry_copy_sourcepath(e, file);
- archive_entry_set_pathname(e, dest.c_str());
+ cm_archive_entry_copy_sourcepath(e, file);
+ cm_archive_entry_copy_pathname(e, dest);
if(archive_read_disk_entry_from_file(this->Disk, e, -1, 0) != ARCHIVE_OK)
{
this->Error = "archive_read_disk_entry_from_file: ";
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 61c6eb3..e47365a 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -3172,15 +3172,7 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
return false;
}
- struct stat st;
- if(::stat(filename.c_str(), &st))
- {
- std::string errStr = "UPLOAD cannot stat file '";
- errStr += filename + "'.";
- this->SetError(errStr);
- fclose(fin);
- return false;
- }
+ unsigned long file_size = cmsys::SystemTools::FileLength(filename.c_str());
::CURL *curl;
::curl_global_init(CURL_GLOBAL_DEFAULT);
@@ -3270,7 +3262,7 @@ cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
// and give the size of the upload (optional)
res = ::curl_easy_setopt(curl,
- CURLOPT_INFILESIZE, static_cast<long>(st.st_size));
+ CURLOPT_INFILESIZE, static_cast<long>(file_size));
check_curl_result(res, "UPLOAD cannot set input file size: ");
res = ::curl_easy_perform(curl);
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index c925869..b648eb2 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -1028,6 +1028,19 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
{
if (dagCheckerParent->EvaluatingLinkLibraries())
{
+#define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \
+ (#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) ||
+ if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_COMPARE)
+ false)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_PROPERTY:...> expression in link libraries "
+ "evaluation depends on target property which is transitive "
+ "over the link libraries, creating a recursion.");
+ return std::string();
+ }
+#undef TRANSITIVE_PROPERTY_COMPARE
+
if(!prop)
{
return std::string();
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index cfcf9f4..15a1b32 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -608,6 +608,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
std::string(cmake::GetCMakeFilesDirectoryPostSlash())
+ target.GetName() + ".rsp";
+ // Gather order-only dependencies.
+ cmNinjaDeps orderOnlyDeps;
+ this->GetLocalGenerator()->AppendTargetDepends(this->GetTarget(),
+ orderOnlyDeps);
+
// Write the build statement for this target.
globalGen.WriteBuild(this->GetBuildFileStream(),
comment.str(),
@@ -615,7 +620,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
outputs,
explicitDeps,
implicitDeps,
- emptyDeps,
+ orderOnlyDeps,
vars,
rspfile,
commandLineLengthLimit);
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 0ab722e..12a63b0 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -91,6 +91,31 @@ extern char** environ;
# endif
#endif
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+static std::string
+cm_archive_entry_pathname(struct archive_entry *entry)
+{
+#if cmsys_STL_HAS_WSTRING
+ return cmsys::Encoding::ToNarrow(
+ archive_entry_pathname_w(entry)).c_str();
+#else
+ return archive_entry_pathname(entry);
+#endif
+}
+
+static int cm_archive_read_open_file(struct archive* a,
+ const char* file,
+ int block_size)
+{
+#if cmsys_STL_HAS_WSTRING
+ std::wstring wfile = cmsys::Encoding::ToWide(file);
+ return archive_read_open_filename_w(a, wfile.c_str(), block_size);
+#else
+ return archive_read_open_filename(a, file, block_size);
+#endif
+}
+#endif
+
#ifdef _WIN32
class cmSystemToolsWindowsHandle
{
@@ -1581,7 +1606,7 @@ namespace{
}
strftime(tmp, sizeof(tmp), fmt, localtime(&tim));
fprintf(out, " %s ", tmp);
- fprintf(out, "%s", archive_entry_pathname(entry));
+ fprintf(out, "%s", cm_archive_entry_pathname(entry).c_str());
/* Extra information for links. */
if (archive_entry_hardlink(entry)) /* Hard link */
@@ -1641,7 +1666,7 @@ bool extract_tar(const char* outFileName, bool verbose,
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
struct archive_entry *entry;
- int r = archive_read_open_file(a, outFileName, 10240);
+ int r = cm_archive_read_open_file(a, outFileName, 10240);
if(r)
{
cmSystemTools::Error("Problem with archive_read_open_file(): ",
@@ -1666,7 +1691,7 @@ bool extract_tar(const char* outFileName, bool verbose,
if(extract)
{
cmSystemTools::Stdout("x ");
- cmSystemTools::Stdout(archive_entry_pathname(entry));
+ cmSystemTools::Stdout(cm_archive_entry_pathname(entry).c_str());
}
else
{
@@ -1676,7 +1701,7 @@ bool extract_tar(const char* outFileName, bool verbose,
}
else if(!extract)
{
- cmSystemTools::Stdout(archive_entry_pathname(entry));
+ cmSystemTools::Stdout(cm_archive_entry_pathname(entry).c_str());
cmSystemTools::Stdout("\n");
}
if(extract)
@@ -1706,7 +1731,8 @@ bool extract_tar(const char* outFileName, bool verbose,
else if(const char* linktext = archive_entry_symlink(entry))
{
std::cerr << "cmake -E tar: warning: skipping symbolic link \""
- << archive_entry_pathname(entry) << "\" -> \""
+ << cm_archive_entry_pathname(entry)
+ << "\" -> \""
<< linktext << "\"." << std::endl;
}
#endif
@@ -1715,7 +1741,7 @@ bool extract_tar(const char* outFileName, bool verbose,
cmSystemTools::Error("Problem with archive_write_header(): ",
archive_error_string(ext));
cmSystemTools::Error("Current file: ",
- archive_entry_pathname(entry));
+ cm_archive_entry_pathname(entry).c_str());
break;
}
}
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index aa0ed56..d27293a 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -3265,6 +3265,11 @@ const char *cmTarget::GetProperty(const std::string& prop,
}
if(prop == "INCLUDE_DIRECTORIES")
{
+ if (this->Internal->IncludeDirectoriesEntries.empty())
+ {
+ return 0;
+ }
+
static std::string output;
output = "";
std::string sep;
@@ -3283,6 +3288,11 @@ const char *cmTarget::GetProperty(const std::string& prop,
}
if(prop == "COMPILE_OPTIONS")
{
+ if (this->Internal->CompileOptionsEntries.empty())
+ {
+ return 0;
+ }
+
static std::string output;
output = "";
std::string sep;
@@ -3301,6 +3311,11 @@ const char *cmTarget::GetProperty(const std::string& prop,
}
if(prop == "COMPILE_FEATURES")
{
+ if (this->Internal->CompileFeaturesEntries.empty())
+ {
+ return 0;
+ }
+
static std::string output;
output = "";
std::string sep;
@@ -3319,6 +3334,11 @@ const char *cmTarget::GetProperty(const std::string& prop,
}
if(prop == "COMPILE_DEFINITIONS")
{
+ if (this->Internal->CompileDefinitionsEntries.empty())
+ {
+ return 0;
+ }
+
static std::string output;
output = "";
std::string sep;
@@ -3337,6 +3357,11 @@ const char *cmTarget::GetProperty(const std::string& prop,
}
if(prop == "LINK_LIBRARIES")
{
+ if (this->Internal->LinkImplementationPropertyEntries.empty())
+ {
+ return 0;
+ }
+
static std::string output;
output = "";
std::string sep;
@@ -3359,6 +3384,11 @@ const char *cmTarget::GetProperty(const std::string& prop,
if(prop == "SOURCES")
{
+ if (this->Internal->SourceEntries.empty())
+ {
+ return 0;
+ }
+
cmOStringStream ss;
const char* sep = "";
typedef cmTargetInternals::TargetPropertyEntry
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index ac26503..6fd6ab7 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -33,15 +33,13 @@ std::string cmTimestamp::CurrentTime(
std::string cmTimestamp::FileModificationTime(const char* path,
const std::string& formatString, bool utcFlag)
{
- struct stat info;
- memset(&info, 0, sizeof(info));
-
- if(stat(path, &info) != 0)
+ if(!cmsys::SystemTools::FileExists(path))
{
return std::string();
}
- return CreateTimestampFromTimeT(info.st_mtime, formatString, utcFlag);
+ time_t mtime = cmsys::SystemTools::ModifiedTime(path);
+ return CreateTimestampFromTimeT(mtime, formatString, utcFlag);
}
//----------------------------------------------------------------------------
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index cf7bd75..cb455e0 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -3,7 +3,7 @@
macro(ADD_TEST_MACRO NAME COMMAND)
string(REPLACE "." "/" dir "${NAME}")
string(REGEX REPLACE "[^.]*\\." "" proj "${NAME}")
- add_test(${NAME} ${CMAKE_CTEST_COMMAND}
+ add_test(NAME "${NAME}" COMMAND "${CMAKE_CTEST_COMMAND}"
--build-and-test
"${CMake_SOURCE_DIR}/Tests/${dir}"
"${CMake_BINARY_DIR}/Tests/${dir}"
diff --git a/Tests/CTestTestMemcheck/CMakeLists.txt.in b/Tests/CTestTestMemcheck/CMakeLists.txt.in
index e28e56a..d15d148 100644
--- a/Tests/CTestTestMemcheck/CMakeLists.txt.in
+++ b/Tests/CTestTestMemcheck/CMakeLists.txt.in
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 2.8.9)
-project(CTestTestMemcheck@SUBTEST_NAME@)
+project(CTestTestMemcheck@SUBTEST_NAME@ NONE)
include(CTest)
add_test(NAME RunCMake COMMAND "${CMAKE_COMMAND}" --version)
diff --git a/Tests/ObjectLibrary/CMakeLists.txt b/Tests/ObjectLibrary/CMakeLists.txt
index 0aeefaa..75c34d8 100644
--- a/Tests/ObjectLibrary/CMakeLists.txt
+++ b/Tests/ObjectLibrary/CMakeLists.txt
@@ -59,4 +59,10 @@ add_executable(UseABinternal ${dummy}
$<TARGET_OBJECTS:ABmain> $<TARGET_OBJECTS:A> $<TARGET_OBJECTS:B>
)
+# Test target-level dependencies of executable without sources.
+file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/UseABinternalDep.cmake)
+add_custom_target(UseABinternalDep COMMAND ${CMAKE_COMMAND} -E touch UseABinternalDep.cmake)
+add_custom_command(TARGET UseABinternal POST_BUILD COMMAND ${CMAKE_COMMAND} -P UseABinternalDep.cmake)
+add_dependencies(UseABinternal UseABinternalDep)
+
add_subdirectory(ExportLanguages)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1-stderr.txt
new file mode 100644
index 0000000..7e002f5
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1-stderr.txt
@@ -0,0 +1,10 @@
+CMake Error at LinkImplementationCycle1.cmake:5 \(target_link_libraries\):
+ Error evaluating generator expression:
+
+ \$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>
+
+ \$<TARGET_PROPERTY:...> expression in link libraries evaluation depends on
+ target property which is transitive over the link libraries, creating a
+ recursion.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:8 \(include\)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1.cmake
new file mode 100644
index 0000000..4b60214
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle1.cmake
@@ -0,0 +1,8 @@
+
+add_library(empty1 empty.cpp)
+add_library(empty2 empty.cpp)
+
+target_link_libraries(empty1
+ LINK_PUBLIC
+ $<$<STREQUAL:$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>,/foo/bar>:empty2>
+)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2-stderr.txt
new file mode 100644
index 0000000..2f72de6
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2-stderr.txt
@@ -0,0 +1,10 @@
+CMake Error at LinkImplementationCycle2.cmake:5 \(target_link_libraries\):
+ Error evaluating generator expression:
+
+ \$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>
+
+ \$<TARGET_PROPERTY:...> expression in link libraries evaluation depends on
+ target property which is transitive over the link libraries, creating a
+ recursion.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:8 \(include\)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2.cmake
new file mode 100644
index 0000000..557eac1
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle2.cmake
@@ -0,0 +1,8 @@
+
+add_library(empty1 empty.cpp)
+add_library(empty2 empty.cpp)
+
+target_link_libraries(empty1
+ LINK_PUBLIC
+ $<$<STREQUAL:$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>,/foo/bar>:empty2>
+)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3-result.txt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3-result.txt
@@ -0,0 +1 @@
+0
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3-stderr.txt
new file mode 100644
index 0000000..10f3293
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3-stderr.txt
@@ -0,0 +1 @@
+^$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3.cmake
new file mode 100644
index 0000000..0f921d4
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle3.cmake
@@ -0,0 +1,10 @@
+
+add_library(empty1 empty.cpp)
+add_library(empty2 empty.cpp)
+
+# This is OK, because evaluating the INCLUDE_DIRECTORIES is not affected by
+# the content of the INTERFACE_LINK_LIBRARIES.
+target_link_libraries(empty1
+ INTERFACE
+ $<$<STREQUAL:$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>,/foo/bar>:empty2>
+)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4-stderr.txt
new file mode 100644
index 0000000..5cfeb0a
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error:
+ Error evaluating generator expression:
+
+ \$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>
+
+ \$<TARGET_PROPERTY:...> expression in link libraries evaluation depends on
+ target property which is transitive over the link libraries, creating a
+ recursion.
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4.cmake
new file mode 100644
index 0000000..ab6d0b2
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle4.cmake
@@ -0,0 +1,14 @@
+
+add_library(empty1 empty.cpp)
+add_library(empty2 empty.cpp)
+
+# The INTERFACE_INCLUDE_DIRECTORIES do not depend on the link interface.
+# On its own, this is fine. It is only when used by empty3 that an error
+# is appropriately issued.
+target_link_libraries(empty1
+ INTERFACE
+ $<$<STREQUAL:$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>,/foo/bar>:empty2>
+)
+
+add_library(empty3 empty.cpp)
+target_link_libraries(empty3 empty1)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5-stderr.txt
new file mode 100644
index 0000000..5cfeb0a
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error:
+ Error evaluating generator expression:
+
+ \$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>
+
+ \$<TARGET_PROPERTY:...> expression in link libraries evaluation depends on
+ target property which is transitive over the link libraries, creating a
+ recursion.
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5.cmake
new file mode 100644
index 0000000..dc180e3
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle5.cmake
@@ -0,0 +1,10 @@
+
+add_library(empty1 INTERFACE IMPORTED)
+add_library(empty2 INTERFACE IMPORTED)
+
+set_property(TARGET empty1 PROPERTY INTERFACE_LINK_LIBRARIES
+ $<$<STREQUAL:$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>,/foo/bar>:empty2>
+)
+
+add_library(empty3 empty.cpp)
+target_link_libraries(empty3 empty1)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6-stderr.txt
new file mode 100644
index 0000000..5cfeb0a
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6-stderr.txt
@@ -0,0 +1,8 @@
+CMake Error:
+ Error evaluating generator expression:
+
+ \$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>
+
+ \$<TARGET_PROPERTY:...> expression in link libraries evaluation depends on
+ target property which is transitive over the link libraries, creating a
+ recursion.
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6.cmake
new file mode 100644
index 0000000..91252d0
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/LinkImplementationCycle6.cmake
@@ -0,0 +1,14 @@
+
+add_library(empty1 SHARED empty.cpp)
+add_library(empty2 SHARED empty.cpp)
+
+# The INTERFACE_INCLUDE_DIRECTORIES do not depend on the link interface.
+# On its own, this is fine. It is only when used by empty3 that an error
+# is appropriately issued.
+target_link_libraries(empty1
+ INTERFACE
+ $<$<STREQUAL:$<TARGET_PROPERTY:INTERFACE_INCLUDE_DIRECTORIES>,/foo/bar>:empty2>
+)
+
+add_library(empty3 SHARED empty.cpp)
+target_link_libraries(empty3 empty1)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
index 0ee3238..645a57d 100644
--- a/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
@@ -15,3 +15,9 @@ run_cmake(BadInvalidName5)
run_cmake(BadInvalidName6)
run_cmake(BadInvalidName7)
run_cmake(BadInvalidName8)
+run_cmake(LinkImplementationCycle1)
+run_cmake(LinkImplementationCycle2)
+run_cmake(LinkImplementationCycle3)
+run_cmake(LinkImplementationCycle4)
+run_cmake(LinkImplementationCycle5)
+run_cmake(LinkImplementationCycle6)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/empty.cpp b/Tests/RunCMake/TargetPropertyGeneratorExpressions/empty.cpp
new file mode 100644
index 0000000..bfbbdde
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/empty.cpp
@@ -0,0 +1,7 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+int empty()
+{
+ return 0;
+}