Merge topic 'file-generate-relative-paths'

82be694c file(GENERATE): Add policy CMP0070 to define relative path behavior
69050f4d Tests: Use full output paths in file(GENERATE) calls

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !943
This commit is contained in:
Brad King
2017-06-12 14:14:37 +00:00
committed by Kitware Robot
32 changed files with 217 additions and 19 deletions
+5
View File
@@ -291,6 +291,8 @@ from the input content to produce the output content. The options are:
``INPUT <input-file>``
Use the content from a given file as input.
A relative path is treated with respect to the value of
:variable:`CMAKE_CURRENT_SOURCE_DIR`. See policy :policy:`CMP0070`.
``OUTPUT <output-file>``
Specify the output file name to generate. Use generator expressions
@@ -298,6 +300,9 @@ from the input content to produce the output content. The options are:
name. Multiple configurations may generate the same output file only
if the generated content is identical. Otherwise, the ``<output-file>``
must evaluate to an unique name for each configuration.
A relative path (after evaluating generator expressions) is treated
with respect to the value of :variable:`CMAKE_CURRENT_BINARY_DIR`.
See policy :policy:`CMP0070`.
Exactly one ``CONTENT`` or ``INPUT`` option must be given. A specific
``OUTPUT`` file may be named by at most one invocation of ``file(GENERATE)``.
+8
View File
@@ -51,6 +51,14 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used
to determine whether to report an error on use of deprecated macros or
functions.
Policies Introduced by CMake 3.10
=================================
.. toctree::
:maxdepth: 1
CMP0070: Define file(GENERATE) behavior for relative paths. </policy/CMP0070>
Policies Introduced by CMake 3.9
================================
+25
View File
@@ -0,0 +1,25 @@
CMP0070
-------
Define :command:`file(GENERATE)` behavior for relative paths.
CMake 3.10 and newer define that relative paths given to ``INPUT`` and
``OUTPUT`` arguments of ``file(GENERATE)`` are interpreted relative to the
current source and binary directories, respectively. CMake 3.9 and lower did
not define any behavior for relative paths but did not diagnose them either
and accidentally treated them relative to the process working directory.
Policy ``CMP0070`` provides compatibility with projects that used the old
undefined behavior.
This policy affects behavior of relative paths given to ``file(GENERATE)``.
The ``OLD`` behavior for this policy is to treat the paths relative to the
working directory of CMake. The ``NEW`` behavior for this policy is to
interpret relative paths with respect to the current source or binary
directory of the caller.
This policy was introduced in CMake version 3.10. CMake version
|release| warns when the policy is not set and uses ``OLD`` behavior.
Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW``
explicitly.
.. include:: DEPRECATED.txt
@@ -0,0 +1,7 @@
file-generate-relative-paths
----------------------------
* The :command:`file(GENERATE)` command now interprets relative paths
given to its ``OUTPUT`` and ``INPUT`` arguments with respect to the
caller's current binary and source directories, respectively.
See policy :policy:`CMP0070`.
+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)
@@ -11,7 +11,7 @@ endif()
]])
endif()
file(GENERATE OUTPUT check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
set(check_pairs
\"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/test.manifest\"
)
+1 -1
View File
@@ -2,7 +2,7 @@ enable_language(C)
add_executable(main ${CMAKE_CURRENT_BINARY_DIR}/main.c)
file(GENERATE OUTPUT check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
set(check_pairs
\"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.c\"
)
@@ -16,7 +16,7 @@ add_custom_command(
add_custom_target(drive ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/after-always)
file(GENERATE OUTPUT check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
set(check_pairs
\"${CMAKE_CURRENT_BINARY_DIR}/always-updated|${CMAKE_CURRENT_BINARY_DIR}/before-always\"
\"${CMAKE_CURRENT_BINARY_DIR}/after-always|${CMAKE_CURRENT_BINARY_DIR}/always-updated\"
@@ -16,7 +16,7 @@ add_custom_command(
add_custom_target(drive ALL DEPENDS use-byproduct)
add_dependencies(drive produce)
file(GENERATE OUTPUT check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
if (check_step EQUAL 1)
set(check_pairs
\"${CMAKE_CURRENT_BINARY_DIR}/use-byproduct|${CMAKE_CURRENT_BINARY_DIR}/gen-byproduct-stamp\"
@@ -6,7 +6,7 @@ add_custom_command(
add_custom_target(generate ALL DEPENDS output.cxx)
set_property(TARGET generate PROPERTY INCLUDE_DIRECTORIES ${CMAKE_CURRENT_BINARY_DIR})
file(GENERATE OUTPUT check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
set(check_pairs
\"${CMAKE_CURRENT_BINARY_DIR}/output.cxx|${CMAKE_CURRENT_BINARY_DIR}/MakeCustomIncludes.h\"
)
@@ -3,7 +3,7 @@ get_filename_component(include_dir "${CMAKE_BINARY_DIR}" PATH)
include_directories("${include_dir}")
add_executable(MakeInProjectOnly MakeInProjectOnly.c)
set(CMAKE_DEPENDS_IN_PROJECT_ONLY 1)
file(GENERATE OUTPUT check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
if (check_step EQUAL 1)
set(check_pairs
\"$<TARGET_FILE:MakeInProjectOnly>|${include_dir}/MakeInProjectOnly.h\"
@@ -1,6 +1,6 @@
add_executable(mytest test.cpp)
file(GENERATE OUTPUT runtest_info.cmake CONTENT [[
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/runtest_info.cmake CONTENT [[
set(EXPECTED_MYTEST_NAME "$<TARGET_FILE_NAME:mytest>")
]])
@@ -6,7 +6,7 @@ foreach(CONFIG IN LISTS CMAKE_CONFIGURATION_TYPES)
OUTPUT_NAME_${UPPER_CONFIG} bar_${CONFIG})
endforeach()
file(GENERATE OUTPUT runtest_info_$<CONFIG>.cmake CONTENT [[
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/runtest_info_$<CONFIG>.cmake CONTENT [[
set(CPACK_BUILD_CONFIG "$<CONFIG>")
set(EXPECTED_MYTEST_NAME "$<TARGET_FILE_NAME:mytest>")
]])
@@ -1,6 +1,6 @@
add_executable(mytest test.cpp)
file(GENERATE OUTPUT runtest_info.cmake CONTENT [[
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/runtest_info.cmake CONTENT [[
set(EXPECTED_MYTEST_NAME "$<TARGET_FILE_NAME:mytest>")
]])
@@ -0,0 +1,13 @@
foreach(f
"${RunCMake_TEST_SOURCE_DIR}/relative-input-NEW.txt"
"${RunCMake_TEST_BINARY_DIR}/relative-output-NEW.txt"
)
if(EXISTS "${f}")
file(READ "${f}" content)
if(NOT content MATCHES "^relative-input-NEW[\r\n]*$")
string(APPEND RunCMake_TEST_FAILED "File\n ${f}\ndoes not have expected content.\n")
endif()
else()
string(APPEND RunCMake_TEST_FAILED "Missing\n ${f}\n")
endif()
endforeach()
@@ -0,0 +1,2 @@
cmake_policy(SET CMP0070 NEW)
file(GENERATE OUTPUT relative-output-NEW.txt INPUT relative-input-NEW.txt)
@@ -0,0 +1,13 @@
foreach(f
"${RunCMake_TEST_BINARY_DIR}/relative-input-OLD.txt"
"${RunCMake_TEST_BINARY_DIR}/relative-output-OLD.txt"
)
if(EXISTS "${f}")
file(READ "${f}" content)
if(NOT content MATCHES "^relative-input-OLD[\r\n]*$")
string(APPEND RunCMake_TEST_FAILED "File\n ${f}\ndoes not have expected content.\n")
endif()
else()
string(APPEND RunCMake_TEST_FAILED "Missing\n ${f}\n")
endif()
endforeach()
@@ -0,0 +1,3 @@
cmake_policy(SET CMP0070 OLD)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/relative-input-OLD.txt "relative-input-OLD\n")
file(GENERATE OUTPUT relative-output-OLD.txt INPUT relative-input-OLD.txt)
@@ -0,0 +1,13 @@
foreach(f
"${RunCMake_TEST_BINARY_DIR}/relative-input-WARN.txt"
"${RunCMake_TEST_BINARY_DIR}/relative-output-WARN.txt"
)
if(EXISTS "${f}")
file(READ "${f}" content)
if(NOT content MATCHES "^relative-input-WARN[\r\n]*$")
string(APPEND RunCMake_TEST_FAILED "File\n ${f}\ndoes not have expected content.\n")
endif()
else()
string(APPEND RunCMake_TEST_FAILED "Missing\n ${f}\n")
endif()
endforeach()
@@ -0,0 +1,27 @@
^CMake Warning \(dev\) in CMakeLists.txt:
Policy CMP0070 is not set: Define file\(GENERATE\) behavior for relative
paths. Run "cmake --help-policy CMP0070" for policy details. Use the
cmake_policy command to set the policy and suppress this warning.
file\(GENERATE\) given relative INPUT path:
relative-input-WARN.txt
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.
This warning is for project developers. Use -Wno-dev to suppress it.(
+
CMake Warning \(dev\) in CMakeLists.txt:
Policy CMP0070 is not set: Define file\(GENERATE\) behavior for relative
paths. Run "cmake --help-policy CMP0070" for policy details. Use the
cmake_policy command to set the policy and suppress this warning.
file\(GENERATE\) given relative OUTPUT path:
relative-output-WARN.txt
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.
This warning is for project developers. Use -Wno-dev to suppress it.)+$
@@ -0,0 +1,2 @@
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/relative-input-WARN.txt "relative-input-WARN\n")
file(GENERATE OUTPUT relative-output-WARN.txt INPUT relative-input-WARN.txt)
@@ -7,6 +7,6 @@ target_compile_options(empty
)
file(GENERATE
OUTPUT opts-$<COMPILE_LANGUAGE>.txt
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/opts-$<COMPILE_LANGUAGE>.txt
CONTENT "$<TARGET_PROPERTY:empty,COMPILE_OPTIONS>\n"
)
@@ -1,5 +1,5 @@
file(GENERATE
OUTPUT output_file.txt
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output_file.txt"
INPUT "${CMAKE_CURRENT_BINARY_DIR}/input_file.txt"
)
@@ -1,5 +1,9 @@
include(RunCMake)
run_cmake(CMP0070-NEW)
run_cmake(CMP0070-OLD)
run_cmake(CMP0070-WARN)
run_cmake(CommandConflict)
if("${RunCMake_GENERATOR}" MATCHES "Visual Studio|Xcode")
run_cmake(OutputConflict)
@@ -1,5 +1,5 @@
file(GENERATE
OUTPUT output_file.txt
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/output_file.txt
CONTENT "123"
)
@@ -0,0 +1 @@
relative-input-NEW
@@ -22,4 +22,4 @@ set_source_files_properties(some.txt PROPERTIES MACOSX_PACKAGE_LOCATION somedir)
add_custom_command(TARGET Framework POST_BUILD
COMMAND /usr/bin/file $<TARGET_FILE:Framework>)
file(GENERATE OUTPUT FrameworkName.cmake CONTENT "set(framework-dir \"$<TARGET_BUNDLE_DIR:Framework>\")\n")
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/FrameworkName.cmake CONTENT "set(framework-dir \"$<TARGET_BUNDLE_DIR:Framework>\")\n")
+2 -2
View File
@@ -1,7 +1,7 @@
add_library(iface INTERFACE)
target_sources(iface INTERFACE $<TARGET_OBJECTS:NoTarget>)
file(GENERATE OUTPUT test_output CONTENT $<TARGET_OBJECTS:NoTarget>)
file(GENERATE OUTPUT test_output2 CONTENT $<TARGET_PROPERTY:iface,INTERFACE_SOURCES>)
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/test_output CONTENT $<TARGET_OBJECTS:NoTarget>)
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/test_output2 CONTENT $<TARGET_PROPERTY:iface,INTERFACE_SOURCES>)
install(FILES $<TARGET_OBJECTS:NoTarget> DESTINATION objects)
@@ -1,3 +1,3 @@
add_library(StaticLib empty.cpp)
file(GENERATE OUTPUT test_output CONTENT $<TARGET_OBJECTS:StaticLib>)
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/test_output CONTENT $<TARGET_OBJECTS:StaticLib>)