From b2c14bc7749c21b8a994ce1d9f4e736f712481b9 Mon Sep 17 00:00:00 2001 From: Kyle Edwards Date: Fri, 2 Oct 2020 14:25:30 -0400 Subject: cmake -E: Add cmake_transform_depfile internal command --- Source/CMakeLists.txt | 2 + Source/cmTransformDepfile.cxx | 114 +++++++++++++++++++++ Source/cmTransformDepfile.h | 14 +++ Source/cmcmd.cxx | 18 ++++ Tests/RunCMake/CMakeLists.txt | 1 + Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake | 21 ++++ Tests/RunCMake/TransformDepfile/deps-unix.d | 6 ++ Tests/RunCMake/TransformDepfile/deps-unix.d.txt | 8 ++ Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt | 6 ++ Tests/RunCMake/TransformDepfile/deps-windows.d | 6 ++ Tests/RunCMake/TransformDepfile/deps-windows.d.txt | 8 ++ .../TransformDepfile/deps-windows.tlog.txt | 6 ++ Tests/RunCMake/TransformDepfile/empty.d | 0 Tests/RunCMake/TransformDepfile/empty.d.txt | 0 Tests/RunCMake/TransformDepfile/empty.tlog.txt | 0 Tests/RunCMake/TransformDepfile/gccdepfile.cmake | 16 +++ .../TransformDepfile/invalid-gcc-result.txt | 1 + .../TransformDepfile/invalid-tlog-result.txt | 1 + Tests/RunCMake/TransformDepfile/invalid.d | 1 + Tests/RunCMake/TransformDepfile/noexist.d.txt | 0 Tests/RunCMake/TransformDepfile/noexist.tlog.txt | 0 Tests/RunCMake/TransformDepfile/vstlog.cmake | 16 +++ bootstrap | 4 + 23 files changed, 249 insertions(+) create mode 100644 Source/cmTransformDepfile.cxx create mode 100644 Source/cmTransformDepfile.h create mode 100644 Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake create mode 100644 Tests/RunCMake/TransformDepfile/deps-unix.d create mode 100644 Tests/RunCMake/TransformDepfile/deps-unix.d.txt create mode 100644 Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt create mode 100644 Tests/RunCMake/TransformDepfile/deps-windows.d create mode 100644 Tests/RunCMake/TransformDepfile/deps-windows.d.txt create mode 100644 Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt create mode 100644 Tests/RunCMake/TransformDepfile/empty.d create mode 100644 Tests/RunCMake/TransformDepfile/empty.d.txt create mode 100644 Tests/RunCMake/TransformDepfile/empty.tlog.txt create mode 100644 Tests/RunCMake/TransformDepfile/gccdepfile.cmake create mode 100644 Tests/RunCMake/TransformDepfile/invalid-gcc-result.txt create mode 100644 Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt create mode 100644 Tests/RunCMake/TransformDepfile/invalid.d create mode 100644 Tests/RunCMake/TransformDepfile/noexist.d.txt create mode 100644 Tests/RunCMake/TransformDepfile/noexist.tlog.txt create mode 100644 Tests/RunCMake/TransformDepfile/vstlog.cmake diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 1e16e17..2946022 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -439,6 +439,8 @@ set(SRCS cmTest.h cmTestGenerator.cxx cmTestGenerator.h + cmTransformDepfile.cxx + cmTransformDepfile.h cmUuid.cxx cmUVHandlePtr.cxx cmUVHandlePtr.h diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx new file mode 100644 index 0000000..e1f8753 --- /dev/null +++ b/Source/cmTransformDepfile.cxx @@ -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 +#include +#include +#include + +#include + +#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; +} diff --git a/Source/cmTransformDepfile.h b/Source/cmTransformDepfile.h new file mode 100644 index 0000000..792c1aa --- /dev/null +++ b/Source/cmTransformDepfile.h @@ -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 + +enum class cmDepfileFormat +{ + GccDepfile, + VsTlog, +}; + +bool cmTransformDepfile(cmDepfileFormat format, const std::string& prefix, + const std::string& infile, const std::string& outfile); diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 15d2fd1..0bdc6fa 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -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 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()); diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index a8261c6..59ca3b1 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -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) diff --git a/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake b/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake new file mode 100644 index 0000000..cb75eb0 --- /dev/null +++ b/Tests/RunCMake/TransformDepfile/RunCMakeTest.cmake @@ -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) diff --git a/Tests/RunCMake/TransformDepfile/deps-unix.d b/Tests/RunCMake/TransformDepfile/deps-unix.d new file mode 100644 index 0000000..5da5be8 --- /dev/null +++ b/Tests/RunCMake/TransformDepfile/deps-unix.d @@ -0,0 +1,6 @@ +out1 /home/build/out2: in1 /home/build/in2 + +out3 \ + /home/build/out4: \ + in3 \ + /home/build/in4 diff --git a/Tests/RunCMake/TransformDepfile/deps-unix.d.txt b/Tests/RunCMake/TransformDepfile/deps-unix.d.txt new file mode 100644 index 0000000..58770f2 --- /dev/null +++ b/Tests/RunCMake/TransformDepfile/deps-unix.d.txt @@ -0,0 +1,8 @@ +../out1 \ + /home/build/out2: \ + ../in1 \ + /home/build/in2 +../out3 \ + /home/build/out4: \ + ../in3 \ + /home/build/in4 diff --git a/Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt b/Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt new file mode 100644 index 0000000..2a26edf --- /dev/null +++ b/Tests/RunCMake/TransformDepfile/deps-unix.tlog.txt @@ -0,0 +1,6 @@ +^../out1|/home/build/out2 +../in1 +/home/build/in2 +^../out3|/home/build/out4 +../in3 +/home/build/in4 diff --git a/Tests/RunCMake/TransformDepfile/deps-windows.d b/Tests/RunCMake/TransformDepfile/deps-windows.d new file mode 100644 index 0000000..c926670 --- /dev/null +++ b/Tests/RunCMake/TransformDepfile/deps-windows.d @@ -0,0 +1,6 @@ +out1 C:/build/out2: in1 C:/build/in2 + +out3 \ + C:/build/out4: \ + in3 \ + C:/build/in4 diff --git a/Tests/RunCMake/TransformDepfile/deps-windows.d.txt b/Tests/RunCMake/TransformDepfile/deps-windows.d.txt new file mode 100644 index 0000000..47b3ebf --- /dev/null +++ b/Tests/RunCMake/TransformDepfile/deps-windows.d.txt @@ -0,0 +1,8 @@ +../out1 \ + C:/build/out2: \ + ../in1 \ + C:/build/in2 +../out3 \ + C:/build/out4: \ + ../in3 \ + C:/build/in4 diff --git a/Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt b/Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt new file mode 100644 index 0000000..1e6024d --- /dev/null +++ b/Tests/RunCMake/TransformDepfile/deps-windows.tlog.txt @@ -0,0 +1,6 @@ +^..\out1|C:\build\out2 +..\in1 +C:\build\in2 +^..\out3|C:\build\out4 +..\in3 +C:\build\in4 diff --git a/Tests/RunCMake/TransformDepfile/empty.d b/Tests/RunCMake/TransformDepfile/empty.d new file mode 100644 index 0000000..e69de29 diff --git a/Tests/RunCMake/TransformDepfile/empty.d.txt b/Tests/RunCMake/TransformDepfile/empty.d.txt new file mode 100644 index 0000000..e69de29 diff --git a/Tests/RunCMake/TransformDepfile/empty.tlog.txt b/Tests/RunCMake/TransformDepfile/empty.tlog.txt new file mode 100644 index 0000000..e69de29 diff --git a/Tests/RunCMake/TransformDepfile/gccdepfile.cmake b/Tests/RunCMake/TransformDepfile/gccdepfile.cmake new file mode 100644 index 0000000..be1e210 --- /dev/null +++ b/Tests/RunCMake/TransformDepfile/gccdepfile.cmake @@ -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() diff --git a/Tests/RunCMake/TransformDepfile/invalid-gcc-result.txt b/Tests/RunCMake/TransformDepfile/invalid-gcc-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/TransformDepfile/invalid-gcc-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt b/Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/TransformDepfile/invalid-tlog-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/TransformDepfile/invalid.d b/Tests/RunCMake/TransformDepfile/invalid.d new file mode 100644 index 0000000..9977a28 --- /dev/null +++ b/Tests/RunCMake/TransformDepfile/invalid.d @@ -0,0 +1 @@ +invalid diff --git a/Tests/RunCMake/TransformDepfile/noexist.d.txt b/Tests/RunCMake/TransformDepfile/noexist.d.txt new file mode 100644 index 0000000..e69de29 diff --git a/Tests/RunCMake/TransformDepfile/noexist.tlog.txt b/Tests/RunCMake/TransformDepfile/noexist.tlog.txt new file mode 100644 index 0000000..e69de29 diff --git a/Tests/RunCMake/TransformDepfile/vstlog.cmake b/Tests/RunCMake/TransformDepfile/vstlog.cmake new file mode 100644 index 0000000..afa78d0 --- /dev/null +++ b/Tests/RunCMake/TransformDepfile/vstlog.cmake @@ -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() diff --git a/bootstrap b/bootstrap index feccde9..9126ae6 100755 --- a/bootstrap +++ b/bootstrap @@ -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="\ -- cgit v0.12