1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
/* 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 <algorithm>
#include <functional>
#include <string>
#include <utility>
#include <vector>
#include <cm/optional>
#include "cmsys/FStream.hxx"
#include "cmGccDepfileReader.h"
#include "cmGccDepfileReaderTypes.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.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 WriteDepfile(cmDepfileFormat format, cmsys::ofstream& fout,
const cmLocalGenerator& lg,
const cmGccDepfileContent& content)
{
std::function<std::string(const std::string&)> formatPath =
[&lg](const std::string& path) -> std::string {
return lg.MaybeRelativeToTopBinDir(path);
};
if (lg.GetGlobalGenerator()->GetName() == "Xcode") {
// full paths must be preserved for Xcode compliance
formatPath = [](const std::string& path) -> std::string { return path; };
}
for (auto const& dep : content) {
bool first = true;
for (auto const& rule : dep.rules) {
if (!first) {
fout << " \\\n ";
}
first = false;
WriteFilenameGcc(fout, formatPath(rule));
}
fout << ':';
for (auto const& path : dep.paths) {
fout << " \\\n ";
WriteFilenameGcc(fout, formatPath(path));
}
fout << '\n';
}
if (format == cmDepfileFormat::MakeDepfile) {
// In this case, phony targets must be added for all dependencies
fout << "\n";
for (auto const& dep : content) {
for (auto const& path : dep.paths) {
fout << "\n";
WriteFilenameGcc(fout, formatPath(path));
fout << ":\n";
}
}
}
}
void WriteMSBuildAdditionalInputs(cmsys::ofstream& fout,
cmLocalGenerator const& lg,
cmGccDepfileContent const& content)
{
if (content.empty()) {
return;
}
// Write a UTF-8 BOM so MSBuild knows the encoding when reading the file.
static const char utf8bom[] = { static_cast<char>(0xEF),
static_cast<char>(0xBB),
static_cast<char>(0xBF) };
fout.write(utf8bom, sizeof(utf8bom));
// Write the format expected by MSBuild CustomBuild AdditionalInputs.
const char* sep = "";
for (const auto& c : content) {
for (std::string path : c.paths) {
if (!cmSystemTools::FileIsFullPath(path)) {
path = cmSystemTools::CollapseFullPath(path,
lg.GetCurrentBinaryDirectory());
}
std::replace(path.begin(), path.end(), '/', '\\');
fout << sep << path;
sep = ";";
}
}
fout << "\n";
}
}
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(), lg.GetCurrentBinaryDirectory());
if (!result) {
return false;
}
content = *std::move(result);
} else {
lg.GetMakefile()->IssueMessage(
MessageType::WARNING,
cmStrCat("Expected depfile does not exist.\n ", infile));
}
cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(outfile));
cmsys::ofstream fout(outfile.c_str());
if (!fout) {
return false;
}
switch (format) {
case cmDepfileFormat::GccDepfile:
case cmDepfileFormat::MakeDepfile:
WriteDepfile(format, fout, lg, content);
break;
case cmDepfileFormat::MSBuildAdditionalInputs:
WriteMSBuildAdditionalInputs(fout, lg, content);
break;
}
return true;
}
|