Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/flatbuffers/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,11 @@ FLATBUFFERS_CONSTEXPR char kPathSeparator = '/';
// Returns the path with the extension, if any, removed.
std::string StripExtension(const std::string& filepath);

// Escapes characters that are special to make in a filename, so the name can
// be emitted into a make dependency rule. Mirrors how gcc and clang emit
// -M/-MD depfiles.
std::string EscapeMakeDep(const std::string& filepath);

// Returns the extension, if any.
std::string GetExtension(const std::string& filepath);

Expand Down
6 changes: 3 additions & 3 deletions src/code_generators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ std::string JavaCSharpMakeRule(const bool java, const Parser& parser,
if (!make_rule.empty()) make_rule += " ";
std::string directory =
BaseGenerator::NamespaceDir(parser, path, *enum_def.defined_namespace);
make_rule += directory + enum_def.name + file_extension;
make_rule += EscapeMakeDep(directory + enum_def.name + file_extension);
}

for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end();
Expand All @@ -51,13 +51,13 @@ std::string JavaCSharpMakeRule(const bool java, const Parser& parser,
if (!make_rule.empty()) make_rule += " ";
std::string directory = BaseGenerator::NamespaceDir(
parser, path, *struct_def.defined_namespace);
make_rule += directory + struct_def.name + file_extension;
make_rule += EscapeMakeDep(directory + struct_def.name + file_extension);
}

make_rule += ": ";
auto included_files = parser.GetIncludedFilesRecursive(file_name);
for (auto it = included_files.begin(); it != included_files.end(); ++it) {
make_rule += " " + *it;
make_rule += " " + EscapeMakeDep(*it);
}
return make_rule;
}
Expand Down
5 changes: 3 additions & 2 deletions src/flatc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -957,8 +957,9 @@ std::unique_ptr<Parser> FlatCompiler::GenerateCode(const FlatCOptions& options,
const CodeGenerator::Status status = code_generator->GenerateMakeRule(
*parser, options.output_path, filename, make_rule);
if (status == CodeGenerator::Status::OK && !make_rule.empty()) {
printf("%s\n",
flatbuffers::WordWrap(make_rule, 80, " ", " \\").c_str());
// Emit the rule as a single line. Depfiles are line-oriented and
// word-wrapping would split escaped filenames.
printf("%s\n", make_rule.c_str());
} else {
Error("Cannot generate make rule for " +
code_generator->LanguageName());
Expand Down
6 changes: 3 additions & 3 deletions src/idl_gen_binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ static std::string BinaryMakeRule(const Parser& parser, const std::string& path,
if (!parser.builder_.GetSize()) return "";
std::string filebase =
flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
std::string make_rule =
BinaryFileName(parser, path, filebase) + ": " + file_name;
std::string make_rule = EscapeMakeDep(BinaryFileName(parser, path, filebase)) +
": " + EscapeMakeDep(file_name);
auto included_files =
parser.GetIncludedFilesRecursive(parser.root_struct_def_->file);
for (auto it = included_files.begin(); it != included_files.end(); ++it) {
make_rule += " " + *it;
make_rule += " " + EscapeMakeDep(*it);
}
return make_rule;
}
Expand Down
5 changes: 3 additions & 2 deletions src/idl_gen_cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4546,9 +4546,10 @@ static std::string CPPMakeRule(const Parser& parser, const std::string& path,
cpp::CppGenerator geneartor(parser, path, file_name, parser.opts);
const auto included_files = parser.GetIncludedFilesRecursive(file_name);
std::string make_rule =
geneartor.GeneratedFileName(path, filebase, parser.opts) + ": ";
EscapeMakeDep(geneartor.GeneratedFileName(path, filebase, parser.opts)) +
": ";
for (const std::string& included_file : included_files) {
make_rule += " " + included_file;
make_rule += " " + EscapeMakeDep(included_file);
}
return make_rule;
}
Expand Down
4 changes: 2 additions & 2 deletions src/idl_gen_dart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1152,11 +1152,11 @@ static std::string DartMakeRule(const Parser& parser, const std::string& path,
auto filebase =
flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
dart::DartGenerator generator(parser, path, file_name);
auto make_rule = generator.Filename("") + ": ";
auto make_rule = EscapeMakeDep(generator.Filename("")) + ": ";

auto included_files = parser.GetIncludedFilesRecursive(file_name);
for (auto it = included_files.begin(); it != included_files.end(); ++it) {
make_rule += " " + *it;
make_rule += " " + EscapeMakeDep(*it);
}
return make_rule;
}
Expand Down
5 changes: 3 additions & 2 deletions src/idl_gen_rust.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3213,11 +3213,12 @@ static std::string RustMakeRule(const Parser& parser, const std::string& path,
flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
rust::RustGenerator generator(parser, path, file_name);
std::string make_rule =
generator.GeneratedFileName(path, filebase, parser.opts) + ": ";
EscapeMakeDep(generator.GeneratedFileName(path, filebase, parser.opts)) +
": ";

auto included_files = parser.GetIncludedFilesRecursive(file_name);
for (auto it = included_files.begin(); it != included_files.end(); ++it) {
make_rule += " " + *it;
make_rule += " " + EscapeMakeDep(*it);
}
return make_rule;
}
Expand Down
6 changes: 4 additions & 2 deletions src/idl_gen_text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,11 +461,13 @@ static std::string TextMakeRule(const Parser& parser, const std::string& path,
if (!parser.builder_.GetSize() || !parser.root_struct_def_) return "";
std::string filebase =
flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
std::string make_rule = TextFileName(path, filebase) + ": " + file_name;
std::string make_rule =
EscapeMakeDep(TextFileName(path, filebase)) + ": " +
EscapeMakeDep(file_name);
auto included_files =
parser.GetIncludedFilesRecursive(parser.root_struct_def_->file);
for (auto it = included_files.begin(); it != included_files.end(); ++it) {
make_rule += " " + *it;
make_rule += " " + EscapeMakeDep(*it);
}
return make_rule;
}
Expand Down
5 changes: 3 additions & 2 deletions src/idl_gen_ts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2405,11 +2405,12 @@ static std::string TSMakeRule(const Parser& parser, const std::string& path,
flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
ts::TsGenerator generator(parser, path, file_name);
std::string make_rule =
generator.GeneratedFileName(path, filebase, parser.opts) + ": ";
EscapeMakeDep(generator.GeneratedFileName(path, filebase, parser.opts)) +
": ";

auto included_files = parser.GetIncludedFilesRecursive(file_name);
for (auto it = included_files.begin(); it != included_files.end(); ++it) {
make_rule += " " + *it;
make_rule += " " + EscapeMakeDep(*it);
}
return make_rule;
}
Expand Down
16 changes: 16 additions & 0 deletions src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,22 @@ std::string StripExtension(const std::string& filepath) {
return i != std::string::npos ? filepath.substr(0, i) : filepath;
}

std::string EscapeMakeDep(const std::string& filepath) {
std::string escaped;
escaped.reserve(filepath.size() * 2);
for (const char c : filepath) {
switch (c) {
case '\\': escaped += "\\\\"; break;
case ' ': escaped += "\\ "; break;
case '#': escaped += "\\#"; break;
case ':': escaped += "\\:"; break;
case '$': escaped += "$$"; break;
default: escaped += c; break;
}
}
return escaped;
}

std::string GetExtension(const std::string& filepath) {
size_t i = filepath.find_last_of('.');
return i != std::string::npos ? filepath.substr(i + 1) : "";
Expand Down
1 change: 1 addition & 0 deletions tests/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1799,6 +1799,7 @@ int FlatBufferTests(const std::string& tests_data_path) {
#endif

UtilConvertCase();
EscapeMakeDepTest();

FuzzTest1();
FuzzTest2();
Expand Down
19 changes: 19 additions & 0 deletions tests/util_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,24 @@ void UtilConvertCase() {
}
}

void EscapeMakeDepTest() {
// Characters special to make must be escaped, backslash first.
TEST_EQ(std::string("\\\\"), flatbuffers::EscapeMakeDep("\\"));
TEST_EQ(std::string("\\ "), flatbuffers::EscapeMakeDep(" "));
TEST_EQ(std::string("\\#"), flatbuffers::EscapeMakeDep("#"));
TEST_EQ(std::string("\\:"), flatbuffers::EscapeMakeDep(":"));
TEST_EQ(std::string("$$"), flatbuffers::EscapeMakeDep("$"));
// Combined special characters.
TEST_EQ(std::string("a\\ b\\#c\\:d$$e"),
flatbuffers::EscapeMakeDep("a b#c:d$e"));
// Trailing backslash.
TEST_EQ(std::string("name\\\\"), flatbuffers::EscapeMakeDep("name\\"));
// Empty string unchanged.
TEST_EQ(std::string(""), flatbuffers::EscapeMakeDep(""));
// Ordinary filenames are untouched.
TEST_EQ(std::string("dir/file.fbs"),
flatbuffers::EscapeMakeDep("dir/file.fbs"));
}

} // namespace tests
} // namespace flatbuffers
1 change: 1 addition & 0 deletions tests/util_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace tests {
void NumericUtilsTest();
void IsAsciiUtilsTest();
void UtilConvertCase();
void EscapeMakeDepTest();

} // namespace tests
} // namespace flatbuffers
Expand Down