Fix crash on $<TARGET_PROPERTY:...,LOCATION> genex (#16134)

Policy CMP0026 deprecated the LOCATION property, and we have long
provided a $<TARGET_FILE:...> generator expression.  However, if
a project tries to use $<TARGET_PROPERTY:...,LOCATION> we should
at least not crash.

The compatibility implementation of the LOCATION property uses
cmGlobalGenerator::CreateGenerationObjects to create the structures
needed to evaluate the property before generation starts.  The
implementation assumed that accessing the property could only be done
during configuration (via the typical get_property command use case).
The $<TARGET_PROPERTY:...,LOCATION> genex causes the LOCATION property
to be accessed during generation.  Calling CreateGenerationObjects
during generation blows away all the objects currently being used for
generation and is not safe.  Add a condition to call it only when
configuration is not finished.
This commit is contained in:
Brad King 2016-06-02 10:57:10 -04:00
parent 9d81f1b3aa
commit f500a784d0
4 changed files with 23 additions and 3 deletions

View File

@ -1131,7 +1131,9 @@ const char* cmTarget::GetProperty(const std::string& prop,
// target because the configuration type may not be known at
// CMake time.
cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
gg->CreateGenerationObjects();
if (!gg->GetConfigureDoneCMP0026()) {
gg->CreateGenerationObjects();
}
cmGeneratorTarget* gt = gg->FindGeneratorTarget(this->GetName());
this->Properties.SetProperty(propLOCATION, gt->GetLocationForBuild());
}
@ -1150,7 +1152,9 @@ const char* cmTarget::GetProperty(const std::string& prop,
prop, this->ImportedGetFullPath(configName, false).c_str());
} else {
cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
gg->CreateGenerationObjects();
if (!gg->GetConfigureDoneCMP0026()) {
gg->CreateGenerationObjects();
}
cmGeneratorTarget* gt = gg->FindGeneratorTarget(this->GetName());
this->Properties.SetProperty(
prop, gt->GetFullPath(configName, false).c_str());
@ -1168,7 +1172,9 @@ const char* cmTarget::GetProperty(const std::string& prop,
prop, this->ImportedGetFullPath(configName, false).c_str());
} else {
cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
gg->CreateGenerationObjects();
if (!gg->GetConfigureDoneCMP0026()) {
gg->CreateGenerationObjects();
}
cmGeneratorTarget* gt = gg->FindGeneratorTarget(this->GetName());
this->Properties.SetProperty(
prop, gt->GetFullPath(configName, false).c_str());

View File

@ -28,6 +28,7 @@ run_cmake(COMPILE_LANGUAGE-add_test)
run_cmake(COMPILE_LANGUAGE-unknown-lang)
run_cmake(TARGET_FILE-recursion)
run_cmake(OUTPUT_NAME-recursion)
run_cmake(TARGET_PROPERTY-LOCATION)
run_cmake(ImportedTarget-TARGET_PDB_FILE)
if(LINKER_SUPPORTS_PDB)

View File

@ -0,0 +1,10 @@
CMake Warning \(dev\) in CMakeLists.txt:
Policy CMP0026 is not set: Disallow use of the LOCATION target property.
Run "cmake --help-policy CMP0026" for policy details. Use the cmake_policy
command to set the policy and suppress this warning.
The LOCATION property should not be read from target "foo". Use the target
name directly with add_custom_command, or use the generator expression
\$<TARGET_FILE>, as appropriate.
This warning is for project developers. Use -Wno-dev to suppress it.

View File

@ -0,0 +1,3 @@
enable_language(C)
add_library(foo empty.c)
add_custom_target(drive COMMAND ${CMAKE_COMMAND} -E echo $<TARGET_PROPERTY:foo,LOCATION>)