file(GENERATE): Add policy CMP0070 to define relative path behavior

Previously `file(GENERATE)` did not define any behavior for relative
paths given to the `OUTPUT` or `INPUT` arguments.  Define behavior
consistent with CMake conventions and add a policy to provide
compatibility for projects that relied on the old accidental behavior.

Fixes: #16786
This commit is contained in:
Brad King
2017-06-08 11:54:03 -04:00
parent 69050f4d16
commit 82be694c7a
17 changed files with 201 additions and 3 deletions
+61 -1
View File
@@ -20,11 +20,13 @@
cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile(
const std::string& input,
CM_AUTO_PTR<cmCompiledGeneratorExpression> outputFileExpr,
CM_AUTO_PTR<cmCompiledGeneratorExpression> condition, bool inputIsContent)
CM_AUTO_PTR<cmCompiledGeneratorExpression> condition, bool inputIsContent,
cmPolicies::PolicyStatus policyStatusCMP0070)
: Input(input)
, OutputFileExpr(outputFileExpr)
, Condition(condition)
, InputIsContent(inputIsContent)
, PolicyStatusCMP0070(policyStatusCMP0070)
{
}
@@ -58,6 +60,8 @@ void cmGeneratorExpressionEvaluationFile::Generate(
if (cmSystemTools::FileIsFullPath(outputFileName)) {
outputFileName = cmSystemTools::CollapseFullPath(outputFileName);
} else {
outputFileName = this->FixRelativePath(outputFileName, PathForOutput, lg);
}
std::map<std::string, std::string>::iterator it =
@@ -118,6 +122,8 @@ void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg)
std::string inputFileName = this->Input;
if (cmSystemTools::FileIsFullPath(inputFileName)) {
inputFileName = cmSystemTools::CollapseFullPath(inputFileName);
} else {
inputFileName = this->FixRelativePath(inputFileName, PathForInput, lg);
}
lg->GetMakefile()->AddCMakeDependFile(inputFileName);
cmSystemTools::GetPermissions(inputFileName.c_str(), perm);
@@ -167,3 +173,57 @@ void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg)
}
}
}
std::string cmGeneratorExpressionEvaluationFile::FixRelativePath(
std::string const& relativePath, PathRole role, cmLocalGenerator* lg)
{
std::string resultPath;
switch (this->PolicyStatusCMP0070) {
case cmPolicies::WARN: {
std::string arg;
switch (role) {
case PathForInput:
arg = "INPUT";
break;
case PathForOutput:
arg = "OUTPUT";
break;
}
std::ostringstream w;
/* clang-format off */
w <<
cmPolicies::GetPolicyWarning(cmPolicies::CMP0070) << "\n"
"file(GENERATE) given relative " << arg << " path:\n"
" " << relativePath << "\n"
"This is not defined behavior unless CMP0070 is set to NEW. "
"For compatibility with older versions of CMake, the previous "
"undefined behavior will be used."
;
/* clang-format on */
lg->IssueMessage(cmake::AUTHOR_WARNING, w.str());
}
CM_FALLTHROUGH;
case cmPolicies::OLD:
// OLD behavior is to use the relative path unchanged,
// which ends up being used relative to the working dir.
resultPath = relativePath;
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
// NEW behavior is to interpret the relative path with respect
// to the current source or binary directory.
switch (role) {
case PathForInput:
resultPath = cmSystemTools::CollapseFullPath(
relativePath, lg->GetCurrentSourceDirectory());
break;
case PathForOutput:
resultPath = cmSystemTools::CollapseFullPath(
relativePath, lg->GetCurrentBinaryDirectory());
break;
}
break;
}
return resultPath;
}
+12 -1
View File
@@ -10,6 +10,7 @@
#include <vector>
#include "cmGeneratorExpression.h"
#include "cmPolicies.h"
#include "cm_auto_ptr.hxx"
#include "cm_sys_stat.h"
@@ -21,7 +22,8 @@ public:
cmGeneratorExpressionEvaluationFile(
const std::string& input,
CM_AUTO_PTR<cmCompiledGeneratorExpression> outputFileExpr,
CM_AUTO_PTR<cmCompiledGeneratorExpression> condition, bool inputIsContent);
CM_AUTO_PTR<cmCompiledGeneratorExpression> condition, bool inputIsContent,
cmPolicies::PolicyStatus policyStatusCMP0070);
void Generate(cmLocalGenerator* lg);
@@ -35,12 +37,21 @@ private:
cmCompiledGeneratorExpression* inputExpression,
std::map<std::string, std::string>& outputFiles, mode_t perm);
enum PathRole
{
PathForInput,
PathForOutput
};
std::string FixRelativePath(std::string const& filePath, PathRole role,
cmLocalGenerator* lg);
private:
const std::string Input;
const CM_AUTO_PTR<cmCompiledGeneratorExpression> OutputFileExpr;
const CM_AUTO_PTR<cmCompiledGeneratorExpression> Condition;
std::vector<std::string> Files;
const bool InputIsContent;
cmPolicies::PolicyStatus PolicyStatusCMP0070;
};
#endif
+2 -1
View File
@@ -592,7 +592,8 @@ void cmMakefile::AddEvaluationFile(
CM_AUTO_PTR<cmCompiledGeneratorExpression> condition, bool inputIsContent)
{
this->EvaluationFiles.push_back(new cmGeneratorExpressionEvaluationFile(
inputFile, outputName, condition, inputIsContent));
inputFile, outputName, condition, inputIsContent,
this->GetPolicyStatus(cmPolicies::CMP0070)));
}
std::vector<cmGeneratorExpressionEvaluationFile*>
+3
View File
@@ -206,6 +206,9 @@ class cmMakefile;
cmPolicies::WARN) \
SELECT(POLICY, CMP0069, \
"INTERPROCEDURAL_OPTIMIZATION is enforced when enabled.", 3, 9, 0, \
cmPolicies::WARN) \
SELECT(POLICY, CMP0070, \
"Define file(GENERATE) behavior for relative paths.", 3, 10, 0, \
cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)