1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-14 02:08:27 +08:00

Ninja: add_custom_command(DEPFILE): Ensure dependencies consistency

Fixes: #21694
This commit is contained in:
Marc Chevrier
2021-01-16 17:37:23 +01:00
parent 5b9f7a5f28
commit b5c2163293
17 changed files with 99 additions and 64 deletions

View File

@@ -200,6 +200,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
argv.push_back(cmSystemTools::GetCMakeCommand());
argv.emplace_back("-E");
argv.emplace_back("cmake_transform_depfile");
argv.push_back(this->LG->GetGlobalGenerator()->GetName());
switch (*this->LG->GetGlobalGenerator()->DepfileFormat()) {
case cmDepfileFormat::GccDepfile:
argv.emplace_back("gccdepfile");
@@ -208,15 +209,10 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
argv.emplace_back("vstlog");
break;
}
if (this->LG->GetCurrentBinaryDirectory() ==
this->LG->GetBinaryDirectory()) {
argv.emplace_back("./");
} else {
argv.push_back(cmStrCat(this->LG->MaybeConvertToRelativePath(
this->LG->GetBinaryDirectory(),
this->LG->GetCurrentBinaryDirectory()),
'/'));
}
argv.push_back(this->LG->GetSourceDirectory());
argv.push_back(this->LG->GetCurrentSourceDirectory());
argv.push_back(this->LG->GetBinaryDirectory());
argv.push_back(this->LG->GetCurrentBinaryDirectory());
argv.push_back(this->GetFullDepfile());
argv.push_back(this->GetInternalDepfile());

View File

@@ -97,17 +97,8 @@ bool cmDependsCompiler::CheckDependencies(
std::vector<std::string> depends;
if (format == "custom"_s) {
std::string prefix;
if (this->LocalGenerator->GetCurrentBinaryDirectory() !=
this->LocalGenerator->GetBinaryDirectory()) {
prefix =
cmStrCat(this->LocalGenerator->MaybeConvertToRelativePath(
this->LocalGenerator->GetBinaryDirectory(),
this->LocalGenerator->GetCurrentBinaryDirectory()),
'/');
}
auto deps = cmReadGccDepfile(depFile.c_str(), prefix);
auto deps = cmReadGccDepfile(
depFile.c_str(), this->LocalGenerator->GetCurrentBinaryDirectory());
if (!deps) {
continue;
}

View File

@@ -24,7 +24,7 @@ cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath,
for (auto& dep : *deps) {
for (auto& rule : dep.rules) {
if (!prefix.empty() && !cmSystemTools::FileIsFullPath(rule)) {
rule = cmStrCat(prefix, rule);
rule = cmStrCat(prefix, '/', rule);
}
if (cmSystemTools::FileIsFullPath(rule)) {
rule = cmSystemTools::CollapseFullPath(rule);
@@ -33,7 +33,7 @@ cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath,
}
for (auto& path : dep.paths) {
if (!prefix.empty() && !cmSystemTools::FileIsFullPath(path)) {
path = cmStrCat(prefix, path);
path = cmStrCat(prefix, '/', path);
}
if (cmSystemTools::FileIsFullPath(path)) {
path = cmSystemTools::CollapseFullPath(path);

View File

@@ -13,6 +13,7 @@
#include "cmGccDepfileReader.h"
#include "cmGccDepfileReaderTypes.h"
#include "cmLocalGenerator.h"
#include "cmSystemTools.h"
namespace {
@@ -33,8 +34,11 @@ void WriteFilenameGcc(cmsys::ofstream& fout, const std::string& filename)
}
}
void WriteGccDepfile(cmsys::ofstream& fout, const cmGccDepfileContent& content)
void WriteGccDepfile(cmsys::ofstream& fout, const cmLocalGenerator& lg,
const cmGccDepfileContent& content)
{
const auto& binDir = lg.GetBinaryDirectory();
for (auto const& dep : content) {
bool first = true;
for (auto const& rule : dep.rules) {
@@ -42,19 +46,32 @@ void WriteGccDepfile(cmsys::ofstream& fout, const cmGccDepfileContent& content)
fout << " \\\n ";
}
first = false;
WriteFilenameGcc(fout, rule);
WriteFilenameGcc(fout, lg.MaybeConvertToRelativePath(binDir, rule));
}
fout << ':';
for (auto const& path : dep.paths) {
fout << " \\\n ";
WriteFilenameGcc(fout, path);
WriteFilenameGcc(fout, lg.MaybeConvertToRelativePath(binDir, path));
}
fout << '\n';
}
}
void WriteVsTlog(cmsys::ofstream& fout, const cmGccDepfileContent& content)
// tlog format : always windows paths on Windows regardless the generator
std::string ConvertToTLogOutputPath(const std::string& path)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
return cmSystemTools::ConvertToWindowsOutputPath(path);
#else
return cmSystemTools::ConvertToOutputPath(path);
#endif
}
void WriteVsTlog(cmsys::ofstream& fout, const cmLocalGenerator& lg,
const cmGccDepfileContent& content)
{
const auto& binDir = lg.GetBinaryDirectory();
for (auto const& dep : content) {
fout << '^';
bool first = true;
@@ -63,22 +80,26 @@ void WriteVsTlog(cmsys::ofstream& fout, const cmGccDepfileContent& content)
fout << '|';
}
first = false;
fout << cmSystemTools::ConvertToOutputPath(rule);
fout << ConvertToTLogOutputPath(
lg.MaybeConvertToRelativePath(binDir, rule));
}
fout << "\r\n";
for (auto const& path : dep.paths) {
fout << cmSystemTools::ConvertToOutputPath(path) << "\r\n";
fout << ConvertToTLogOutputPath(
lg.MaybeConvertToRelativePath(binDir, path))
<< "\r\n";
}
}
}
}
bool cmTransformDepfile(cmDepfileFormat format, const std::string& prefix,
bool cmTransformDepfile(cmDepfileFormat format, const cmLocalGenerator& lg,
const std::string& infile, const std::string& outfile)
{
cmGccDepfileContent content;
if (cmSystemTools::FileExists(infile)) {
auto result = cmReadGccDepfile(infile.c_str(), prefix);
auto result =
cmReadGccDepfile(infile.c_str(), lg.GetCurrentBinaryDirectory());
if (!result) {
return false;
}
@@ -91,10 +112,10 @@ bool cmTransformDepfile(cmDepfileFormat format, const std::string& prefix,
}
switch (format) {
case cmDepfileFormat::GccDepfile:
WriteGccDepfile(fout, content);
WriteGccDepfile(fout, lg, content);
break;
case cmDepfileFormat::VsTlog:
WriteVsTlog(fout, content);
WriteVsTlog(fout, lg, content);
break;
}
return true;

View File

@@ -10,5 +10,7 @@ enum class cmDepfileFormat
VsTlog,
};
bool cmTransformDepfile(cmDepfileFormat format, const std::string& prefix,
class cmLocalGenerator;
bool cmTransformDepfile(cmDepfileFormat format, const cmLocalGenerator& lg,
const std::string& infile, const std::string& outfile);

View File

@@ -1522,20 +1522,42 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
#endif
// Internal depfile transformation
if (args[1] == "cmake_transform_depfile" && args.size() == 6) {
if (args[1] == "cmake_transform_depfile" && args.size() == 10) {
auto format = cmDepfileFormat::GccDepfile;
if (args[2] == "gccdepfile") {
if (args[3] == "gccdepfile") {
format = cmDepfileFormat::GccDepfile;
} else if (args[2] == "vstlog") {
} else if (args[3] == "vstlog") {
format = cmDepfileFormat::VsTlog;
} else {
return 1;
}
std::string prefix = args[3];
if (prefix == "./") {
prefix.clear();
// Create a cmake object instance to process dependencies.
// All we need is the `set` command.
cmake cm(cmake::RoleScript, cmState::Unknown);
std::string homeDir;
std::string startDir;
std::string homeOutDir;
std::string startOutDir;
homeDir = cmSystemTools::CollapseFullPath(args[4]);
startDir = cmSystemTools::CollapseFullPath(args[5]);
homeOutDir = cmSystemTools::CollapseFullPath(args[6]);
startOutDir = cmSystemTools::CollapseFullPath(args[7]);
cm.SetHomeDirectory(homeDir);
cm.SetHomeOutputDirectory(homeOutDir);
cm.GetCurrentSnapshot().SetDefaultDefinitions();
if (auto ggd = cm.CreateGlobalGenerator(args[2])) {
cm.SetGlobalGenerator(std::move(ggd));
cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
snapshot.GetDirectory().SetCurrentBinary(startOutDir);
snapshot.GetDirectory().SetCurrentSource(startDir);
snapshot.GetDirectory().SetRelativePathTopSource(homeDir.c_str());
snapshot.GetDirectory().SetRelativePathTopBinary(homeOutDir.c_str());
cmMakefile mf(cm.GetGlobalGenerator(), snapshot);
auto lgd = cm.GetGlobalGenerator()->CreateLocalGenerator(&mf);
return cmTransformDepfile(format, *lgd, args[8], args[9]) ? 0 : 2;
}
return cmTransformDepfile(format, prefix, args[4], args[5]) ? 0 : 1;
return 1;
}
}

View File

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

View File

@@ -4,7 +4,7 @@ enable_language(C)
add_custom_command(
OUTPUT topcc.c
DEPFILE topcc.c.d
COMMAND ${CMAKE_COMMAND} -DOUTFILE=topcc.c -DINFILE=topccdep.txt -DDEPFILE=topcc.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake"
COMMAND ${CMAKE_COMMAND} -DOUTFILE=${CMAKE_CURRENT_BINARY_DIR}/topcc.c -DINFILE=topccdep.txt -DDEPFILE=topcc.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake"
)
add_custom_target(topcc ALL DEPENDS topcc.c)

View File

@@ -3,7 +3,7 @@ cmake_policy(SET CMP0116 NEW)
add_custom_command(
OUTPUT subcc.c
DEPFILE subcc.c.d
COMMAND ${CMAKE_COMMAND} -DOUTFILE=subcc.c -DINFILE=subccdep.txt -DDEPFILE=subcc.c.d -P "${CMAKE_CURRENT_LIST_DIR}/../WriteDepfile.cmake"
COMMAND ${CMAKE_COMMAND} -DOUTFILE=${CMAKE_CURRENT_BINARY_DIR}/subcc.c -DINFILE=subccdep.txt -DDEPFILE=subcc.c.d -P "${CMAKE_CURRENT_LIST_DIR}/../WriteDepfile.cmake"
)
add_custom_target(subcc ALL DEPENDS subcc.c)

View File

@@ -796,7 +796,10 @@ add_RunCMake_test(PrecompileHeaders -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
add_RunCMake_test("UnityBuild")
add_RunCMake_test(CMakePresets -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA})
if(${CMAKE_GENERATOR} MATCHES "Make|Ninja")
add_RunCMake_test(TransformDepfile)
endif()
if(WIN32)
add_RunCMake_test(Win32GenEx)

View File

@@ -3,11 +3,11 @@ include(RunCMake)
function(run_transform_depfile name)
set(RunCMake-check-file gccdepfile.cmake)
run_cmake_command(${name}-gcc
${CMAKE_COMMAND} -E cmake_transform_depfile gccdepfile ../ ${CMAKE_CURRENT_LIST_DIR}/${name}.d out.d
${CMAKE_COMMAND} -E cmake_transform_depfile "${RunCMake_GENERATOR}" gccdepfile "${RunCMake_SOURCE_DIR}" "${RunCMake_SOURCE_DIR}/subdir" "${RunCMake_BINARY_DIR}" "${RunCMake_BINARY_DIR}/subdir" "${CMAKE_CURRENT_LIST_DIR}/${name}.d" out.d
)
set(RunCMake-check-file vstlog.cmake)
run_cmake_command(${name}-tlog
${CMAKE_COMMAND} -E cmake_transform_depfile vstlog ../ ${CMAKE_CURRENT_LIST_DIR}/${name}.d out.tlog
${CMAKE_COMMAND} -E cmake_transform_depfile "${RunCMake_GENERATOR}" vstlog "${RunCMake_SOURCE_DIR}" "${RunCMake_SOURCE_DIR}/subdir" "${RunCMake_BINARY_DIR}" "${RunCMake_BINARY_DIR}/subdir" "${CMAKE_CURRENT_LIST_DIR}/${name}.d" out.tlog
)
endfunction()

View File

@@ -1,8 +1,8 @@
../out1 \
subdir/out1 \
/home/build/out2: \
../in1 \
subdir/in1 \
/home/build/in2
../out3 \
subdir/out3 \
/home/build/out4: \
../in3 \
subdir/in3 \
/home/build/in4

View File

@@ -1,6 +1,6 @@
^../out1|/home/build/out2
../in1
^subdir/out1|/home/build/out2
subdir/in1
/home/build/in2
^../out3|/home/build/out4
../in3
^subdir/out3|/home/build/out4
subdir/in3
/home/build/in4

View File

@@ -1,8 +1,8 @@
../out1 \
subdir/out1 \
C:/build/out2: \
../in1 \
subdir/in1 \
C:/build/in2
../out3 \
subdir/out3 \
C:/build/out4: \
../in3 \
subdir/in3 \
C:/build/in4

View File

@@ -1,6 +1,6 @@
^..\out1|C:\build\out2
..\in1
^subdir\out1|C:\build\out2
subdir\in1
C:\build\in2
^..\out3|C:\build\out4
..\in3
^subdir\out3|C:\build\out4
subdir\in3
C:\build\in4