cmake -E: Add cmake_transform_depfile internal command

This commit is contained in:
Kyle Edwards 2020-10-02 14:25:30 -04:00
parent 946adadd40
commit b2c14bc774
23 changed files with 249 additions and 0 deletions

View File

@ -439,6 +439,8 @@ set(SRCS
cmTest.h
cmTestGenerator.cxx
cmTestGenerator.h
cmTransformDepfile.cxx
cmTransformDepfile.h
cmUuid.cxx
cmUVHandlePtr.cxx
cmUVHandlePtr.h

View File

@ -0,0 +1,114 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTransformDepfile.h"
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include <cm/optional>
#include "cmsys/FStream.hxx"
#include "cmGccDepfileReader.h"
#include "cmGccDepfileReaderTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
namespace {
void WriteFilenameGcc(cmsys::ofstream& fout, const std::string& filename)
{
for (auto c : filename) {
switch (c) {
case ' ':
fout << "\\ ";
break;
case '\\':
fout << "\\\\";
break;
default:
fout << c;
break;
}
}
}
void WriteGccDepfile(cmsys::ofstream& fout, const cmGccDepfileContent& content)
{
for (auto const& dep : content) {
bool first = true;
for (auto const& rule : dep.rules) {
if (!first) {
fout << " \\\n ";
}
first = false;
WriteFilenameGcc(fout, rule);
}
fout << ':';
for (auto const& path : dep.paths) {
fout << " \\\n " << path;
}
fout << '\n';
}
}
void WriteVsTlog(cmsys::ofstream& fout, const cmGccDepfileContent& content)
{
for (auto const& dep : content) {
fout << '^';
bool first = true;
for (auto const& rule : dep.rules) {
if (!first) {
fout << '|';
}
first = false;
fout << cmSystemTools::ConvertToOutputPath(rule);
}
fout << "\r\n";
for (auto const& path : dep.paths) {
fout << cmSystemTools::ConvertToOutputPath(path) << "\r\n";
}
}
}
}
bool cmTransformDepfile(cmDepfileFormat format, const std::string& prefix,
const std::string& infile, const std::string& outfile)
{
cmGccDepfileContent content;
if (cmSystemTools::FileExists(infile)) {
auto result = cmReadGccDepfile(infile.c_str());
if (!result) {
return false;
}
content = *std::move(result);
}
for (auto& dep : content) {
for (auto& rule : dep.rules) {
if (!cmSystemTools::FileIsFullPath(rule)) {
rule = cmStrCat(prefix, rule);
}
}
for (auto& path : dep.paths) {
if (!cmSystemTools::FileIsFullPath(path)) {
path = cmStrCat(prefix, path);
}
}
}
cmsys::ofstream fout(outfile.c_str());
if (!fout) {
return false;
}
switch (format) {
case cmDepfileFormat::GccDepfile:
WriteGccDepfile(fout, content);
break;
case cmDepfileFormat::VsTlog:
WriteVsTlog(fout, content);
break;
}
return true;
}

View File

@ -0,0 +1,14 @@
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include <string>
enum class cmDepfileFormat
{
GccDepfile,
VsTlog,
};
bool cmTransformDepfile(cmDepfileFormat format, const std::string& prefix,
const std::string& infile, const std::string& outfile);

View File

@ -19,6 +19,7 @@
#include "cmStateSnapshot.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTransformDepfile.h"
#include "cmUVProcessChain.h"
#include "cmUtils.hxx"
#include "cmVersion.h"
@ -1426,6 +1427,23 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
return cmcmd::WindowsCEEnvironment("9.0", args[2]);
}
#endif
// Internal depfile transformation
if (args[1] == "cmake_transform_depfile" && args.size() == 6) {
auto format = cmDepfileFormat::GccDepfile;
if (args[2] == "gccdepfile") {
format = cmDepfileFormat::GccDepfile;
} else if (args[2] == "vstlog") {
format = cmDepfileFormat::VsTlog;
} else {
return 1;
}
std::string prefix = args[3];
if (prefix == "./") {
prefix.clear();
}
return cmTransformDepfile(format, prefix, args[4], args[5]) ? 0 : 1;
}
}
::CMakeCommandUsage(args[0].c_str());

View File

@ -771,6 +771,7 @@ add_RunCMake_test(PrecompileHeaders -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
add_RunCMake_test("UnityBuild")
add_RunCMake_test(CMakePresets)
add_RunCMake_test(TransformDepfile)
if(WIN32)
add_RunCMake_test(Win32GenEx)

View File

@ -0,0 +1,21 @@
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
)
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
)
endfunction()
if(WIN32)
run_transform_depfile(deps-windows)
else()
run_transform_depfile(deps-unix)
endif()
run_transform_depfile(noexist)
run_transform_depfile(empty)
run_transform_depfile(invalid)

View File

@ -0,0 +1,6 @@
out1 /home/build/out2: in1 /home/build/in2
out3 \
/home/build/out4: \
in3 \
/home/build/in4

View File

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

View File

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

View File

@ -0,0 +1,6 @@
out1 C:/build/out2: in1 C:/build/in2
out3 \
C:/build/out4: \
in3 \
C:/build/in4

View File

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

View File

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

View File

View File

@ -0,0 +1,16 @@
if(EXISTS "${RunCMake_SOURCE_DIR}/${name}.d.txt")
file(READ "${RunCMake_SOURCE_DIR}/${name}.d.txt" expected_contents)
if(EXISTS "${RunCMake_TEST_BINARY_DIR}/out.d")
file(READ "${RunCMake_TEST_BINARY_DIR}/out.d" actual_contents)
if(NOT actual_contents STREQUAL expected_contents)
string(REPLACE "\n" "\n " p_expected_contents "${expected_contents}")
string(REPLACE "\n" "\n " p_actual_contents "${actual_contents}")
string(APPEND RunCMake_TEST_FAILED "Expected contents of ${RunCMake_TEST_BINARY_DIR}/out.d:\n ${p_expected_contents}\nActual contents:\n ${p_actual_contents}")
endif()
else()
string(APPEND RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/out.d should exist\n")
endif()
elseif(EXISTS "${RunCMake_TEST_BINARY_DIR}/out.d")
string(APPEND RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/out.d should not exist\n")
endif()

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1 @@
invalid

View File

@ -0,0 +1,16 @@
if(EXISTS "${RunCMake_SOURCE_DIR}/${name}.tlog.txt")
file(READ "${RunCMake_SOURCE_DIR}/${name}.tlog.txt" expected_contents)
if(EXISTS "${RunCMake_TEST_BINARY_DIR}/out.tlog")
file(READ "${RunCMake_TEST_BINARY_DIR}/out.tlog" actual_contents)
if(NOT actual_contents STREQUAL expected_contents)
string(REPLACE "\n" "\n " p_expected_contents "${expected_contents}")
string(REPLACE "\n" "\n " p_actual_contents "${actual_contents}")
string(APPEND RunCMake_TEST_FAILED "Expected contents of ${RunCMake_TEST_BINARY_DIR}/out.tlog:\n ${p_expected_contents}\nActual contents:\n ${p_actual_contents}")
endif()
else()
string(APPEND RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/out.tlog should exist\n")
endif()
elseif(EXISTS "${RunCMake_TEST_BINARY_DIR}/out.tlog")
string(APPEND RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/out.tlog should not exist\n")
endif()

View File

@ -412,6 +412,8 @@ CMAKE_CXX_SOURCES="\
cmProjectCommand \
cmPropertyDefinition \
cmPropertyMap \
cmGccDepfileLexerHelper \
cmGccDepfileReader \
cmReturnCommand \
cmRulePlaceholderExpander \
cmRuntimeDependencyArchive \
@ -452,6 +454,7 @@ CMAKE_CXX_SOURCES="\
cmTest \
cmTestGenerator \
cmTimestamp \
cmTransformDepfile \
cmTryCompileCommand \
cmTryRunCommand \
cmUnsetCommand \
@ -491,6 +494,7 @@ LexerParser_CXX_SOURCES="\
cmCommandArgumentParser \
cmExprLexer \
cmExprParser \
cmGccDepfileLexer \
"
LexerParser_C_SOURCES="\