1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmTransformDepfile.h"
12 #include <cm/optional>
14 #include "cmsys/FStream.hxx"
16 #include "cmGccDepfileReader.h"
17 #include "cmGccDepfileReaderTypes.h"
18 #include "cmGlobalGenerator.h"
19 #include "cmLocalGenerator.h"
20 #include "cmSystemTools.h"
23 void WriteFilenameGcc(cmsys::ofstream& fout, const std::string& filename)
25 for (auto c : filename) {
40 void WriteDepfile(cmDepfileFormat format, cmsys::ofstream& fout,
41 const cmLocalGenerator& lg,
42 const cmGccDepfileContent& content)
44 std::function<std::string(const std::string&)> formatPath =
45 [&lg](const std::string& path) -> std::string {
46 return lg.MaybeRelativeToTopBinDir(path);
48 if (lg.GetGlobalGenerator()->GetName() == "Xcode") {
49 // full paths must be preserved for Xcode compliance
50 formatPath = [](const std::string& path) -> std::string { return path; };
53 for (auto const& dep : content) {
55 for (auto const& rule : dep.rules) {
60 WriteFilenameGcc(fout, formatPath(rule));
63 for (auto const& path : dep.paths) {
65 WriteFilenameGcc(fout, formatPath(path));
70 if (format == cmDepfileFormat::MakeDepfile) {
71 // In this case, phony targets must be added for all dependencies
73 for (auto const& dep : content) {
74 for (auto const& path : dep.paths) {
76 WriteFilenameGcc(fout, formatPath(path));
83 void WriteMSBuildAdditionalInputs(cmsys::ofstream& fout,
84 cmLocalGenerator const& lg,
85 cmGccDepfileContent const& content)
87 if (content.empty()) {
91 // Write a UTF-8 BOM so MSBuild knows the encoding when reading the file.
92 static const char utf8bom[] = { static_cast<char>(0xEF),
93 static_cast<char>(0xBB),
94 static_cast<char>(0xBF) };
95 fout.write(utf8bom, sizeof(utf8bom));
97 // Write the format expected by MSBuild CustomBuild AdditionalInputs.
99 for (const auto& c : content) {
100 for (std::string path : c.paths) {
101 if (!cmSystemTools::FileIsFullPath(path)) {
102 path = cmSystemTools::CollapseFullPath(path,
103 lg.GetCurrentBinaryDirectory());
105 std::replace(path.begin(), path.end(), '/', '\\');
114 bool cmTransformDepfile(cmDepfileFormat format, const cmLocalGenerator& lg,
115 const std::string& infile, const std::string& outfile)
117 cmGccDepfileContent content;
118 if (cmSystemTools::FileExists(infile)) {
120 cmReadGccDepfile(infile.c_str(), lg.GetCurrentBinaryDirectory());
124 content = *std::move(result);
127 cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(outfile));
128 cmsys::ofstream fout(outfile.c_str());
133 case cmDepfileFormat::GccDepfile:
134 case cmDepfileFormat::MakeDepfile:
135 WriteDepfile(format, fout, lg, content);
137 case cmDepfileFormat::MSBuildAdditionalInputs:
138 WriteMSBuildAdditionalInputs(fout, lg, content);