Merge "Fix clean build of UI"
diff --git a/buildtools/.gitignore b/buildtools/.gitignore
index fedb4e2..272cb1b 100644
--- a/buildtools/.gitignore
+++ b/buildtools/.gitignore
@@ -15,3 +15,4 @@
 ndk/
 nodejs/
 protobuf/
+sqlite/
diff --git a/buildtools/BUILD.gn b/buildtools/BUILD.gn
index ee356d5..e829a1b 100644
--- a/buildtools/BUILD.gn
+++ b/buildtools/BUILD.gn
@@ -558,3 +558,42 @@
     public_configs = [ ":libbacktrace_config" ]
   }
 }
+
+config("sqlite_config") {
+  include_dirs = [ "sqlite" ]
+  cflags = [
+    "-DSQLITE_THREADSAFE=0",
+    "-DQLITE_DEFAULT_MEMSTATUS=0",
+    "-DSQLITE_LIKE_DOESNT_MATCH_BLOBS",
+    "-DSQLITE_OMIT_DECLTYPE",
+    "-DSQLITE_OMIT_DEPRECATED",
+    "-DSQLITE_OMIT_SHARED_CACHE",
+    "-DHAVE_USLEEP",
+    "-DHAVE_UTIME",
+    "-DSQLITE_BYTEORDER=1234",
+    "-DSQLITE_DEFAULT_AUTOVACUUM=0",
+    "-DSQLITE_DEFAULT_MMAP_SIZE=0",
+    "-DSQLITE_CORE",
+  ]
+}
+
+source_set("sqlite") {
+  sources = [
+    "sqlite/sqlite3.c",
+    "sqlite/sqlite3.h",
+    "sqlite/sqlite3ext.h",
+  ]
+  configs -= [ "//gn/standalone:extra_warnings" ]
+  public_configs = [ ":sqlite_config" ]
+}
+
+source_set("sqlite_shell") {
+  testonly = true
+  sources = [
+    "sqlite/shell.c",
+  ]
+  configs -= [ "//gn/standalone:extra_warnings" ]
+  deps = [
+    ":sqlite",
+  ]
+}
diff --git a/protos/perfetto/trace/ftrace/BUILD.gn b/protos/perfetto/trace/ftrace/BUILD.gn
index 2ca2a31..5100643 100644
--- a/protos/perfetto/trace/ftrace/BUILD.gn
+++ b/protos/perfetto/trace/ftrace/BUILD.gn
@@ -18,6 +18,8 @@
 
 proto_library("lite") {
   generate_python = false
+  generate_descriptor =
+      "$perfetto_root_path/protos/perfetto/trace/ftrace.descriptor"
   sources = ftrace_proto_names
   proto_in_dir = "$perfetto_root_path/protos"
   proto_out_dir = "$perfetto_root_path/protos"
diff --git a/tools/ftrace_proto_gen/ftrace_proto_gen.cc b/tools/ftrace_proto_gen/ftrace_proto_gen.cc
index 82a71d4..8874e64 100644
--- a/tools/ftrace_proto_gen/ftrace_proto_gen.cc
+++ b/tools/ftrace_proto_gen/ftrace_proto_gen.cc
@@ -20,6 +20,7 @@
 #include <fstream>
 #include <regex>
 
+#include "perfetto/base/file_utils.h"
 #include "perfetto/base/logging.h"
 #include "perfetto/base/string_splitter.h"
 
@@ -37,6 +38,19 @@
 
 }  // namespace
 
+VerifyStream::VerifyStream(std::string filename)
+    : filename_(std::move(filename)) {
+  PERFETTO_CHECK(base::ReadFile(filename_, &expected_));
+}
+
+VerifyStream::~VerifyStream() {
+  // TODO(fmayer): Teach this clang-format.
+  if (expected_ != str()) {
+    PERFETTO_FATAL("%s is out of date. Please run tools/run_ftrace_proto_gen.",
+                   filename_.c_str());
+  }
+}
+
 FtraceEventName::FtraceEventName(const std::string& full_name) {
   if (full_name == "removed") {
     valid_ = false;
@@ -283,27 +297,26 @@
   return true;
 }
 
-void GenerateFtraceEventProto(
-    const std::vector<FtraceEventName>& raw_whitelist) {
-  std::string output_path = "protos/perfetto/trace/ftrace/ftrace_event.proto";
-  std::ofstream fout(output_path.c_str(), std::ios::out);
-  fout << "// Autogenerated by:\n";
-  fout << std::string("// ") + __FILE__ + "\n";
-  fout << "// Do not edit.\n\n";
-  fout << R"(syntax = "proto2";)"
-       << "\n";
-  fout << "option optimize_for = LITE_RUNTIME;\n\n";
+void GenerateFtraceEventProto(const std::vector<FtraceEventName>& raw_whitelist,
+                              std::ostream* fout) {
+  *fout << "// Autogenerated by:\n";
+  *fout << std::string("// ") + __FILE__ + "\n";
+  *fout << "// Do not edit.\n\n";
+  *fout << R"(syntax = "proto2";)"
+        << "\n";
+  *fout << "option optimize_for = LITE_RUNTIME;\n\n";
   for (const FtraceEventName& event : raw_whitelist) {
     if (!event.valid())
       continue;
 
-    fout << R"(import "perfetto/trace/ftrace/)" << event.name() << R"(.proto";)"
-         << "\n";
+    *fout << R"(import "perfetto/trace/ftrace/)" << event.name()
+          << R"(.proto";)"
+          << "\n";
   }
 
-  fout << "\n";
-  fout << "package perfetto.protos;\n\n";
-  fout << R"(message FtraceEvent {
+  *fout << "\n";
+  *fout << "package perfetto.protos;\n\n";
+  *fout << R"(message FtraceEvent {
   // Nanoseconds since an epoch.
   // Epoch is configurable by writing into trace_clock.
   // By default this timestamp is CPU local.
@@ -318,17 +331,17 @@
   int i = 3;
   for (const FtraceEventName& event : raw_whitelist) {
     if (!event.valid()) {
-      fout << "    // removed field with id " << i << ";\n";
+      *fout << "    // removed field with id " << i << ";\n";
       ++i;
       continue;
     }
 
-    fout << "    " << ToCamelCase(event.name()) << "FtraceEvent "
-         << event.name() << " = " << i << ";\n";
+    *fout << "    " << ToCamelCase(event.name()) << "FtraceEvent "
+          << event.name() << " = " << i << ";\n";
     ++i;
   }
-  fout << "  }\n";
-  fout << "}\n";
+  *fout << "  }\n";
+  *fout << "}\n";
 }
 
 // Generates section of event_info.cc for a single event.
@@ -349,14 +362,8 @@
 }
 
 // This will generate the event_info.cc file for the whitelisted protos.
-void GenerateEventInfo(const std::vector<std::string>& events_info) {
-  std::string output_path = "src/ftrace_reader/event_info.cc";
-  std::ofstream fout(output_path.c_str(), std::ios::out);
-  if (!fout) {
-    fprintf(stderr, "Failed to open %s\n", output_path.c_str());
-    return;
-  }
-
+void GenerateEventInfo(const std::vector<std::string>& events_info,
+                       std::ostream* fout) {
   std::string s = "// Autogenerated by:\n";
   s += std::string("// ") + __FILE__ + "\n";
   s += "// Do not edit.\n";
@@ -385,8 +392,7 @@
 }  // namespace perfetto
 )";
 
-  fout << s;
-  fout.close();
+  *fout << s;
 }
 
 Proto::Proto(std::string evt_name, const google::protobuf::Descriptor& desc)
diff --git a/tools/ftrace_proto_gen/ftrace_proto_gen.h b/tools/ftrace_proto_gen/ftrace_proto_gen.h
index deeed67..19b5515 100644
--- a/tools/ftrace_proto_gen/ftrace_proto_gen.h
+++ b/tools/ftrace_proto_gen/ftrace_proto_gen.h
@@ -20,6 +20,7 @@
 #include <google/protobuf/descriptor.h>
 #include <map>
 #include <set>
+#include <sstream>
 #include <string>
 #include <vector>
 
@@ -27,6 +28,16 @@
 
 namespace perfetto {
 
+class VerifyStream : public std::ostringstream {
+ public:
+  VerifyStream(std::string filename);
+  virtual ~VerifyStream();
+
+ private:
+  std::string filename_;
+  std::string expected_;
+};
+
 class FtraceEventName {
  public:
   explicit FtraceEventName(const std::string& full_name);
@@ -88,12 +99,13 @@
 ProtoType InferProtoType(const FtraceEvent::Field& field);
 
 std::vector<FtraceEventName> ReadWhitelist(const std::string& filename);
-void GenerateFtraceEventProto(
-    const std::vector<FtraceEventName>& raw_whitelist);
+void GenerateFtraceEventProto(const std::vector<FtraceEventName>& raw_whitelist,
+                              std::ostream* fout);
 std::string SingleEventInfo(perfetto::Proto proto,
                             const std::string& group,
                             const uint32_t proto_field_id);
-void GenerateEventInfo(const std::vector<std::string>& events_info);
+void GenerateEventInfo(const std::vector<std::string>& events_info,
+                       std::ostream* fout);
 
 }  // namespace perfetto
 
diff --git a/tools/ftrace_proto_gen/main.cc b/tools/ftrace_proto_gen/main.cc
index 486ee0a..9d572cb 100644
--- a/tools/ftrace_proto_gen/main.cc
+++ b/tools/ftrace_proto_gen/main.cc
@@ -30,12 +30,23 @@
 #include "perfetto/trace/ftrace/ftrace_event.pbzero.h"
 #include "tools/ftrace_proto_gen/ftrace_proto_gen.h"
 
+std::unique_ptr<std::ostream> MakeOFStream(const std::string& filename);
+std::unique_ptr<std::ostream> MakeOFStream(const std::string& filename) {
+  return std::unique_ptr<std::ostream>(new std::ofstream(filename));
+}
+
+std::unique_ptr<std::ostream> MakeVerifyStream(const std::string& filename);
+std::unique_ptr<std::ostream> MakeVerifyStream(const std::string& filename) {
+  return std::unique_ptr<std::ostream>(new perfetto::VerifyStream(filename));
+}
+
 int main(int argc, char** argv) {
   static struct option long_options[] = {
       {"whitelist_path", required_argument, nullptr, 'w'},
       {"output_dir", required_argument, nullptr, 'o'},
       {"proto_descriptor", required_argument, nullptr, 'd'},
       {"update_build_files", no_argument, nullptr, 'b'},
+      {"check_only", no_argument, nullptr, 'c'},
   };
 
   int option_index;
@@ -46,6 +57,9 @@
   std::string proto_descriptor;
   bool update_build_files = false;
 
+  std::unique_ptr<std::ostream> (*ostream_factory)(const std::string&) =
+      &MakeOFStream;
+
   while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
     switch (c) {
       case 'w':
@@ -60,6 +74,8 @@
       case 'b':
         update_build_files = true;
         break;
+      case 'c':
+        ostream_factory = &MakeVerifyStream;
     }
   }
 
@@ -70,7 +86,7 @@
   if (optind >= argc) {
     fprintf(stderr,
             "Usage: ./%s -w whitelist_dir -o output_dir -d proto_descriptor "
-            "input_dir...\n",
+            "[--check_only] input_dir...\n",
             argv[0]);
     return 1;
   }
@@ -95,14 +111,10 @@
     }
   }
 
-  perfetto::GenerateFtraceEventProto(whitelist);
-
-  std::string ftrace;
-  if (!perfetto::base::ReadFile(
-          "protos/perfetto/trace/ftrace/ftrace_event.proto", &ftrace)) {
-    fprintf(stderr, "Failed to open %s\n",
-            "protos/perfetto/trace/ftrace/ftrace_event.proto");
-    return 1;
+  {
+    std::unique_ptr<std::ostream> out =
+        ostream_factory(output_dir + "/ftrace_event.proto");
+    perfetto::GenerateFtraceEventProto(whitelist, out.get());
   }
 
   std::set<std::string> new_events;
@@ -179,22 +191,28 @@
     events_info.push_back(
         perfetto::SingleEventInfo(proto, event.group(), proto_field_id));
 
-    std::ofstream fout(output_path.c_str(), std::ios::out);
+    std::unique_ptr<std::ostream> fout = ostream_factory(output_path);
     if (!fout) {
       fprintf(stderr, "Failed to open %s\n", output_path.c_str());
       return 1;
     }
 
-    fout << proto.ToString();
-    fout.close();
+    *fout << proto.ToString();
+    PERFETTO_CHECK(!fout->fail());
   }
 
-  perfetto::GenerateEventInfo(events_info);
+  {
+    std::unique_ptr<std::ostream> out =
+        ostream_factory("src/ftrace_reader/event_info.cc");
+    perfetto::GenerateEventInfo(events_info, out.get());
+    PERFETTO_CHECK(!out->fail());
+  }
 
   if (update_build_files) {
-    std::ofstream f(output_dir + "/all_protos.gni");
+    std::unique_ptr<std::ostream> f =
+        ostream_factory(output_dir + "/all_protos.gni");
 
-    f << R"(# Copyright (C) 2018 The Android Open Source Project
+    *f << R"(# Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -219,10 +237,9 @@
     for (const perfetto::FtraceEventName& event : whitelist) {
       if (!event.valid())
         continue;
-      f << "  \"" << event.name() << ".proto\",\n";
+      *f << "  \"" << event.name() << ".proto\",\n";
     }
-    f << "]\n";
-    f.close();
-    PERFETTO_CHECK(!f.fail());
+    *f << "]\n";
+    PERFETTO_CHECK(!f->fail());
   }
 }
diff --git a/tools/install-build-deps b/tools/install-build-deps
index a665a42..8157361 100755
--- a/tools/install-build-deps
+++ b/tools/install-build-deps
@@ -212,6 +212,11 @@
    'fdc26481fe70001ea00e83b99d0df906c9b2a45f',
    'linux2'
   ),
+  ('buildtools/sqlite.zip',
+   'https://storage.googleapis.com/perfetto/sqlite-amalgamation-3230100.zip',
+   '98729f2c2d57d166e3d6d9862744c1d66388e286',
+   'all'
+  ),
 ]
 
 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
diff --git a/tools/run_ftrace_proto_gen b/tools/run_ftrace_proto_gen
new file mode 100755
index 0000000..4f0ed80
--- /dev/null
+++ b/tools/run_ftrace_proto_gen
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+BUILDDIR="$DIR/../out/ftrace_proto_gen_build"
+
+"$DIR/gn" gen "$BUILDDIR" --args="is_clang=true is_debug=false"
+"$DIR/ninja" -C "$BUILDDIR" ftrace_proto_gen
+
+# FIXME(fmayer): make ftrace_proto_gen independent of cwd.
+cd "$DIR/.."
+
+"$BUILDDIR/ftrace_proto_gen" \
+  --whitelist_path "$DIR/ftrace_proto_gen/event_whitelist" \
+  --output_dir "$DIR/../protos/perfetto/trace/ftrace/" \
+  --proto_descriptor "$BUILDDIR/gen/protos/perfetto/trace/ftrace.descriptor" \
+  --update_build_files \
+  "$@" \
+  "$DIR"/../src/ftrace_reader/test/data/*/events/
+
+rm -rf "$BUILDDIR"