cmTarget: Deprecate the LOCATION target property with a policy.

The final location and name of a build-target is not determined
until generate-time. However, reading the LOCATION property from
a target is currently allowed at configure time. Apart from creating
possibly-erroneous results, this has an impact on the implementation
of cmake itself, and prevents some major cleanups from being made.

Disallow reading LOCATION from build-targets with a policy. Port some
existing uses of it in CMake itself to use the TARGET_FILE generator
expression.
This commit is contained in:
Stephen Kelly 2013-06-28 16:37:39 +02:00
parent 7e4910fe47
commit e4e5b28c27
20 changed files with 152 additions and 9 deletions

View File

@ -637,6 +637,28 @@ cmPolicies::cmPolicies()
"The OLD behavior for this policy is to use compiler id \"Clang\". "
"The NEW behavior for this policy is to use compiler id \"AppleClang\".",
2,8,13,0, cmPolicies::WARN);
this->DefinePolicy(
CMP0026, "CMP0026",
"Disallow use of the LOCATION target property.",
"CMake 2.8.12 and lower allowed reading the LOCATION target property to "
"determine the eventual location of build targets. This relies on the "
"assumption that all necessary information is available at "
"configure-time to determine the final location and filename of the "
"target. However, this property is not fully determined until later at "
"generate-time. At generate time, the $<TARGET_FILE> generator "
"expression can be used to determine the eventual LOCATION of a target "
"output."
"\n"
"Code which reads the LOCATION target property can be ported to use the "
"$<TARGET_FILE> generator expression together with the file(GENERATE) "
"subcommand to generate a file containing the target location."
"\n"
"The OLD behavior for this policy is to allow reading the LOCATION "
"property from build-targets. "
"The NEW behavior for this policy is to not to allow reading the "
"LOCATION property from build-targets.",
2,8,13,0, cmPolicies::WARN);
}
cmPolicies::~cmPolicies()

View File

@ -76,6 +76,7 @@ public:
CMP0023, ///< Disallow mixing keyword and plain tll signatures
CMP0024, ///< Disallow including export() result.
CMP0025, ///< Compiler id for Apple Clang is now AppleClang
CMP0026, ///< Disallow use of the LOCATION target property.
/** \brief Always the last entry.
*

View File

@ -4129,6 +4129,43 @@ const char *cmTarget::GetProperty(const char* prop)
return this->GetProperty(prop, cmProperty::TARGET);
}
//----------------------------------------------------------------------------
bool cmTarget::HandleLocationPropertyPolicy()
{
if (this->IsImported())
{
return true;
}
const char *modal = 0;
cmake::MessageType messageType = cmake::AUTHOR_WARNING;
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0026))
{
case cmPolicies::WARN:
modal = "should";
case cmPolicies::OLD:
break;
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::NEW:
modal = "may";
messageType = cmake::FATAL_ERROR;
}
if (modal)
{
cmOStringStream e;
e << (this->Makefile->GetPolicies()
->GetPolicyWarning(cmPolicies::CMP0026)) << "\n";
e << "The LOCATION property " << modal << " not be read from target \""
<< this->GetName() << "\". Use the target name directly with "
"add_custom_command, or use the generator expression $<TARGET_FILE>, "
"as appropriate.\n";
this->Makefile->IssueMessage(messageType, e.str().c_str());
}
return messageType != cmake::FATAL_ERROR;
}
//----------------------------------------------------------------------------
const char *cmTarget::GetProperty(const char* prop,
cmProperty::ScopeType scope)
@ -4154,6 +4191,11 @@ const char *cmTarget::GetProperty(const char* prop,
{
if(strcmp(prop,"LOCATION") == 0)
{
if (!this->HandleLocationPropertyPolicy())
{
return 0;
}
// Set the LOCATION property of the target.
//
// For an imported target this is the location of an arbitrary
@ -4169,6 +4211,10 @@ const char *cmTarget::GetProperty(const char* prop,
// Support "LOCATION_<CONFIG>".
if(strncmp(prop, "LOCATION_", 9) == 0)
{
if (!this->HandleLocationPropertyPolicy())
{
return 0;
}
std::string configName = prop+9;
this->SetProperty(prop, this->GetLocation(configName.c_str()));
}
@ -4181,6 +4227,10 @@ const char *cmTarget::GetProperty(const char* prop,
std::string configName(prop, len-9);
if(configName != "IMPORTED")
{
if (!this->HandleLocationPropertyPolicy())
{
return 0;
}
this->SetProperty(prop, this->GetLocation(configName.c_str()));
}
}

View File

@ -554,6 +554,8 @@ public:
{ return this->TargetTypeValue == STATIC_LIBRARY; }
private:
bool HandleLocationPropertyPolicy();
// The set of include directories that are marked as system include
// directories.
std::set<cmStdString> SystemIncludeDirectories;

View File

@ -19,8 +19,16 @@ if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Makefile")
configure_file(FindFoo.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FindFoo.cmake @ONLY)
# now set up the test:
get_target_property(cmakeExecutable cmake LOCATION)
if (NOT CMAKE_VERSION VERSION_LESS 2.8.12)
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/cmakeExecutable.mk"
CONTENT "CMAKE = \"$<TARGET_FILE:cmake>\"\n"
)
else()
get_target_property(cmakeLocation cmake LOCATION)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cmakeExecutable.mk"
"CMAKE = \"${cmakeLocation}\"\n"
)
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Makefile.in ${CMAKE_CURRENT_BINARY_DIR}/ConfMakefile @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/main.cpp ${CMAKE_CURRENT_BINARY_DIR}/main.cpp COPYONLY)

View File

@ -1,4 +1,6 @@
CMAKE = "@cmakeExecutable@"
include cmakeExecutable.mk
CMAKE_CURRENT_BINARY_DIR = "@CMAKE_CURRENT_BINARY_DIR@"
CMAKE_CXX_COMPILER = "@CMAKE_CXX_COMPILER@"
CMAKE_CXX_COMPILER_ID = "@CMAKE_CXX_COMPILER_ID@"

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1 @@
^$

View File

@ -0,0 +1,6 @@
enable_language(CXX)
add_library(someimportedlib SHARED IMPORTED)
get_target_property(_loc someimportedlib LOCATION)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,11 @@
CMake Error at CMP0026-NEW.cmake:7 \(get_target_property\):
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 may not be read from target "somelib". Use the
target name directly with add_custom_command, or use the generator
expression \$<TARGET_FILE>, as appropriate.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1,7 @@
enable_language(CXX)
cmake_policy(SET CMP0026 NEW)
add_library(somelib empty.cpp)
get_target_property(_loc somelib LOCATION)

View File

@ -0,0 +1 @@
0

View File

@ -0,0 +1,12 @@
CMake Warning \(dev\) at CMP0026-WARN.cmake:5 \(get_target_property\):
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 "somelib". Use the
target name directly with add_custom_command, or use the generator
expression \$<TARGET_FILE>, as appropriate.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.

View File

@ -0,0 +1,5 @@
enable_language(CXX)
add_library(somelib empty.cpp)
get_target_property(_loc somelib LOCATION)

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 2.8)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,5 @@
include(RunCMake)
run_cmake(CMP0026-WARN)
run_cmake(CMP0026-NEW)
run_cmake(CMP0026-IMPORTED)

View File

@ -0,0 +1,7 @@
#ifdef _WIN32
__declspec(dllexport)
#endif
int empty()
{
return 0;
}

View File

@ -53,6 +53,7 @@ endif()
add_RunCMake_test(CMP0019)
add_RunCMake_test(CMP0022)
add_RunCMake_test(CMP0026)
add_RunCMake_test(CTest)
if(UNIX AND "${CMAKE_TEST_GENERATOR}" MATCHES "Unix Makefiles")
add_RunCMake_test(CompilerChange)

View File

@ -48,14 +48,12 @@ set(DOCBOOK_FILES
)
macro(ADD_DOCS target dependency)
# Generate documentation for "ctest" executable.
get_target_property(CMD ${target} LOCATION)
# only generate the documentation if the target is actually built
if(CMD)
if(${target})
add_custom_command(
OUTPUT ${CMake_BINARY_DIR}/Docs/${target}.txt
${${target}-PATH} # Possibly set PATH, see below.
COMMAND ${CMD}
COMMAND $<TARGET_FILE:${target}>
ARGS --help-full ${CMake_BINARY_DIR}/Docs/${target}.txt
--help-full ${CMake_BINARY_DIR}/Docs/${target}.html
--help-full ${CMake_BINARY_DIR}/Docs/${target}.1
@ -92,10 +90,9 @@ ADD_DOCS(cmake-gui ${CMake_SOURCE_DIR}/Utilities/Doxygen/doxyfile.in)
# add the documentation for cmake itself
get_target_property(CMD cmake LOCATION)
add_custom_command(
OUTPUT ${CMake_BINARY_DIR}/Docs/cmake.txt
COMMAND ${CMD}
COMMAND $<TARGET_FILE:cmake>
ARGS --copyright ${CMake_BINARY_DIR}/Docs/Copyright.txt
--help-full ${CMake_BINARY_DIR}/Docs/cmake.txt
--help-full ${CMake_BINARY_DIR}/Docs/cmake.html