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 YY_RULE_SETUP
{ {
// A line continuation ends the current file name. // A line continuation ends the current file name.
yyextra->newDependency(); yyextra->newRuleOrDependency();
} }
YY_BREAK YY_BREAK
case 6: case 6:

View File

@@ -42,7 +42,7 @@ NEWLINE \r?\n
} }
{WSPACE}*\\{NEWLINE} { {WSPACE}*\\{NEWLINE} {
// A line continuation ends the current file name. // A line continuation ends the current file name.
yyextra->newDependency(); yyextra->newRuleOrDependency();
} }
{NEWLINE} { {NEWLINE} {
// A newline ends the current file name and the current rule. // 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) { if (!file) {
return false; return false;
} }
newEntry(); this->newEntry();
yyscan_t scanner; yyscan_t scanner;
cmGccDepfile_yylex_init(&scanner); cmGccDepfile_yylex_init(&scanner);
cmGccDepfile_yyset_extra(this, scanner); cmGccDepfile_yyset_extra(this, scanner);
cmGccDepfile_yyrestart(file, scanner); cmGccDepfile_yyrestart(file, scanner);
cmGccDepfile_yylex(scanner); cmGccDepfile_yylex(scanner);
cmGccDepfile_yylex_destroy(scanner); cmGccDepfile_yylex_destroy(scanner);
sanitizeContent(); this->sanitizeContent();
fclose(file); fclose(file);
return true; return this->HelperState != State::Failed;
} }
void cmGccDepfileLexerHelper::newEntry() 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->HelperState = State::Rule;
this->Content.emplace_back(); this->Content.emplace_back();
newRule(); this->newRule();
} }
void cmGccDepfileLexerHelper::newRule() void cmGccDepfileLexerHelper::newRule()
@@ -56,20 +63,22 @@ void cmGccDepfileLexerHelper::newRule()
void cmGccDepfileLexerHelper::newDependency() void cmGccDepfileLexerHelper::newDependency()
{ {
// printf("NEW DEP\n"); if (this->HelperState == State::Failed) {
return;
}
this->HelperState = State::Dependency; this->HelperState = State::Dependency;
if (this->Content.back().paths.empty() || auto& entry = this->Content.back();
!this->Content.back().paths.back().empty()) { if (entry.paths.empty() || !entry.paths.back().empty()) {
this->Content.back().paths.emplace_back(); entry.paths.emplace_back();
} }
} }
void cmGccDepfileLexerHelper::newRuleOrDependency() void cmGccDepfileLexerHelper::newRuleOrDependency()
{ {
if (this->HelperState == State::Rule) { if (this->HelperState == State::Rule) {
newRule(); this->newRule();
} else { } else if (this->HelperState == State::Dependency) {
newDependency(); this->newDependency();
} }
} }
@@ -93,6 +102,8 @@ void cmGccDepfileLexerHelper::addToCurrentPath(const char* s)
} }
dst = &dep->paths.back(); dst = &dep->paths.back();
} break; } break;
case State::Failed:
return;
} }
dst->append(s); dst->append(s);
} }

View File

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

View File

@@ -5,14 +5,15 @@
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <cm/optional>
#include "cmGccDepfileLexerHelper.h" #include "cmGccDepfileLexerHelper.h"
cmGccDepfileContent cmReadGccDepfile(const char* filePath) cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath)
{ {
cmGccDepfileContent result;
cmGccDepfileLexerHelper helper; cmGccDepfileLexerHelper helper;
if (helper.readFile(filePath)) { 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. */ file Copyright.txt or https://cmake.org/licensing for details. */
#pragma once #pragma once
#include <cm/optional>
#include "cmGccDepfileReaderTypes.h" #include "cmGccDepfileReaderTypes.h"
cmGccDepfileContent cmReadGccDepfile(const char* filePath); cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath);

View File

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

View File

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