Add policy CMP0019 to skip include/link variable re-expansion
Historically CMake has always expanded ${} variable references in the
values given to include_directories(), link_directories(), and
link_libraries(). This has been unnecessary since general ${}
evaluation syntax was added to the language a LONG time ago, but has
remained for compatibility with VERY early CMake versions.
For a long time the re-expansion was a lightweight operation because it
was only processed once at the directory level and the fast-path of
cmMakefile::ExpandVariablesInString was usually taken because values did
not have any '$' in them. Then commit d899eb71
(Call
ExpandVariablesInString for each target's INCLUDE_DIRECTORIES,
2012-02-22) made the operation a bit heavier because the expansion is
now needed on a per-target basis. In the future we will support
generator expressions in INCLUDE_DIRECTORIES with $<> syntax, so the
fast-path in cmMakefile::ExpandVariablesInString will no longer be taken
and re-expansion will be very expensive.
Add policy CMP0019 to skip the re-expansion altogether in NEW behavior.
In OLD behavior perform the expansion but improve the fast-path
heuristic to match ${} but not $<>. If the policy is not set then warn
if expansion actually does anything. We expect this to be encountered
very rarely in practice.
This commit is contained in:
parent
d5ac791366
commit
711b63f7e0
|
@ -814,7 +814,7 @@ bool cmMakefile::NeedBackwardsCompatibility(unsigned int major,
|
||||||
void cmMakefile::FinalPass()
|
void cmMakefile::FinalPass()
|
||||||
{
|
{
|
||||||
// do all the variable expansions here
|
// do all the variable expansions here
|
||||||
this->ExpandVariables();
|
this->ExpandVariablesCMP0019();
|
||||||
|
|
||||||
// give all the commands a chance to do something
|
// give all the commands a chance to do something
|
||||||
// after the file has been parsed before generation
|
// after the file has been parsed before generation
|
||||||
|
@ -2122,21 +2122,33 @@ void cmMakefile::AddExtraDirectory(const char* dir)
|
||||||
this->AuxSourceDirectories.push_back(dir);
|
this->AuxSourceDirectories.push_back(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool mightExpandVariablesCMP0019(const char* s)
|
||||||
// expand CMAKE_BINARY_DIR and CMAKE_SOURCE_DIR in the
|
|
||||||
// include and library directories.
|
|
||||||
|
|
||||||
void cmMakefile::ExpandVariables()
|
|
||||||
{
|
{
|
||||||
// Now expand variables in the include and link strings
|
return s && *s && strstr(s,"${") && strchr(s,'}');
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmMakefile::ExpandVariablesCMP0019()
|
||||||
|
{
|
||||||
|
// Drop this ancient compatibility behavior with a policy.
|
||||||
|
cmPolicies::PolicyStatus pol = this->GetPolicyStatus(cmPolicies::CMP0019);
|
||||||
|
if(pol != cmPolicies::OLD && pol != cmPolicies::WARN)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cmOStringStream w;
|
||||||
|
|
||||||
// May not be necessary anymore... But may need a policy for strict
|
|
||||||
// backwards compatibility
|
|
||||||
const char *includeDirs = this->GetProperty("INCLUDE_DIRECTORIES");
|
const char *includeDirs = this->GetProperty("INCLUDE_DIRECTORIES");
|
||||||
if (includeDirs)
|
if(mightExpandVariablesCMP0019(includeDirs))
|
||||||
{
|
{
|
||||||
std::string dirs = includeDirs;
|
std::string dirs = includeDirs;
|
||||||
this->ExpandVariablesInString(dirs, true, true);
|
this->ExpandVariablesInString(dirs, true, true);
|
||||||
|
if(pol == cmPolicies::WARN && dirs != includeDirs)
|
||||||
|
{
|
||||||
|
w << "Evaluated directory INCLUDE_DIRECTORIES\n"
|
||||||
|
<< " " << includeDirs << "\n"
|
||||||
|
<< "as\n"
|
||||||
|
<< " " << dirs << "\n";
|
||||||
|
}
|
||||||
this->SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
|
this->SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2146,10 +2158,17 @@ void cmMakefile::ExpandVariables()
|
||||||
{
|
{
|
||||||
cmTarget &t = l->second;
|
cmTarget &t = l->second;
|
||||||
includeDirs = t.GetProperty("INCLUDE_DIRECTORIES");
|
includeDirs = t.GetProperty("INCLUDE_DIRECTORIES");
|
||||||
if (includeDirs)
|
if(mightExpandVariablesCMP0019(includeDirs))
|
||||||
{
|
{
|
||||||
std::string dirs = includeDirs;
|
std::string dirs = includeDirs;
|
||||||
this->ExpandVariablesInString(dirs, true, true);
|
this->ExpandVariablesInString(dirs, true, true);
|
||||||
|
if(pol == cmPolicies::WARN && dirs != includeDirs)
|
||||||
|
{
|
||||||
|
w << "Evaluated target " << t.GetName() << " INCLUDE_DIRECTORIES\n"
|
||||||
|
<< " " << includeDirs << "\n"
|
||||||
|
<< "as\n"
|
||||||
|
<< " " << dirs << "\n";
|
||||||
|
}
|
||||||
t.SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
|
t.SetProperty("INCLUDE_DIRECTORIES", dirs.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2157,13 +2176,45 @@ void cmMakefile::ExpandVariables()
|
||||||
for(std::vector<std::string>::iterator d = this->LinkDirectories.begin();
|
for(std::vector<std::string>::iterator d = this->LinkDirectories.begin();
|
||||||
d != this->LinkDirectories.end(); ++d)
|
d != this->LinkDirectories.end(); ++d)
|
||||||
{
|
{
|
||||||
|
if(mightExpandVariablesCMP0019(d->c_str()))
|
||||||
|
{
|
||||||
|
std::string orig = *d;
|
||||||
this->ExpandVariablesInString(*d, true, true);
|
this->ExpandVariablesInString(*d, true, true);
|
||||||
|
if(pol == cmPolicies::WARN && *d != orig)
|
||||||
|
{
|
||||||
|
w << "Evaluated link directory\n"
|
||||||
|
<< " " << orig << "\n"
|
||||||
|
<< "as\n"
|
||||||
|
<< " " << *d << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for(cmTarget::LinkLibraryVectorType::iterator l =
|
for(cmTarget::LinkLibraryVectorType::iterator l =
|
||||||
this->LinkLibraries.begin();
|
this->LinkLibraries.begin();
|
||||||
l != this->LinkLibraries.end(); ++l)
|
l != this->LinkLibraries.end(); ++l)
|
||||||
{
|
{
|
||||||
|
if(mightExpandVariablesCMP0019(l->first.c_str()))
|
||||||
|
{
|
||||||
|
std::string orig = l->first;
|
||||||
this->ExpandVariablesInString(l->first, true, true);
|
this->ExpandVariablesInString(l->first, true, true);
|
||||||
|
if(pol == cmPolicies::WARN && l->first != orig)
|
||||||
|
{
|
||||||
|
w << "Evaluated link library\n"
|
||||||
|
<< " " << orig << "\n"
|
||||||
|
<< "as\n"
|
||||||
|
<< " " << l->first << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!w.str().empty())
|
||||||
|
{
|
||||||
|
cmOStringStream m;
|
||||||
|
m << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0019)
|
||||||
|
<< "\n"
|
||||||
|
<< "The following variable evaluations were encountered:\n"
|
||||||
|
<< w.str();
|
||||||
|
this->IssueMessage(cmake::AUTHOR_WARNING, m.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -693,7 +693,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Expand variables in the makefiles ivars such as link directories etc
|
* Expand variables in the makefiles ivars such as link directories etc
|
||||||
*/
|
*/
|
||||||
void ExpandVariables();
|
void ExpandVariablesCMP0019();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace variables and #cmakedefine lines in the given string.
|
* Replace variables and #cmakedefine lines in the given string.
|
||||||
|
|
|
@ -491,6 +491,23 @@ cmPolicies::cmPolicies()
|
||||||
"CMAKE_SHARED_LIBRARY_<Lang>_FLAGS whether it is modified or not and "
|
"CMAKE_SHARED_LIBRARY_<Lang>_FLAGS whether it is modified or not and "
|
||||||
"honor the POSITION_INDEPENDENT_CODE target property.",
|
"honor the POSITION_INDEPENDENT_CODE target property.",
|
||||||
2,8,9,0, cmPolicies::WARN);
|
2,8,9,0, cmPolicies::WARN);
|
||||||
|
|
||||||
|
this->DefinePolicy(
|
||||||
|
CMP0019, "CMP0019",
|
||||||
|
"Do not re-expand variables in include and link information.",
|
||||||
|
"CMake 2.8.10 and lower re-evaluated values given to the "
|
||||||
|
"include_directories, link_directories, and link_libraries "
|
||||||
|
"commands to expand any leftover variable references at the "
|
||||||
|
"end of the configuration step. "
|
||||||
|
"This was for strict compatibility with VERY early CMake versions "
|
||||||
|
"because all variable references are now normally evaluated during "
|
||||||
|
"CMake language processing. "
|
||||||
|
"CMake 2.8.11 and higher prefer to skip the extra evaluation."
|
||||||
|
"\n"
|
||||||
|
"The OLD behavior for this policy is to re-evaluate the values "
|
||||||
|
"for strict compatibility. "
|
||||||
|
"The NEW behavior for this policy is to leave the values untouched.",
|
||||||
|
2,8,11,0, cmPolicies::WARN);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmPolicies::~cmPolicies()
|
cmPolicies::~cmPolicies()
|
||||||
|
|
|
@ -68,6 +68,7 @@ public:
|
||||||
CMP0018, ///< Ignore language flags for shared libs, and adhere to
|
CMP0018, ///< Ignore language flags for shared libs, and adhere to
|
||||||
/// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C}
|
/// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C}
|
||||||
/// instead.
|
/// instead.
|
||||||
|
CMP0019, ///< No variable re-expansion in include and link info
|
||||||
|
|
||||||
/** \brief Always the last entry.
|
/** \brief Always the last entry.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
cmake_policy(SET CMP0019 NEW)
|
||||||
|
include(CMP0019-code.cmake)
|
|
@ -0,0 +1,2 @@
|
||||||
|
cmake_policy(SET CMP0019 OLD)
|
||||||
|
include(CMP0019-code.cmake)
|
|
@ -0,0 +1,40 @@
|
||||||
|
CMake Warning \(dev\) in CMakeLists.txt:
|
||||||
|
Policy CMP0019 is not set: Do not re-expand variables in include and link
|
||||||
|
information. Run "cmake --help-policy CMP0019" for policy details. Use
|
||||||
|
the cmake_policy command to set the policy and suppress this warning.
|
||||||
|
|
||||||
|
The following variable evaluations were encountered:
|
||||||
|
|
||||||
|
Evaluated directory INCLUDE_DIRECTORIES
|
||||||
|
|
||||||
|
/usr/include/\${VAR_INCLUDE};/usr/include/normal
|
||||||
|
|
||||||
|
as
|
||||||
|
|
||||||
|
/usr/include/VAL_INCLUDE;/usr/include/normal
|
||||||
|
|
||||||
|
Evaluated target some_target INCLUDE_DIRECTORIES
|
||||||
|
|
||||||
|
/usr/include/\${VAR_INCLUDE};/usr/include/normal
|
||||||
|
|
||||||
|
as
|
||||||
|
|
||||||
|
/usr/include/VAL_INCLUDE;/usr/include/normal
|
||||||
|
|
||||||
|
Evaluated link directory
|
||||||
|
|
||||||
|
/usr/lib/\${VAR_LINK_DIRS}
|
||||||
|
|
||||||
|
as
|
||||||
|
|
||||||
|
/usr/lib/VAL_LINK_DIRS
|
||||||
|
|
||||||
|
Evaluated link library
|
||||||
|
|
||||||
|
\${VAR_LINK_LIBS}
|
||||||
|
|
||||||
|
as
|
||||||
|
|
||||||
|
VAL_LINK_LIBS
|
||||||
|
|
||||||
|
This warning is for project developers. Use -Wno-dev to suppress it.$
|
|
@ -0,0 +1 @@
|
||||||
|
include(CMP0019-code.cmake)
|
|
@ -0,0 +1,9 @@
|
||||||
|
set(VAR_INCLUDE "VAL_INCLUDE")
|
||||||
|
set(VAR_LINK_DIRS "VAL_LINK_DIRS")
|
||||||
|
set(VAR_LINK_LIBS "VAL_LINK_LIBS")
|
||||||
|
add_custom_target(some_target)
|
||||||
|
include_directories("/usr/include/\${VAR_INCLUDE}" /usr/include/normal)
|
||||||
|
link_directories("/usr/lib/\${VAR_LINK_DIRS}" /usr/lib/normal)
|
||||||
|
link_libraries("\${VAR_LINK_LIBS}" normal)
|
||||||
|
add_custom_target(other_target)
|
||||||
|
set_property(TARGET other_target PROPERTY INCLUDE_DIRECTORIES "")
|
|
@ -0,0 +1,3 @@
|
||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
project(${RunCMake_TEST} NONE)
|
||||||
|
include(${RunCMake_TEST}.cmake)
|
|
@ -0,0 +1,5 @@
|
||||||
|
include(RunCMake)
|
||||||
|
|
||||||
|
run_cmake(CMP0019-WARN)
|
||||||
|
run_cmake(CMP0019-OLD)
|
||||||
|
run_cmake(CMP0019-NEW)
|
|
@ -45,6 +45,7 @@ macro(add_RunCMake_test test)
|
||||||
)
|
)
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
add_RunCMake_test(CMP0019)
|
||||||
add_RunCMake_test(GeneratorExpression)
|
add_RunCMake_test(GeneratorExpression)
|
||||||
add_RunCMake_test(TargetPropertyGeneratorExpressions)
|
add_RunCMake_test(TargetPropertyGeneratorExpressions)
|
||||||
add_RunCMake_test(Languages)
|
add_RunCMake_test(Languages)
|
||||||
|
|
Loading…
Reference in New Issue