Merge topic 'OUTPUT_DIRECTORY-genex'
d25819bc
Add generator expression support to OUTPUT_DIRECTORY target propertiese36a05fd
cmTarget: Detect and diagnose recursion in GetOutputInfo
This commit is contained in:
commit
a07d16085b
|
@ -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)>`.
|
||||
|
|
|
@ -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)>`.
|
||||
|
|
|
@ -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)>`.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)>`.
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -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\)
|
|
@ -0,0 +1,3 @@
|
|||
enable_language(C)
|
||||
add_executable(empty1 empty.c)
|
||||
set_property(TARGET empty1 PROPERTY RUNTIME_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:empty1>)
|
Loading…
Reference in New Issue