Allow the flatbuffer compiler (flatc) to be built as a library.

Change-Id: I71baff427243f96be1596b01ff3405fdf39386d7
parent fd61d702
...@@ -48,6 +48,7 @@ set(FlatBuffers_Compiler_SRCS ...@@ -48,6 +48,7 @@ set(FlatBuffers_Compiler_SRCS
src/idl_gen_fbs.cpp src/idl_gen_fbs.cpp
src/idl_gen_grpc.cpp src/idl_gen_grpc.cpp
src/flatc.cpp src/flatc.cpp
src/flatc_main.cpp
grpc/src/compiler/schema_interface.h grpc/src/compiler/schema_interface.h
grpc/src/compiler/cpp_generator.h grpc/src/compiler/cpp_generator.h
grpc/src/compiler/cpp_generator.cc grpc/src/compiler/cpp_generator.cc
......
/*
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include <functional>
#include <limits>
#include <string>
#ifndef FLATC_H_
#define FLATC_H_
namespace flatbuffers {
class FlatCompiler {
public:
// Output generator for the various programming languages and formats we
// support.
struct Generator {
typedef bool (*GenerateFn)(const flatbuffers::Parser &parser,
const std::string &path,
const std::string &file_name);
typedef std::string (*MakeRuleFn)(const flatbuffers::Parser &parser,
const std::string &path,
const std::string &file_name);
GenerateFn generate;
const char *generator_opt_short;
const char *generator_opt_long;
const char *lang_name;
GenerateFn generateGRPC;
flatbuffers::IDLOptions::Language lang;
const char *generator_help;
MakeRuleFn make_rule;
};
typedef void (*WarnFn)(const FlatCompiler *flatc,
const std::string &warn,
bool show_exe_name);
typedef void (*ErrorFn)(const FlatCompiler *flatc,
const std::string &err,
bool usage, bool show_exe_name);
// Parameters required to initialize the FlatCompiler.
struct InitParams {
InitParams()
: generators(nullptr),
num_generators(0),
warn_fn(nullptr),
error_fn(nullptr) {}
const Generator* generators;
size_t num_generators;
WarnFn warn_fn;
ErrorFn error_fn;
};
explicit FlatCompiler(const InitParams& params) : params_(params) {}
int Compile(int argc, const char** argv);
std::string GetUsageString(const char* program_name) const;
private:
void ParseFile(flatbuffers::Parser &parser,
const std::string &filename,
const std::string &contents,
std::vector<const char *> &include_directories) const;
void Warn(const std::string &warn, bool show_exe_name = true) const;
void Error(const std::string &err, bool usage = true,
bool show_exe_name = true) const;
InitParams params_;
};
} // namespace flatbuffers
#endif // FLATC_H_
...@@ -14,105 +14,50 @@ ...@@ -14,105 +14,50 @@
* limitations under the License. * limitations under the License.
*/ */
#include "flatbuffers/flatbuffers.h" #include "flatbuffers/flatc.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include <limits>
#define FLATC_VERSION "1.5.0 (" __DATE__ ")" #define FLATC_VERSION "1.5.0 (" __DATE__ ")"
static void Error(const std::string &err, bool usage = false, namespace flatbuffers {
bool show_exe_name = true);
// This struct allows us to create a table of all possible output generators void FlatCompiler::ParseFile(
// for the various programming languages and formats we support. flatbuffers::Parser &parser,
struct Generator { const std::string &filename,
bool (*generate)(const flatbuffers::Parser &parser, const std::string &contents,
const std::string &path, std::vector<const char *> &include_directories) const {
const std::string &file_name); auto local_include_directory = flatbuffers::StripFileName(filename);
const char *generator_opt_short; include_directories.push_back(local_include_directory.c_str());
const char *generator_opt_long; include_directories.push_back(nullptr);
const char *lang_name; if (!parser.Parse(contents.c_str(), &include_directories[0],
bool (*generateGRPC)(const flatbuffers::Parser &parser, filename.c_str()))
const std::string &path, Error(parser.error_, false, false);
const std::string &file_name); include_directories.pop_back();
flatbuffers::IDLOptions::Language lang; include_directories.pop_back();
const char *generator_help; }
std::string (*make_rule)(const flatbuffers::Parser &parser, void FlatCompiler::Warn(const std::string &warn, bool show_exe_name) const {
const std::string &path, params_.warn_fn(this, warn, show_exe_name);
const std::string &file_name); }
};
const Generator generators[] = { void FlatCompiler::Error(const std::string &err, bool usage,
{ flatbuffers::GenerateBinary, "-b", "--binary", "binary", bool show_exe_name) const {
nullptr, params_.error_fn(this, err, usage, show_exe_name);
flatbuffers::IDLOptions::kBinary, }
"Generate wire format binaries for any data definitions",
flatbuffers::BinaryMakeRule },
{ flatbuffers::GenerateTextFile, "-t", "--json", "text",
nullptr,
flatbuffers::IDLOptions::kJson,
"Generate text output for any data definitions",
flatbuffers::TextMakeRule },
{ flatbuffers::GenerateCPP, "-c", "--cpp", "C++",
flatbuffers::GenerateCppGRPC,
flatbuffers::IDLOptions::kCpp,
"Generate C++ headers for tables/structs",
flatbuffers::CPPMakeRule },
{ flatbuffers::GenerateGo, "-g", "--go", "Go",
flatbuffers::GenerateGoGRPC,
flatbuffers::IDLOptions::kGo,
"Generate Go files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateGeneral, "-j", "--java", "Java",
nullptr,
flatbuffers::IDLOptions::kJava,
"Generate Java classes for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateJS, "-s", "--js", "JavaScript",
nullptr,
flatbuffers::IDLOptions::kJs,
"Generate JavaScript code for tables/structs",
flatbuffers::JSMakeRule },
{ flatbuffers::GenerateGeneral, "-n", "--csharp", "C#",
nullptr,
flatbuffers::IDLOptions::kCSharp,
"Generate C# classes for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePython, "-p", "--python", "Python",
nullptr,
flatbuffers::IDLOptions::kPython,
"Generate Python files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePhp, nullptr, "--php", "PHP",
nullptr,
flatbuffers::IDLOptions::kPhp,
"Generate PHP files for tables/structs",
flatbuffers::GeneralMakeRule },
};
const char *g_program_name = nullptr; std::string FlatCompiler::GetUsageString(const char* program_name) const {
flatbuffers::Parser *g_parser = nullptr; std::stringstream ss;
ss << "Usageaa: " << program_name << " [OPTION]... FILE... [-- FILE...]\n";
for (size_t i = 0; i < params_.num_generators; ++i) {
const Generator& g = params_.generators[i];
static void Warn(const std::string &warn, bool show_exe_name = true) { std::stringstream full_name;
if (show_exe_name) printf("%s: ", g_program_name); full_name << std::setw(12) << std::left << g.generator_opt_long;
printf("warning: %s\n", warn.c_str()); const char *name = g.generator_opt_short ? g.generator_opt_short : " ";
} const char *help = g.generator_help;
static void Error(const std::string &err, bool usage, bool show_exe_name) { ss << " " << full_name.str() << " " << name << " " << help << ".\n";
if (show_exe_name) printf("%s: ", g_program_name); }
printf("error: %s\n", err.c_str()); ss <<
if (usage) {
printf("usage: %s [OPTION]... FILE... [-- FILE...]\n", g_program_name);
for (size_t i = 0; i < sizeof(generators) / sizeof(generators[0]); ++i)
printf(" %-12s %s %s.\n",
generators[i].generator_opt_long,
generators[i].generator_opt_short
? generators[i].generator_opt_short
: " ",
generators[i].generator_help);
printf(
" -o PATH Prefix PATH to all generated files.\n" " -o PATH Prefix PATH to all generated files.\n"
" -I PATH Search for includes in the specified path.\n" " -I PATH Search for includes in the specified path.\n"
" -M Print make rules for generated files.\n" " -M Print make rules for generated files.\n"
...@@ -154,32 +99,18 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) { ...@@ -154,32 +99,18 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) {
"FILEs after the -- must be binary flatbuffer format files.\n" "FILEs after the -- must be binary flatbuffer format files.\n"
"Output files are named using the base file name of the input,\n" "Output files are named using the base file name of the input,\n"
"and written to the current directory or the path given by -o.\n" "and written to the current directory or the path given by -o.\n"
"example: %s -c -b schema1.fbs schema2.fbs data.json\n", "example: " << program_name << " -c -b schema1.fbs schema2.fbs data.json\n";
g_program_name); return ss.str();
}
if (g_parser) delete g_parser;
exit(1);
} }
static void ParseFile(flatbuffers::Parser &parser, const std::string &filename, int FlatCompiler::Compile(int argc, const char** argv) {
const std::string &contents, if (params_.generators == nullptr || params_.num_generators == 0) {
std::vector<const char *> &include_directories) { return 0;
auto local_include_directory = flatbuffers::StripFileName(filename); }
include_directories.push_back(local_include_directory.c_str());
include_directories.push_back(nullptr);
if (!parser.Parse(contents.c_str(), &include_directories[0],
filename.c_str()))
Error(parser.error_, false, false);
include_directories.pop_back();
include_directories.pop_back();
}
int main(int argc, const char *argv[]) {
g_program_name = argv[0];
flatbuffers::IDLOptions opts; flatbuffers::IDLOptions opts;
std::string output_path; std::string output_path;
const size_t num_generators = sizeof(generators) / sizeof(generators[0]);
bool generator_enabled[num_generators] = { false };
bool any_generator = false; bool any_generator = false;
bool print_make_rules = false; bool print_make_rules = false;
bool raw_binary = false; bool raw_binary = false;
...@@ -188,9 +119,11 @@ int main(int argc, const char *argv[]) { ...@@ -188,9 +119,11 @@ int main(int argc, const char *argv[]) {
std::vector<std::string> filenames; std::vector<std::string> filenames;
std::vector<const char *> include_directories; std::vector<const char *> include_directories;
std::vector<const char *> conform_include_directories; std::vector<const char *> conform_include_directories;
std::vector<bool> generator_enabled(params_.num_generators, false);
size_t binary_files_from = std::numeric_limits<size_t>::max(); size_t binary_files_from = std::numeric_limits<size_t>::max();
std::string conform_to_schema; std::string conform_to_schema;
for (int argi = 1; argi < argc; argi++) {
for (int argi = 0; argi < argc; argi++) {
std::string arg = argv[argi]; std::string arg = argv[argi];
if (arg[0] == '-') { if (arg[0] == '-') {
if (filenames.size() && arg[1] != '-') if (filenames.size() && arg[1] != '-')
...@@ -261,13 +194,13 @@ int main(int argc, const char *argv[]) { ...@@ -261,13 +194,13 @@ int main(int argc, const char *argv[]) {
} else if(arg == "--grpc") { } else if(arg == "--grpc") {
grpc_enabled = true; grpc_enabled = true;
} else { } else {
for (size_t i = 0; i < num_generators; ++i) { for (size_t i = 0; i < params_.num_generators; ++i) {
if (arg == generators[i].generator_opt_long || if (arg == params_.generators[i].generator_opt_long ||
(generators[i].generator_opt_short && (params_.generators[i].generator_opt_short &&
arg == generators[i].generator_opt_short)) { arg == params_.generators[i].generator_opt_short)) {
generator_enabled[i] = true; generator_enabled[i] = true;
any_generator = true; any_generator = true;
opts.lang_to_generate |= generators[i].lang; opts.lang_to_generate |= params_.generators[i].lang;
goto found; goto found;
} }
} }
...@@ -297,8 +230,8 @@ int main(int argc, const char *argv[]) { ...@@ -297,8 +230,8 @@ int main(int argc, const char *argv[]) {
conform_include_directories); conform_include_directories);
} }
// Now process the files: std::unique_ptr<flatbuffers::Parser> parser(new flatbuffers::Parser(opts));
g_parser = new flatbuffers::Parser(opts);
for (auto file_it = filenames.begin(); for (auto file_it = filenames.begin();
file_it != filenames.end(); file_it != filenames.end();
++file_it) { ++file_it) {
...@@ -309,8 +242,8 @@ int main(int argc, const char *argv[]) { ...@@ -309,8 +242,8 @@ int main(int argc, const char *argv[]) {
bool is_binary = static_cast<size_t>(file_it - filenames.begin()) >= bool is_binary = static_cast<size_t>(file_it - filenames.begin()) >=
binary_files_from; binary_files_from;
if (is_binary) { if (is_binary) {
g_parser->builder_.Clear(); parser->builder_.Clear();
g_parser->builder_.PushFlatBuffer( parser->builder_.PushFlatBuffer(
reinterpret_cast<const uint8_t *>(contents.c_str()), reinterpret_cast<const uint8_t *>(contents.c_str()),
contents.length()); contents.length());
if (!raw_binary) { if (!raw_binary) {
...@@ -319,17 +252,17 @@ int main(int argc, const char *argv[]) { ...@@ -319,17 +252,17 @@ int main(int argc, const char *argv[]) {
// does not contain a file identifier. // does not contain a file identifier.
// We'd expect that typically any binary used as a file would have // We'd expect that typically any binary used as a file would have
// such an identifier, so by default we require them to match. // such an identifier, so by default we require them to match.
if (!g_parser->file_identifier_.length()) { if (!parser->file_identifier_.length()) {
Error("current schema has no file_identifier: cannot test if \"" + Error("current schema has no file_identifier: cannot test if \"" +
*file_it + *file_it +
"\" matches the schema, use --raw-binary to read this file" "\" matches the schema, use --raw-binary to read this file"
" anyway."); " anyway.");
} else if (!flatbuffers::BufferHasIdentifier(contents.c_str(), } else if (!flatbuffers::BufferHasIdentifier(contents.c_str(),
g_parser->file_identifier_.c_str())) { parser->file_identifier_.c_str())) {
Error("binary \"" + Error("binary \"" +
*file_it + *file_it +
"\" does not have expected file_identifier \"" + "\" does not have expected file_identifier \"" +
g_parser->file_identifier_ + parser->file_identifier_ +
"\", use --raw-binary to read this file anyway."); "\", use --raw-binary to read this file anyway.");
} }
} }
...@@ -343,63 +276,62 @@ int main(int argc, const char *argv[]) { ...@@ -343,63 +276,62 @@ int main(int argc, const char *argv[]) {
// If we're processing multiple schemas, make sure to start each // If we're processing multiple schemas, make sure to start each
// one from scratch. If it depends on previous schemas it must do // one from scratch. If it depends on previous schemas it must do
// so explicitly using an include. // so explicitly using an include.
delete g_parser; parser.reset(new flatbuffers::Parser(opts));
g_parser = new flatbuffers::Parser(opts);
} }
ParseFile(*g_parser, *file_it, contents, include_directories); ParseFile(*parser.get(), *file_it, contents, include_directories);
if (is_schema && !conform_to_schema.empty()) { if (is_schema && !conform_to_schema.empty()) {
auto err = g_parser->ConformTo(conform_parser); auto err = parser->ConformTo(conform_parser);
if (!err.empty()) Error("schemas don\'t conform: " + err); if (!err.empty()) Error("schemas don\'t conform: " + err);
} }
if (schema_binary) { if (schema_binary) {
g_parser->Serialize(); parser->Serialize();
g_parser->file_extension_ = reflection::SchemaExtension(); parser->file_extension_ = reflection::SchemaExtension();
} }
} }
std::string filebase = flatbuffers::StripPath( std::string filebase = flatbuffers::StripPath(
flatbuffers::StripExtension(*file_it)); flatbuffers::StripExtension(*file_it));
for (size_t i = 0; i < num_generators; ++i) { for (size_t i = 0; i < params_.num_generators; ++i) {
g_parser->opts.lang = generators[i].lang; parser->opts.lang = params_.generators[i].lang;
if (generator_enabled[i]) { if (generator_enabled[i]) {
if (!print_make_rules) { if (!print_make_rules) {
flatbuffers::EnsureDirExists(output_path); flatbuffers::EnsureDirExists(output_path);
if (!generators[i].generate(*g_parser, output_path, filebase)) { if (!params_.generators[i].generate(*parser.get(), output_path, filebase)) {
Error(std::string("Unable to generate ") + Error(std::string("Unable to generate ") +
generators[i].lang_name + params_.generators[i].lang_name +
" for " + " for " +
filebase); filebase);
} }
} else { } else {
std::string make_rule = generators[i].make_rule( std::string make_rule = params_.generators[i].make_rule(
*g_parser, output_path, *file_it); *parser.get(), output_path, *file_it);
if (!make_rule.empty()) if (!make_rule.empty())
printf("%s\n", flatbuffers::WordWrap( printf("%s\n", flatbuffers::WordWrap(
make_rule, 80, " ", " \\").c_str()); make_rule, 80, " ", " \\").c_str());
} }
if (grpc_enabled) { if (grpc_enabled) {
if (generators[i].generateGRPC != nullptr) { if (params_.generators[i].generateGRPC != nullptr) {
if (!generators[i].generateGRPC(*g_parser, output_path, if (!params_.generators[i].generateGRPC(*parser.get(), output_path,
filebase)) { filebase)) {
Error(std::string("Unable to generate GRPC interface for") + Error(std::string("Unable to generate GRPC interface for") +
generators[i].lang_name); params_.generators[i].lang_name);
} }
} else { } else {
Warn(std::string("GRPC interface generator not implemented for ") Warn(std::string("GRPC interface generator not implemented for ")
+ generators[i].lang_name); + params_.generators[i].lang_name);
} }
} }
} }
} }
if (opts.proto_mode) GenerateFBS(*g_parser, output_path, filebase); if (opts.proto_mode) GenerateFBS(*parser.get(), output_path, filebase);
// We do not want to generate code for the definitions in this file // We do not want to generate code for the definitions in this file
// in any files coming up next. // in any files coming up next.
g_parser->MarkGenerated(); parser->MarkGenerated();
} }
delete g_parser;
return 0; return 0;
} }
} // namespace flatbuffers
/*
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "flatbuffers/flatc.h"
static const char *g_program_name = nullptr;
static void Warn(const flatbuffers::FlatCompiler* flatc,
const std::string &warn,
bool show_exe_name) {
if (show_exe_name) {
printf("%s: ", g_program_name);
}
printf("warning: %s\n", warn.c_str());
}
static void Error(const flatbuffers::FlatCompiler* flatc,
const std::string &err,
bool usage,
bool show_exe_name) {
if (show_exe_name) {
printf("%s: ", g_program_name);
}
printf("error: %s\n", err.c_str());
if (usage) {
printf("%s", flatc->GetUsageString(g_program_name).c_str());
}
exit(1);
}
int main(int argc, const char *argv[]) {
g_program_name = argv[0];
const flatbuffers::FlatCompiler::Generator generators[] = {
{ flatbuffers::GenerateBinary, "-b", "--binary", "binary",
nullptr,
flatbuffers::IDLOptions::kBinary,
"Generate wire format binaries for any data definitions",
flatbuffers::BinaryMakeRule },
{ flatbuffers::GenerateTextFile, "-t", "--json", "text",
nullptr,
flatbuffers::IDLOptions::kJson,
"Generate text output for any data definitions",
flatbuffers::TextMakeRule },
{ flatbuffers::GenerateCPP, "-c", "--cpp", "C++",
flatbuffers::GenerateCppGRPC,
flatbuffers::IDLOptions::kCpp,
"Generate C++ headers for tables/structs",
flatbuffers::CPPMakeRule },
{ flatbuffers::GenerateGo, "-g", "--go", "Go",
flatbuffers::GenerateGoGRPC,
flatbuffers::IDLOptions::kGo,
"Generate Go files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateGeneral, "-j", "--java", "Java",
nullptr,
flatbuffers::IDLOptions::kJava,
"Generate Java classes for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateJS, "-s", "--js", "JavaScript",
nullptr,
flatbuffers::IDLOptions::kJs,
"Generate JavaScript code for tables/structs",
flatbuffers::JSMakeRule },
{ flatbuffers::GenerateGeneral, "-n", "--csharp", "C#",
nullptr,
flatbuffers::IDLOptions::kCSharp,
"Generate C# classes for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePython, "-p", "--python", "Python",
nullptr,
flatbuffers::IDLOptions::kPython,
"Generate Python files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePhp, nullptr, "--php", "PHP",
nullptr,
flatbuffers::IDLOptions::kPhp,
"Generate PHP files for tables/structs",
flatbuffers::GeneralMakeRule },
};
flatbuffers::FlatCompiler::InitParams params;
params.generators = generators;
params.num_generators = sizeof(generators) / sizeof(generators[0]);
params.warn_fn = Warn;
params.error_fn = Error;
flatbuffers::FlatCompiler flatc(params);
return flatc.Compile(argc - 1, argv + 1);
}
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