summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/prop_tgt/ARCHIVE_OUTPUT_DIRECTORY_CONFIG.rst3
-rw-r--r--Help/prop_tgt/LIBRARY_OUTPUT_DIRECTORY_CONFIG.rst3
-rw-r--r--Help/prop_tgt/RUNTIME_OUTPUT_DIRECTORY_CONFIG.rst3
-rw-r--r--Help/prop_tgt/XXX_OUTPUT_DIRECTORY.txt7
-rw-r--r--Help/release/dev/OUTPUT_DIRECTORY-genex.rst7
-rw-r--r--Source/cmTarget.cxx41
-rw-r--r--Tests/ExportImport/Export/CMakeLists.txt17
-rw-r--r--Tests/ExportImport/Export/testExe4.c24
-rw-r--r--Tests/ExportImport/Import/A/CMakeLists.txt12
-rw-r--r--Tests/ExportImport/Import/A/imp_testExe1.c3
-rw-r--r--Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake1
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_FILE-recursion-result.txt1
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_FILE-recursion-stderr.txt4
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_FILE-recursion.cmake3
14 files changed, 119 insertions, 10 deletions
diff --git a/Help/prop_tgt/ARCHIVE_OUTPUT_DIRECTORY_CONFIG.rst b/Help/prop_tgt/ARCHIVE_OUTPUT_DIRECTORY_CONFIG.rst
index 29991eb..12f8bb7 100644
--- a/Help/prop_tgt/ARCHIVE_OUTPUT_DIRECTORY_CONFIG.rst
+++ b/Help/prop_tgt/ARCHIVE_OUTPUT_DIRECTORY_CONFIG.rst
@@ -11,3 +11,6 @@ per-configuration subdirectory to the specified directory. This
property is initialized by the value of the
:variable:`CMAKE_ARCHIVE_OUTPUT_DIRECTORY_<CONFIG>` variable if
it is set when a target is created.
+
+Contents of ``ARCHIVE_OUTPUT_DIRECTORY_<CONFIG>`` may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
diff --git a/Help/prop_tgt/LIBRARY_OUTPUT_DIRECTORY_CONFIG.rst b/Help/prop_tgt/LIBRARY_OUTPUT_DIRECTORY_CONFIG.rst
index 6fc0142..28dd404 100644
--- a/Help/prop_tgt/LIBRARY_OUTPUT_DIRECTORY_CONFIG.rst
+++ b/Help/prop_tgt/LIBRARY_OUTPUT_DIRECTORY_CONFIG.rst
@@ -11,3 +11,6 @@ per-configuration subdirectory to the specified directory. This
property is initialized by the value of the
:variable:`CMAKE_LIBRARY_OUTPUT_DIRECTORY_<CONFIG>` variable if
it is set when a target is created.
+
+Contents of ``LIBRARY_OUTPUT_DIRECTORY_<CONFIG>`` may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
diff --git a/Help/prop_tgt/RUNTIME_OUTPUT_DIRECTORY_CONFIG.rst b/Help/prop_tgt/RUNTIME_OUTPUT_DIRECTORY_CONFIG.rst
index c100346..94fb277 100644
--- a/Help/prop_tgt/RUNTIME_OUTPUT_DIRECTORY_CONFIG.rst
+++ b/Help/prop_tgt/RUNTIME_OUTPUT_DIRECTORY_CONFIG.rst
@@ -11,3 +11,6 @@ per-configuration subdirectory to the specified directory. This
property is initialized by the value of the
:variable:`CMAKE_RUNTIME_OUTPUT_DIRECTORY_<CONFIG>` variable if
it is set when a target is created.
+
+Contents of ``RUNTIME_OUTPUT_DIRECTORY_<CONFIG>`` may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
diff --git a/Help/prop_tgt/XXX_OUTPUT_DIRECTORY.txt b/Help/prop_tgt/XXX_OUTPUT_DIRECTORY.txt
index 0b3d31c..3ae5448 100644
--- a/Help/prop_tgt/XXX_OUTPUT_DIRECTORY.txt
+++ b/Help/prop_tgt/XXX_OUTPUT_DIRECTORY.txt
@@ -1,8 +1,11 @@
Output directory in which to build |XXX| target files.
This property specifies the directory into which |xxx| target files
-should be built. Multi-configuration generators (VS, Xcode) append a
-per-configuration subdirectory to the specified directory.
+should be built. The property value may use
+:manual:`generator expressions <cmake-generator-expressions(7)>`.
+Multi-configuration generators (VS, Xcode) append a per-configuration
+subdirectory to the specified directory unless a generator expression
+is used.
This property is initialized by the value of the variable
|CMAKE_XXX_OUTPUT_DIRECTORY| if it is set when a target is created.
diff --git a/Help/release/dev/OUTPUT_DIRECTORY-genex.rst b/Help/release/dev/OUTPUT_DIRECTORY-genex.rst
new file mode 100644
index 0000000..8b839c0
--- /dev/null
+++ b/Help/release/dev/OUTPUT_DIRECTORY-genex.rst
@@ -0,0 +1,7 @@
+OUTPUT_DIRECTORY-genex
+----------------------
+
+* The :prop_tgt:`ARCHIVE_OUTPUT_DIRECTORY`,
+ :prop_tgt:`LIBRARY_OUTPUT_DIRECTORY`, and
+ :prop_tgt:`RUNTIME_OUTPUT_DIRECTORY` target properties learned to
+ support :manual:`generator expressions <cmake-generator-expressions(7)>`.
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 59d4da0..49b3239 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -66,6 +66,8 @@ struct cmTarget::OutputInfo
std::string OutDir;
std::string ImpDir;
std::string PdbDir;
+ bool empty() const
+ { return OutDir.empty() && ImpDir.empty() && PdbDir.empty(); }
};
//----------------------------------------------------------------------------
@@ -2604,19 +2606,35 @@ cmTarget::OutputInfo const* cmTarget::GetOutputInfo(
config_upper = cmSystemTools::UpperCase(config);
}
typedef cmTargetInternals::OutputInfoMapType OutputInfoMapType;
- OutputInfoMapType::const_iterator i =
+ OutputInfoMapType::iterator i =
this->Internal->OutputInfoMap.find(config_upper);
if(i == this->Internal->OutputInfoMap.end())
{
+ // Add empty info in map to detect potential recursion.
OutputInfo info;
+ OutputInfoMapType::value_type entry(config_upper, info);
+ i = this->Internal->OutputInfoMap.insert(entry).first;
+
+ // Compute output directories.
this->ComputeOutputDir(config, false, info.OutDir);
this->ComputeOutputDir(config, true, info.ImpDir);
if(!this->ComputePDBOutputDir("PDB", config, info.PdbDir))
{
info.PdbDir = info.OutDir;
}
- OutputInfoMapType::value_type entry(config_upper, info);
- i = this->Internal->OutputInfoMap.insert(entry).first;
+
+ // Now update the previously-prepared map entry.
+ i->second = info;
+ }
+ else if(i->second.empty())
+ {
+ // An empty map entry indicates we have been called recursively
+ // from the above block.
+ this->Makefile->GetCMakeInstance()->IssueMessage(
+ cmake::FATAL_ERROR,
+ "Target '" + this->GetName() + "' OUTPUT_DIRECTORY depends on itself.",
+ this->GetBacktrace());
+ return 0;
}
return &i->second;
}
@@ -3497,7 +3515,10 @@ bool cmTarget::ComputeOutputDir(const std::string& config,
if(const char* config_outdir = this->GetProperty(configProp))
{
// Use the user-specified per-configuration output directory.
- out = config_outdir;
+ cmGeneratorExpression ge;
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(config_outdir);
+ out = cge->Evaluate(this->Makefile, config);
// Skip per-configuration subdirectory.
conf = "";
@@ -3505,7 +3526,17 @@ bool cmTarget::ComputeOutputDir(const std::string& config,
else if(const char* outdir = this->GetProperty(propertyName))
{
// Use the user-specified output directory.
- out = outdir;
+ cmGeneratorExpression ge;
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(outdir);
+ out = cge->Evaluate(this->Makefile, config);
+
+ // Skip per-configuration subdirectory if the value contained a
+ // generator expression.
+ if (out != outdir)
+ {
+ conf = "";
+ }
}
else if(this->GetType() == cmTarget::EXECUTABLE)
{
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index df3f178..7fdfaa8 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -105,6 +105,19 @@ target_link_libraries(testLib4
add_executable(testExe3 testExe3.c)
set_property(TARGET testExe3 PROPERTY MACOSX_BUNDLE 1)
+# Test <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_DIRECTORY[_<CONFIG>] properties with generator expressions
+add_executable(testExe4 testExe4.c)
+target_link_libraries(testExe4 testExe1lib)
+set_property(TARGET testLib7 PROPERTY ARCHIVE_OUTPUT_DIRECTORY_DEBUG testLib7D-$<CONFIG>)
+set_property(TARGET testLib7 PROPERTY ARCHIVE_OUTPUT_DIRECTORY_RELEASE testLib7R-$<CONFIG>)
+set_property(TARGET testLib7 PROPERTY ARCHIVE_OUTPUT_DIRECTORY testLib7-$<CONFIG>)
+set_property(TARGET testLib5 PROPERTY LIBRARY_OUTPUT_DIRECTORY_DEBUG testLib5D-$<CONFIG>)
+set_property(TARGET testLib5 PROPERTY LIBRARY_OUTPUT_DIRECTORY_RELEASE testLib5R-$<CONFIG>)
+set_property(TARGET testLib5 PROPERTY LIBRARY_OUTPUT_DIRECTORY testLib5-$<CONFIG>)
+set_property(TARGET testExe4 PROPERTY RUNTIME_OUTPUT_DIRECTORY_DEBUG testExe4D-$<CONFIG>)
+set_property(TARGET testExe4 PROPERTY RUNTIME_OUTPUT_DIRECTORY_RELEASE testExe4R-$<CONFIG>)
+set_property(TARGET testExe4 PROPERTY RUNTIME_OUTPUT_DIRECTORY testExe4-$<CONFIG>)
+
# Test cyclic dependencies.
add_library(testLibCycleA STATIC
testLibCycleA1.c testLibCycleA2.c testLibCycleA3.c)
@@ -450,7 +463,7 @@ install(FILES
# Install and export from install tree.
install(
TARGETS
- testExe1 testLib1 testLib2 testExe2 testLib3 testLib4 testExe3
+ testExe1 testLib1 testLib2 testExe2 testLib3 testLib4 testExe3 testExe4
testExe2lib testLib4lib testLib4libdbg testLib4libopt
testLib6 testLib7
testLibCycleA testLibCycleB
@@ -511,7 +524,7 @@ export(TARGETS testExe1 testLib1 testLib2 testLib3
NAMESPACE bld_
FILE ExportBuildTree.cmake
)
-export(TARGETS testExe2 testLib4 testLib5 testLib6 testLib7 testExe3 testExe2lib
+export(TARGETS testExe2 testLib4 testLib5 testLib6 testLib7 testExe3 testExe4 testExe2lib
testLib4lib testLib4libdbg testLib4libopt
testLibCycleA testLibCycleB
testLibPerConfigDest
diff --git a/Tests/ExportImport/Export/testExe4.c b/Tests/ExportImport/Export/testExe4.c
new file mode 100644
index 0000000..731057e
--- /dev/null
+++ b/Tests/ExportImport/Export/testExe4.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+int main(int argc, const char* argv[])
+{
+ if(argc < 2)
+ {
+ fprintf(stderr, "Must specify output file.\n");
+ return 1;
+ }
+ {
+ FILE* f = fopen(argv[1], "w");
+ if(f)
+ {
+ fprintf(f, "int generated_by_testExe4() { return 0; }\n");
+ fclose(f);
+ }
+ else
+ {
+ fprintf(stderr, "Error writing to %s\n", argv[1]);
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt
index a74bad1..0f56495 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -19,11 +19,17 @@ add_custom_command(
COMMAND exp_testExe3 ${Import_BINARY_DIR}/exp_generated3.c
DEPENDS exp_testExe3
)
+add_custom_command(
+ OUTPUT ${Import_BINARY_DIR}/exp_generated4.c
+ COMMAND exp_testExe4 ${Import_BINARY_DIR}/exp_generated4.c
+ DEPENDS exp_testExe4
+ )
add_executable(imp_testExe1
imp_testExe1.c
${Import_BINARY_DIR}/exp_generated.c
${Import_BINARY_DIR}/exp_generated3.c
+ ${Import_BINARY_DIR}/exp_generated4.c
)
# Try linking to a library imported from the install tree.
@@ -53,11 +59,17 @@ add_custom_command(
COMMAND bld_testExe3 ${Import_BINARY_DIR}/bld_generated3.c
DEPENDS bld_testExe3
)
+add_custom_command(
+ OUTPUT ${Import_BINARY_DIR}/bld_generated4.c
+ COMMAND bld_testExe4 ${Import_BINARY_DIR}/bld_generated4.c
+ DEPENDS bld_testExe4
+ )
add_executable(imp_testExe1b
imp_testExe1.c
${Import_BINARY_DIR}/bld_generated.c
${Import_BINARY_DIR}/bld_generated3.c
+ ${Import_BINARY_DIR}/bld_generated4.c
)
# Try linking to a library imported from the build tree.
diff --git a/Tests/ExportImport/Import/A/imp_testExe1.c b/Tests/ExportImport/Import/A/imp_testExe1.c
index 56cdd2c..0a74309 100644
--- a/Tests/ExportImport/Import/A/imp_testExe1.c
+++ b/Tests/ExportImport/Import/A/imp_testExe1.c
@@ -1,5 +1,6 @@
extern int generated_by_testExe1();
extern int generated_by_testExe3();
+extern int generated_by_testExe4();
extern int testLib2();
extern int testLib3();
extern int testLib4();
@@ -24,5 +25,5 @@ int main()
return (testLib2() + generated_by_testExe1() + testLib3() + testLib4()
+ testLib5() + testLib6() + testLib7() + testLibCycleA1()
+ testLibPerConfigDest()
- + generated_by_testExe3() + testLib4lib() + testLib4libcfg());
+ + generated_by_testExe3() + generated_by_testExe4() + testLib4lib() + testLib4libcfg());
}
diff --git a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
index cba3941..21fc851 100644
--- a/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
+++ b/Tests/RunCMake/GeneratorExpression/RunCMakeTest.cmake
@@ -25,6 +25,7 @@ run_cmake(COMPILE_LANGUAGE-add_executable)
run_cmake(COMPILE_LANGUAGE-add_library)
run_cmake(COMPILE_LANGUAGE-add_test)
run_cmake(COMPILE_LANGUAGE-unknown-lang)
+run_cmake(TARGET_FILE-recursion)
run_cmake(ImportedTarget-TARGET_PDB_FILE)
if(LINKER_SUPPORTS_PDB)
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_FILE-recursion-result.txt b/Tests/RunCMake/GeneratorExpression/TARGET_FILE-recursion-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_FILE-recursion-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_FILE-recursion-stderr.txt b/Tests/RunCMake/GeneratorExpression/TARGET_FILE-recursion-stderr.txt
new file mode 100644
index 0000000..5b15526
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_FILE-recursion-stderr.txt
@@ -0,0 +1,4 @@
+CMake Error at TARGET_FILE-recursion.cmake:[0-9]+ \(add_executable\):
+ Target 'empty1' OUTPUT_DIRECTORY depends on itself.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_FILE-recursion.cmake b/Tests/RunCMake/GeneratorExpression/TARGET_FILE-recursion.cmake
new file mode 100644
index 0000000..7633be1
--- /dev/null
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_FILE-recursion.cmake
@@ -0,0 +1,3 @@
+enable_language(C)
+add_executable(empty1 empty.c)
+set_property(TARGET empty1 PROPERTY RUNTIME_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:empty1>)