1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-14 02:08:27 +08:00

cmGccDepfileReader: Rework helper code

Fix some of the semantics of the depfile, add error handling, and
refactor cmGccDepfileLexerHelper.
This commit is contained in:
Kyle Edwards
2020-10-02 12:11:19 -04:00
parent a1988e4c80
commit 946adadd40
13 changed files with 73 additions and 28 deletions

View File

@@ -994,7 +994,7 @@ case 5:
YY_RULE_SETUP
{
// A line continuation ends the current file name.
yyextra->newDependency();
yyextra->newRuleOrDependency();
}
YY_BREAK
case 6:

View File

@@ -42,7 +42,7 @@ NEWLINE \r?\n
}
{WSPACE}*\\{NEWLINE} {
// A line continuation ends the current file name.
yyextra->newDependency();
yyextra->newRuleOrDependency();
}
{NEWLINE} {
// A newline ends the current file name and the current rule.

View File

@@ -27,23 +27,30 @@ bool cmGccDepfileLexerHelper::readFile(const char* filePath)
if (!file) {
return false;
}
newEntry();
this->newEntry();
yyscan_t scanner;
cmGccDepfile_yylex_init(&scanner);
cmGccDepfile_yyset_extra(this, scanner);
cmGccDepfile_yyrestart(file, scanner);
cmGccDepfile_yylex(scanner);
cmGccDepfile_yylex_destroy(scanner);
sanitizeContent();
this->sanitizeContent();
fclose(file);
return true;
return this->HelperState != State::Failed;
}
void cmGccDepfileLexerHelper::newEntry()
{
if (this->HelperState == State::Rule && !this->Content.empty()) {
if (!this->Content.back().rules.empty() &&
!this->Content.back().rules.back().empty()) {
this->HelperState = State::Failed;
}
return;
}
this->HelperState = State::Rule;
this->Content.emplace_back();
newRule();
this->newRule();
}
void cmGccDepfileLexerHelper::newRule()
@@ -56,20 +63,22 @@ void cmGccDepfileLexerHelper::newRule()
void cmGccDepfileLexerHelper::newDependency()
{
// printf("NEW DEP\n");
if (this->HelperState == State::Failed) {
return;
}
this->HelperState = State::Dependency;
if (this->Content.back().paths.empty() ||
!this->Content.back().paths.back().empty()) {
this->Content.back().paths.emplace_back();
auto& entry = this->Content.back();
if (entry.paths.empty() || !entry.paths.back().empty()) {
entry.paths.emplace_back();
}
}
void cmGccDepfileLexerHelper::newRuleOrDependency()
{
if (this->HelperState == State::Rule) {
newRule();
} else {
newDependency();
this->newRule();
} else if (this->HelperState == State::Dependency) {
this->newDependency();
}
}
@@ -93,6 +102,8 @@ void cmGccDepfileLexerHelper::addToCurrentPath(const char* s)
}
dst = &dep->paths.back();
} break;
case State::Failed:
return;
}
dst->append(s);
}

View File

@@ -29,7 +29,8 @@ private:
enum class State
{
Rule,
Dependency
Dependency,
Failed,
};
State HelperState = State::Rule;
};

View File

@@ -5,14 +5,15 @@
#include <type_traits>
#include <utility>
#include <cm/optional>
#include "cmGccDepfileLexerHelper.h"
cmGccDepfileContent cmReadGccDepfile(const char* filePath)
cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath)
{
cmGccDepfileContent result;
cmGccDepfileLexerHelper helper;
if (helper.readFile(filePath)) {
result = std::move(helper).extractContent();
return cm::make_optional(std::move(helper).extractContent());
}
return result;
return cm::nullopt;
}

View File

@@ -2,6 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once
#include <cm/optional>
#include "cmGccDepfileReaderTypes.h"
cmGccDepfileContent cmReadGccDepfile(const char* filePath);
cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath);

View File

@@ -15,6 +15,7 @@
#include <vector>
#include <cm/memory>
#include <cm/optional>
#include <cm/string_view>
#include <cmext/algorithm>
@@ -26,7 +27,6 @@
#include "cmCryptoHash.h"
#include "cmFileTime.h"
#include "cmGccDepfileReader.h"
#include "cmGccDepfileReaderTypes.h"
#include "cmGeneratedFileStream.h"
#include "cmQtAutoGen.h"
#include "cmQtAutoGenerator.h"
@@ -2841,14 +2841,14 @@ bool cmQtAutoMocUicT::CreateDirectories()
std::vector<std::string> cmQtAutoMocUicT::dependenciesFromDepFile(
const char* filePath)
{
cmGccDepfileContent content = cmReadGccDepfile(filePath);
if (content.empty()) {
auto const content = cmReadGccDepfile(filePath);
if (!content || content->empty()) {
return {};
}
// Moc outputs a depfile with exactly one rule.
// Discard the rule and return the dependencies.
return content.front().paths;
return content->front().paths;
}
void cmQtAutoMocUicT::Abort(bool error)

View File

@@ -5,6 +5,8 @@
#include <utility>
#include <vector>
#include <cm/optional>
#include "cmsys/FStream.hxx"
#include "cmGccDepfileReader.h"
@@ -112,19 +114,28 @@ int testGccDepfileReader(int argc, char* argv[])
std::string dataDirPath = argv[1];
dataDirPath += "/testGccDepfileReader_data";
const int numberOfTestFiles = 3;
const int numberOfTestFiles = 7; // 6th file doesn't exist
for (int i = 1; i <= numberOfTestFiles; ++i) {
const std::string base = dataDirPath + "/deps" + std::to_string(i);
const std::string depfile = base + ".d";
const std::string plainDepfile = base + ".txt";
std::cout << "Comparing " << base << " with " << plainDepfile << std::endl;
const auto actual = cmReadGccDepfile(depfile.c_str());
if (cmSystemTools::FileExists(plainDepfile)) {
if (!actual) {
std::cerr << "Reading " << depfile << " should have succeeded\n";
return 1;
}
const auto expected = readPlainDepfile(plainDepfile.c_str());
if (!compare(actual, expected)) {
dump("actual", actual);
if (!compare(*actual, expected)) {
dump("actual", *actual);
dump("expected", expected);
return 1;
}
} else if (actual) {
std::cerr << "Reading " << depfile << " should have failed\n";
return 1;
}
}
return 0;

View File

@@ -0,0 +1 @@
invalid

View File

@@ -0,0 +1,2 @@
--RULES--
--DEPENDENCIES--

View File

@@ -0,0 +1,6 @@
out1 \
out2: \
in1 \
in2
out3: in3

View File

@@ -0,0 +1,10 @@
--RULES--
out1
out2
--DEPENDENCIES--
in1
in2
--RULES--
out3
--DEPENDENCIES--
in3