CMP0058: Remove support for OLD behavior

This commit is contained in:
Brad King 2024-12-09 20:19:00 -05:00
parent c283aafe62
commit 8f9f01b24d
21 changed files with 8 additions and 310 deletions

View File

@ -1,6 +1,9 @@
CMP0058
-------
.. |REMOVED_IN_CMAKE_VERSION| replace:: 4.0
.. include:: REMOVED_PROLOGUE.txt
.. versionadded:: 3.3
Ninja requires custom command byproducts to be explicit.
@ -104,12 +107,10 @@ rules for unknown dependencies in the build tree. The ``NEW``
behavior for this policy is to not generate these and instead
require projects to specify custom command ``BYPRODUCTS`` explicitly.
.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 3.3
.. |WARNS_OR_DOES_NOT_WARN| replace::
warns when it sees unknown dependencies in out-of-source build trees
.. include:: STANDARD_ADVICE.txt
The policy setting must be in scope at the end of the top-level
``CMakeLists.txt`` file of the project and has global effect.
.. include:: DEPRECATED.txt
.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 3.3
.. |WARNED_OR_DID_NOT_WARN| replace::
warned when it saw unknown dependencies in out-of-source build trees
.. include:: REMOVED_EPILOGUE.txt

View File

@ -30,7 +30,6 @@
#include "cmDyndepCollation.h"
#include "cmFortranParser.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLinkLineComputer.h"
@ -243,9 +242,6 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
// Write explicit outputs
for (std::string const& output : build.Outputs) {
buildStr = cmStrCat(buildStr, ' ', this->EncodePath(output));
if (this->ComputingUnknownDependencies) {
this->CombinedBuildOutputs.insert(output);
}
}
// Write implicit outputs
if (!build.ImplicitOuts.empty()) {
@ -254,9 +250,6 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
buildStr = cmStrCat(buildStr, " |");
for (std::string const& implicitOut : build.ImplicitOuts) {
buildStr = cmStrCat(buildStr, ' ', this->EncodePath(implicitOut));
if (this->ComputingUnknownDependencies) {
this->CombinedBuildOutputs.insert(implicitOut);
}
}
}
@ -371,14 +364,6 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild(
{
this->AddCustomCommandRule();
if (this->ComputingUnknownDependencies) {
// we need to track every dependency that comes in, since we are trying
// to find dependencies that are side effects of build commands
for (std::string const& dep : explicitDeps) {
this->CombinedCustomCommandExplicitDependencies.insert(dep);
}
}
{
std::string ninjaDepfilePath;
bool depfileIsOutput = false;
@ -641,19 +626,11 @@ void cmGlobalNinjaGenerator::Generate()
this->ClangTidyExportFixesDirs.clear();
this->ClangTidyExportFixesFiles.clear();
this->PolicyCMP0058 =
this->LocalGenerators[0]->GetMakefile()->GetPolicyStatus(
cmPolicies::CMP0058);
this->ComputingUnknownDependencies =
(this->PolicyCMP0058 == cmPolicies::OLD ||
this->PolicyCMP0058 == cmPolicies::WARN);
this->cmGlobalGenerator::Generate();
this->WriteAssumedSourceDependencies();
this->WriteTargetAliases(*this->GetCommonFileStream());
this->WriteFolderTargets(*this->GetCommonFileStream());
this->WriteUnknownExplicitDependencies(*this->GetCommonFileStream());
this->WriteBuiltinTargets(*this->GetCommonFileStream());
if (cmSystemTools::GetErrorOccurredFlag()) {
@ -1227,10 +1204,6 @@ void cmGlobalNinjaGenerator::AddCXXCompileCommand(
if (!this->CompileCommandsStream) {
std::string buildFilePath =
cmStrCat(buildFileDir, "/compile_commands.json");
if (this->ComputingUnknownDependencies) {
this->CombinedBuildOutputs.insert(
this->NinjaOutputPath("compile_commands.json"));
}
// Get a stream where to generate things.
this->CompileCommandsStream =
@ -1779,128 +1752,6 @@ void cmGlobalNinjaGenerator::WriteFolderTargets(std::ostream& os)
}
}
void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
{
if (!this->ComputingUnknownDependencies) {
return;
}
// We need to collect the set of known build outputs.
// Start with those generated by WriteBuild calls.
// No other method needs this so we can take ownership
// of the set locally and throw it out when we are done.
std::set<std::string> knownDependencies;
knownDependencies.swap(this->CombinedBuildOutputs);
// now write out the unknown explicit dependencies.
// union the configured files, evaluations files and the
// CombinedBuildOutputs,
// and then difference with CombinedExplicitDependencies to find the explicit
// dependencies that we have no rule for
cmGlobalNinjaGenerator::WriteDivider(os);
/* clang-format off */
os << "# Unknown Build Time Dependencies.\n"
<< "# Tell Ninja that they may appear as side effects of build rules\n"
<< "# otherwise ordered by order-only dependencies.\n\n";
/* clang-format on */
// get the list of files that cmake itself has generated as a
// product of configuration.
for (const auto& lg : this->LocalGenerators) {
// get the vector of files created by this makefile and convert them
// to ninja paths, which are all relative in respect to the build directory
for (std::string const& file : lg->GetMakefile()->GetOutputFiles()) {
knownDependencies.insert(this->ConvertToNinjaPath(file));
}
if (!this->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION")) {
// get list files which are implicit dependencies as well and will be
// phony for rebuild manifest
for (std::string const& j : lg->GetMakefile()->GetListFiles()) {
knownDependencies.insert(this->ConvertToNinjaPath(j));
}
}
for (const auto& li : lg->GetMakefile()->GetEvaluationFiles()) {
// get all the files created by generator expressions and convert them
// to ninja paths
for (std::string const& evaluationFile : li->GetFiles()) {
knownDependencies.insert(this->ConvertToNinjaPath(evaluationFile));
}
}
}
knownDependencies.insert(this->CMakeCacheFile);
for (auto const& ta : this->TargetAliases) {
knownDependencies.insert(this->ConvertToNinjaPath(ta.first));
}
// remove all source files we know will exist.
for (auto const& i : this->AssumedSourceDependencies) {
knownDependencies.insert(this->ConvertToNinjaPath(i.first));
}
// now we difference with CombinedCustomCommandExplicitDependencies to find
// the list of items we know nothing about.
// We have encoded all the paths in CombinedCustomCommandExplicitDependencies
// and knownDependencies so no matter if unix or windows paths they
// should all match now.
std::vector<std::string> unknownExplicitDepends;
this->CombinedCustomCommandExplicitDependencies.erase(this->TargetAll);
std::set_difference(this->CombinedCustomCommandExplicitDependencies.begin(),
this->CombinedCustomCommandExplicitDependencies.end(),
knownDependencies.begin(), knownDependencies.end(),
std::back_inserter(unknownExplicitDepends));
std::vector<std::string> warnExplicitDepends;
if (!unknownExplicitDepends.empty()) {
cmake* cmk = this->GetCMakeInstance();
std::string const& buildRoot = cmk->GetHomeOutputDirectory();
bool const inSource = (buildRoot == cmk->GetHomeDirectory());
bool const warn = (!inSource && (this->PolicyCMP0058 == cmPolicies::WARN));
cmNinjaBuild build("phony");
build.Outputs.emplace_back("");
for (std::string const& ued : unknownExplicitDepends) {
// verify the file is in the build directory
std::string const absDepPath =
cmSystemTools::CollapseFullPath(ued, buildRoot);
if (cmSystemTools::IsSubDirectory(absDepPath, buildRoot)) {
// Generate phony build statement
build.Outputs[0] = ued;
this->WriteBuild(os, build);
// Add to warning on demand
if (warn && warnExplicitDepends.size() < 10) {
warnExplicitDepends.push_back(ued);
}
}
}
}
if (!warnExplicitDepends.empty()) {
std::ostringstream w;
/* clang-format off */
w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0058) << "\n"
"This project specifies custom command DEPENDS on files "
"in the build tree that are not specified as the OUTPUT or "
"BYPRODUCTS of any add_custom_command or add_custom_target:\n"
" " << cmJoin(warnExplicitDepends, "\n ") <<
"\n"
"For compatibility with versions of CMake that did not have "
"the BYPRODUCTS option, CMake is generating phony rules for "
"such files to convince 'ninja' to build."
"\n"
"Project authors should add the missing BYPRODUCTS or OUTPUT "
"options to the custom commands that produce these files."
;
/* clang-format on */
this->GetCMakeInstance()->IssueMessage(MessageType::AUTHOR_WARNING,
w.str());
}
}
void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os)
{
// Write headers.

View File

@ -23,7 +23,6 @@
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalGeneratorFactory.h"
#include "cmNinjaTypes.h"
#include "cmPolicies.h"
#include "cmStringAlgorithms.h"
#include "cmTransformDepfile.h"
@ -531,7 +530,6 @@ private:
void WriteTargetAliases(std::ostream& os);
void WriteFolderTargets(std::ostream& os);
void WriteUnknownExplicitDependencies(std::ostream& os);
void WriteBuiltinTargets(std::ostream& os);
void WriteTargetDefault(std::ostream& os);
@ -566,18 +564,6 @@ private:
/// The set of custom command outputs we have seen.
std::set<std::string> CustomCommandOutputs;
/// Whether we are collecting known build outputs and needed
/// dependencies to determine unknown dependencies.
bool ComputingUnknownDependencies = false;
cmPolicies::PolicyStatus PolicyCMP0058 = cmPolicies::WARN;
/// The combined explicit dependencies of custom build commands
std::set<std::string> CombinedCustomCommandExplicitDependencies;
/// When combined with CombinedCustomCommandExplicitDependencies it allows
/// us to detect the set of explicit dependencies that have
std::set<std::string> CombinedBuildOutputs;
/// The mapping from source file to assumed dependencies.
std::map<std::string, std::set<std::string>> AssumedSourceDependencies;

View File

@ -171,7 +171,7 @@ class cmMakefile;
SELECT(POLICY, CMP0057, "Support new IN_LIST if() operator.", 3, 3, 0, NEW) \
SELECT(POLICY, CMP0058, \
"Ninja requires custom command byproducts to be explicit.", 3, 3, 0, \
WARN) \
NEW) \
SELECT(POLICY, CMP0059, \
"Do not treat DEFINITIONS as a built-in directory property.", 3, 3, \
0, WARN) \

View File

@ -1,5 +1,4 @@
cmake_minimum_required(VERSION 3.10)
cmake_policy(SET CMP0058 OLD)
project(CustomCommandByproducts C)
# Generate a byproduct in a rule that runs in the target consuming it.
@ -203,10 +202,3 @@ target_link_libraries(
ExternalLibraryByproducts_WithInstallDirSubstitution
ExternalLibraryWithInstallDirSubstitution
)
if(CMAKE_GENERATOR STREQUAL "Ninja")
add_custom_target(CheckNinja ALL
COMMENT "Checking build.ninja"
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/ninja-check.cmake
)
endif()

View File

@ -1,20 +0,0 @@
file(READ build.ninja build_ninja)
if("${build_ninja}" MATCHES [====[
# Unknown Build Time Dependencies.
# Tell Ninja that they may appear as side effects of build rules
# otherwise ordered by order-only dependencies.
((build [^:]*: phony[^\n]*
)*)# ========]====])
set(phony "${CMAKE_MATCH_1}")
if(NOT phony)
message(STATUS "build.ninja correctly does not have extra phony rules")
else()
string(REGEX REPLACE "\n+$" "" phony "${phony}")
string(REGEX REPLACE "\n" "\n " phony " ${phony}")
message(FATAL_ERROR "build.ninja incorrectly has extra phony rules:\n"
"${phony}")
endif()
else()
message(FATAL_ERROR "build.ninja is incorrectly missing expected block")
endif()

View File

@ -1,3 +1,2 @@
cmake_policy(SET CMP0058 NEW)
set(byproducts BYPRODUCTS byproduct1a byproduct1b)
include(CMP0058-common.cmake)

View File

@ -1,2 +1 @@
cmake_policy(SET CMP0058 NEW)
include(CMP0058-common.cmake)

View File

@ -1,4 +0,0 @@
^[^
]* Generating output1
[^
]* Generating output2$

View File

@ -1,20 +0,0 @@
^CMake Deprecation Warning at CMP0058-OLD-by\.cmake:[0-9] \(cmake_policy\):
Compatibility with CMake < 3\.10 will be removed from a future version of
CMake\.
Update the VERSION argument <min> value\. Or, use the <min>\.\.\.<max> syntax
to tell CMake that the project requires at least <min> but has been updated
to work with policies introduced by <max> or earlier\.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9] \(include\)
+
CMake Deprecation Warning at CMP0058-OLD-by\.cmake:[0-9]+ \(cmake_policy\):
The OLD behavior for policy CMP0058 will be removed from a future version
of CMake\.
The cmake-policies\(7\) manual explains that the OLD behaviors of all
policies are deprecated and that a policy should be set to OLD only under
specific short-term circumstances. Projects should be ported to the NEW
behavior and not rely on setting a policy to OLD.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)$

View File

@ -1,4 +0,0 @@
cmake_policy(VERSION 3.2)
cmake_policy(SET CMP0058 OLD)
set(byproducts BYPRODUCTS byproduct1a byproduct1b)
include(CMP0058-common.cmake)

View File

@ -1,4 +0,0 @@
^[^
]* Generating output1
[^
]* Generating output2$

View File

@ -1,20 +0,0 @@
^CMake Deprecation Warning at CMP0058-OLD-no\.cmake:[0-9] \(cmake_policy\):
Compatibility with CMake < 3\.10 will be removed from a future version of
CMake\.
Update the VERSION argument <min> value\. Or, use the <min>\.\.\.<max> syntax
to tell CMake that the project requires at least <min> but has been updated
to work with policies introduced by <max> or earlier\.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9] \(include\)
+
CMake Deprecation Warning at CMP0058-OLD-no\.cmake:[0-9]+ \(cmake_policy\):
The OLD behavior for policy CMP0058 will be removed from a future version
of CMake\.
The cmake-policies\(7\) manual explains that the OLD behaviors of all
policies are deprecated and that a policy should be set to OLD only under
specific short-term circumstances. Projects should be ported to the NEW
behavior and not rely on setting a policy to OLD.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)$

View File

@ -1,3 +0,0 @@
cmake_policy(VERSION 3.2)
cmake_policy(SET CMP0058 OLD)
include(CMP0058-common.cmake)

View File

@ -1,4 +0,0 @@
^[^
]* Generating output1
[^
]* Generating output2$

View File

@ -1,9 +0,0 @@
^CMake Deprecation Warning at CMP0058-WARN-by\.cmake:[0-9] \(cmake_policy\):
Compatibility with CMake < 3\.10 will be removed from a future version of
CMake\.
Update the VERSION argument <min> value\. Or, use the <min>\.\.\.<max> syntax
to tell CMake that the project requires at least <min> but has been updated
to work with policies introduced by <max> or earlier\.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9] \(include\)$

View File

@ -1,3 +0,0 @@
cmake_policy(VERSION 3.2)
set(byproducts BYPRODUCTS byproduct1a byproduct1b)
include(CMP0058-common.cmake)

View File

@ -1,4 +0,0 @@
^[^
]* Generating output1
[^
]* Generating output2$

View File

@ -1,29 +0,0 @@
^CMake Deprecation Warning at CMP0058-WARN-no\.cmake:[0-9] \(cmake_policy\):
Compatibility with CMake < 3\.10 will be removed from a future version of
CMake\.
Update the VERSION argument <min> value\. Or, use the <min>\.\.\.<max> syntax
to tell CMake that the project requires at least <min> but has been updated
to work with policies introduced by <max> or earlier\.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9] \(include\)
+
CMake Warning \(dev\):
Policy CMP0058 is not set: Ninja requires custom command byproducts to be
explicit. Run "cmake --help-policy CMP0058" for policy details. Use the
cmake_policy command to set the policy and suppress this warning.
This project specifies custom command DEPENDS on files in the build tree
that are not specified as the OUTPUT or BYPRODUCTS of any
add_custom_command or add_custom_target:
byproduct1a
byproduct1b
For compatibility with versions of CMake that did not have the BYPRODUCTS
option, CMake is generating phony rules for such files to convince 'ninja'
to build.
Project authors should add the missing BYPRODUCTS or OUTPUT options to the
custom commands that produce these files.
This warning is for project developers. Use -Wno-dev to suppress it.

View File

@ -1,2 +0,0 @@
cmake_policy(VERSION 3.2)
include(CMP0058-common.cmake)

View File

@ -93,10 +93,6 @@ function(run_CMP0058 case)
run_cmake_command(CMP0058-${case}-build ${CMAKE_COMMAND} --build .)
endfunction()
run_CMP0058(OLD-no)
run_CMP0058(OLD-by)
run_CMP0058(WARN-no)
run_CMP0058(WARN-by)
run_CMP0058(NEW-no)
run_CMP0058(NEW-by)