Commit b2ff3c52 authored by Marc Chevrier's avatar Marc Chevrier
Browse files

cmDependsCompiler: rely now on cmGccDepfileReader for depfile parser

To avoid duplicate effort of depfile parsing and enhance robustness
of parsing against mal-formed depfiles in preparation of DEPFILE option
support of add_custom_command command for makefiles generators.
parent adc6a4c5
Pipeline #204489 canceled with stages
in 85 minutes and 51 seconds
......@@ -5,10 +5,12 @@
#include <algorithm>
#include <map>
#include <memory>
#include <string>
#include <unordered_set>
#include <utility>
#include <cm/optional>
#include <cm/string_view>
#include <cm/vector>
#include <cmext/string_view>
......@@ -16,77 +18,12 @@
#include "cmsys/FStream.hxx"
#include "cmFileTime.h"
#include "cmGccDepfileReader.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
namespace {
std::string& ReplaceAll(std::string& data, const std::string& toSearch,
const std::string& replaceStr)
{
// Get the first occurrence
auto pos = data.find(toSearch);
// Repeat until the end is reached
while (pos != std::string::npos) {
// Replace this occurrence of Sub String
data.replace(pos, toSearch.size(), replaceStr);
// Get the next occurrence from the current position
pos = data.find(toSearch, pos + replaceStr.size());
}
return data;
}
std::string& NormalizePath(std::string& item)
{
ReplaceAll(item, "$$", "$");
ReplaceAll(item, "\\ ", " ");
ReplaceAll(item, "\\#", "#");
ReplaceAll(item, "\\", "/");
return item;
}
void ParseLine(const std::string& line, std::vector<std::string>& depends)
{
auto start = line.find_first_not_of(' ');
if (start == std::string::npos || line[start] == '#') {
return;
}
auto index = start;
while ((index = line.find(' ', index)) != std::string::npos) {
if (line[index - 1] == '\\') {
index += 1;
continue;
}
auto item = line.substr(start, index - start);
if (item.back() != ':') {
// check that ':' is not present after some spaces
auto index2 = line.find_first_not_of(' ', index + 1);
if (index2 == std::string::npos || line[index2] != ':') {
// this is a dependency, add it
depends.emplace_back(std::move(NormalizePath(item)));
} else {
index = index2;
}
}
start = line.find_first_not_of(' ', index + 1);
index = start;
}
if (start != std::string::npos) {
auto item = line.substr(start);
if (line.back() != ':') {
// this is a dependency, add it
depends.emplace_back(std::move(NormalizePath(item)));
}
}
}
}
bool cmDependsCompiler::CheckDependencies(
const std::string& internalDepFile, const std::vector<std::string>& depFiles,
cmDepends::DependencyMap& dependencies,
......@@ -156,14 +93,15 @@ bool cmDependsCompiler::CheckDependencies(
"\" is newer than depends file \"",
internalDepFile, "\".\n"));
}
cmsys::ifstream fin(depFile.c_str());
if (!fin) {
continue;
}
std::vector<std::string> depends;
std::string line;
if (format == "msvc"_s) {
cmsys::ifstream fin(depFile.c_str());
if (!fin) {
continue;
}
std::string line;
if (!isValidPath) {
// insert source as first dependency
depends.push_back(source);
......@@ -172,16 +110,13 @@ bool cmDependsCompiler::CheckDependencies(
depends.emplace_back(std::move(line));
}
} else {
while (cmSystemTools::GetLineFromStream(fin, line)) {
if (line.empty()) {
continue;
}
if (line.back() == '\\') {
line.pop_back();
}
ParseLine(line, depends);
auto deps = cmReadGccDepfile(depFile.c_str());
if (!deps) {
continue;
}
// dependencies generated by the compiler contains only one target
depends = std::move(deps->front().paths);
if (depends.empty()) {
// unexpectedly empty, ignore it and continue
continue;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment