Add absolute file names option to BFBS (#8055)

* Add absolute file names option (#1)

* Use ternary style for if

---------

Co-authored-by: Derek Bailey <derekbailey@google.com>
diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h
index dd13918..a08db9b 100644
--- a/include/flatbuffers/idl.h
+++ b/include/flatbuffers/idl.h
@@ -676,6 +676,7 @@
   bool binary_schema_comments;
   bool binary_schema_builtins;
   bool binary_schema_gen_embed;
+  bool binary_schema_absolute_paths;
   std::string go_import;
   std::string go_namespace;
   std::string go_module_name;
@@ -796,6 +797,7 @@
         binary_schema_comments(false),
         binary_schema_builtins(false),
         binary_schema_gen_embed(false),
+        binary_schema_absolute_paths(false),
         protobuf_ascii_alike(false),
         size_prefixed(false),
         force_defaults(false),
diff --git a/include/flatbuffers/util.h b/include/flatbuffers/util.h
index 1ccf351..82b37fb 100644
--- a/include/flatbuffers/util.h
+++ b/include/flatbuffers/util.h
@@ -479,6 +479,11 @@
 // creating dirs for any parts of the path that don't exist yet.
 void EnsureDirExists(const std::string &filepath);
 
+// Obtains the relative or absolute path.
+std::string FilePath(const std::string &project,
+                     const std::string &filePath,
+                     bool absolute);
+
 // Obtains the absolute path from any other path.
 // Returns the input path if the absolute path couldn't be resolved.
 std::string AbsolutePath(const std::string &filepath);
diff --git a/src/flatc.cpp b/src/flatc.cpp
index d493c5e..4bc88eb 100644
--- a/src/flatc.cpp
+++ b/src/flatc.cpp
@@ -187,6 +187,7 @@
     "relative to. The 'root' is denoted with  `//`. E.g. if PATH=/a/b/c "
     "then /a/d/e.fbs will be serialized as //../d/e.fbs. (PATH defaults to the "
     "directory of the first provided schema file." },
+  { "", "bfbs-absolute-paths", "", "Uses absolute paths instead of relative paths in the BFBS output." },
   { "", "bfbs-comments", "", "Add doc comments to the binary schema files." },
   { "", "bfbs-builtins", "",
     "Add builtin attributes to the binary schema files." },
@@ -596,6 +597,8 @@
         opts.binary_schema_builtins = true;
       } else if (arg == "--bfbs-gen-embed") {
         opts.binary_schema_gen_embed = true;
+      } else if (arg == "--bfbs-absolute-paths") {
+        opts.binary_schema_absolute_paths = true;
       } else if (arg == "--reflect-types") {
         opts.mini_reflect = IDLOptions::kTypes;
       } else if (arg == "--reflect-names") {
diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp
index 5b42b35..d01e18e 100644
--- a/src/idl_parser.cpp
+++ b/src/idl_parser.cpp
@@ -2483,7 +2483,7 @@
   ECHECK(StartEnum(enum_name, is_union, &enum_def));
   if (filename != nullptr && !opts.project_root.empty()) {
     enum_def->declaration_file =
-        &GetPooledString(RelativeToRootPath(opts.project_root, filename));
+        &GetPooledString(FilePath(opts.project_root, filename, opts.binary_schema_absolute_paths));
   }
   enum_def->doc_comment = enum_comment;
   if (!opts.proto_mode) {
@@ -2762,7 +2762,7 @@
   struct_def->fixed = fixed;
   if (filename && !opts.project_root.empty()) {
     struct_def->declaration_file =
-        &GetPooledString(RelativeToRootPath(opts.project_root, filename));
+        &GetPooledString(FilePath(opts.project_root, filename, opts.binary_schema_absolute_paths));
   }
   ECHECK(ParseMetaData(&struct_def->attributes));
   struct_def->sortbysize =
@@ -2856,7 +2856,7 @@
   service_def.defined_namespace = current_namespace_;
   if (filename != nullptr && !opts.project_root.empty()) {
     service_def.declaration_file =
-        &GetPooledString(RelativeToRootPath(opts.project_root, filename));
+        &GetPooledString(FilePath(opts.project_root, filename, opts.binary_schema_absolute_paths));
   }
   if (services_.Add(current_namespace_->GetFullyQualifiedName(service_name),
                     &service_def))
@@ -3937,11 +3937,12 @@
     std::vector<Offset<flatbuffers::String>> included_files;
     for (auto f = files_included_per_file_.begin();
          f != files_included_per_file_.end(); f++) {
-      const auto filename__ = builder_.CreateSharedString(
-          RelativeToRootPath(opts.project_root, f->first));
+
+      const auto filename__ = builder_.CreateSharedString(FilePath(
+          opts.project_root, f->first, opts.binary_schema_absolute_paths));
       for (auto i = f->second.begin(); i != f->second.end(); i++) {
         included_files.push_back(builder_.CreateSharedString(
-            RelativeToRootPath(opts.project_root, i->filename)));
+            FilePath(opts.project_root, i->filename, opts.binary_schema_absolute_paths)));
       }
       const auto included_files__ = builder_.CreateVector(included_files);
       included_files.clear();
diff --git a/src/util.cpp b/src/util.cpp
index b201246..2d45ee7 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -336,6 +336,10 @@
   // clang-format on
 }
 
+std::string FilePath(const std::string& project, const std::string& filePath, bool absolute) {
+    return (absolute) ? AbsolutePath(filePath) : RelativeToRootPath(project, filePath);
+}
+
 std::string AbsolutePath(const std::string &filepath) {
   // clang-format off