1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include <stdio.h>
18*6dbdd20aSAndroid Build Coastguard Worker #include <string>
19*6dbdd20aSAndroid Build Coastguard Worker
20*6dbdd20aSAndroid Build Coastguard Worker #include <google/protobuf/compiler/importer.h>
21*6dbdd20aSAndroid Build Coastguard Worker #include <google/protobuf/io/zero_copy_stream_impl.h>
22*6dbdd20aSAndroid Build Coastguard Worker
23*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
24*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/file_utils.h"
25*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/getopt.h"
26*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/scoped_file.h"
27*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_utils.h"
28*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/version.h"
29*6dbdd20aSAndroid Build Coastguard Worker #include "src/tools/proto_merger/allowlist.h"
30*6dbdd20aSAndroid Build Coastguard Worker #include "src/tools/proto_merger/proto_file.h"
31*6dbdd20aSAndroid Build Coastguard Worker #include "src/tools/proto_merger/proto_file_serializer.h"
32*6dbdd20aSAndroid Build Coastguard Worker #include "src/tools/proto_merger/proto_merger.h"
33*6dbdd20aSAndroid Build Coastguard Worker
34*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
35*6dbdd20aSAndroid Build Coastguard Worker namespace proto_merger {
36*6dbdd20aSAndroid Build Coastguard Worker namespace {
37*6dbdd20aSAndroid Build Coastguard Worker
38*6dbdd20aSAndroid Build Coastguard Worker class MultiFileErrorCollectorImpl
39*6dbdd20aSAndroid Build Coastguard Worker : public google::protobuf::compiler::MultiFileErrorCollector {
40*6dbdd20aSAndroid Build Coastguard Worker public:
41*6dbdd20aSAndroid Build Coastguard Worker ~MultiFileErrorCollectorImpl() override;
42*6dbdd20aSAndroid Build Coastguard Worker void AddError(const std::string&, int, int, const std::string&) override;
43*6dbdd20aSAndroid Build Coastguard Worker void AddWarning(const std::string&, int, int, const std::string&) override;
44*6dbdd20aSAndroid Build Coastguard Worker };
45*6dbdd20aSAndroid Build Coastguard Worker
46*6dbdd20aSAndroid Build Coastguard Worker MultiFileErrorCollectorImpl::~MultiFileErrorCollectorImpl() = default;
47*6dbdd20aSAndroid Build Coastguard Worker
AddError(const std::string & filename,int line,int column,const std::string & message)48*6dbdd20aSAndroid Build Coastguard Worker void MultiFileErrorCollectorImpl::AddError(const std::string& filename,
49*6dbdd20aSAndroid Build Coastguard Worker int line,
50*6dbdd20aSAndroid Build Coastguard Worker int column,
51*6dbdd20aSAndroid Build Coastguard Worker const std::string& message) {
52*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Error %s %d:%d: %s", filename.c_str(), line, column,
53*6dbdd20aSAndroid Build Coastguard Worker message.c_str());
54*6dbdd20aSAndroid Build Coastguard Worker }
55*6dbdd20aSAndroid Build Coastguard Worker
AddWarning(const std::string & filename,int line,int column,const std::string & message)56*6dbdd20aSAndroid Build Coastguard Worker void MultiFileErrorCollectorImpl::AddWarning(const std::string& filename,
57*6dbdd20aSAndroid Build Coastguard Worker int line,
58*6dbdd20aSAndroid Build Coastguard Worker int column,
59*6dbdd20aSAndroid Build Coastguard Worker const std::string& message) {
60*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Warning %s %d:%d: %s", filename.c_str(), line, column,
61*6dbdd20aSAndroid Build Coastguard Worker message.c_str());
62*6dbdd20aSAndroid Build Coastguard Worker }
63*6dbdd20aSAndroid Build Coastguard Worker
64*6dbdd20aSAndroid Build Coastguard Worker struct ImportResult {
65*6dbdd20aSAndroid Build Coastguard Worker std::unique_ptr<google::protobuf::compiler::Importer> importer;
66*6dbdd20aSAndroid Build Coastguard Worker const google::protobuf::FileDescriptor* file_descriptor;
67*6dbdd20aSAndroid Build Coastguard Worker };
68*6dbdd20aSAndroid Build Coastguard Worker
ImportProto(const std::string & proto_file,const std::string & proto_dir_path)69*6dbdd20aSAndroid Build Coastguard Worker ImportResult ImportProto(const std::string& proto_file,
70*6dbdd20aSAndroid Build Coastguard Worker const std::string& proto_dir_path) {
71*6dbdd20aSAndroid Build Coastguard Worker MultiFileErrorCollectorImpl mfe;
72*6dbdd20aSAndroid Build Coastguard Worker
73*6dbdd20aSAndroid Build Coastguard Worker google::protobuf::compiler::DiskSourceTree dst;
74*6dbdd20aSAndroid Build Coastguard Worker dst.MapPath("", proto_dir_path);
75*6dbdd20aSAndroid Build Coastguard Worker
76*6dbdd20aSAndroid Build Coastguard Worker ImportResult result;
77*6dbdd20aSAndroid Build Coastguard Worker result.importer.reset(new google::protobuf::compiler::Importer(&dst, &mfe));
78*6dbdd20aSAndroid Build Coastguard Worker result.file_descriptor = result.importer->Import(proto_file);
79*6dbdd20aSAndroid Build Coastguard Worker return result;
80*6dbdd20aSAndroid Build Coastguard Worker }
81*6dbdd20aSAndroid Build Coastguard Worker
82*6dbdd20aSAndroid Build Coastguard Worker const char kUsage[] =
83*6dbdd20aSAndroid Build Coastguard Worker R"(Usage: proto_merger [-i input proto] [-I import dir]
84*6dbdd20aSAndroid Build Coastguard Worker
85*6dbdd20aSAndroid Build Coastguard Worker -i, --input: Path to the input .proto file (relative to
86*6dbdd20aSAndroid Build Coastguard Worker --input-include directory). The contents of this
87*6dbdd20aSAndroid Build Coastguard Worker file will be updated using the upstream proto.
88*6dbdd20aSAndroid Build Coastguard Worker -I, --input-include: Root directory from which includes for --input
89*6dbdd20aSAndroid Build Coastguard Worker proto should be searched.
90*6dbdd20aSAndroid Build Coastguard Worker -u, --upstream: Path to the upstream .proto file; the contents of
91*6dbdd20aSAndroid Build Coastguard Worker this file will be used to update
92*6dbdd20aSAndroid Build Coastguard Worker the input proto.
93*6dbdd20aSAndroid Build Coastguard Worker -U, --upstream-include: Root directory from which includes for --upstream
94*6dbdd20aSAndroid Build Coastguard Worker proto should be searched.
95*6dbdd20aSAndroid Build Coastguard Worker -a, --allowlist: Allowlist file which is used to add new fields in
96*6dbdd20aSAndroid Build Coastguard Worker the upstream proto to the input proto.
97*6dbdd20aSAndroid Build Coastguard Worker -r, --upstream-root-message: Root message in the upstream proto for which new
98*6dbdd20aSAndroid Build Coastguard Worker fields from the allowlist will be allowed.
99*6dbdd20aSAndroid Build Coastguard Worker -o, --output: Output path for writing the merged proto file.
100*6dbdd20aSAndroid Build Coastguard Worker
101*6dbdd20aSAndroid Build Coastguard Worker Example usage:
102*6dbdd20aSAndroid Build Coastguard Worker
103*6dbdd20aSAndroid Build Coastguard Worker # Updating logs proto from Perfetto repo (must be run in G3):
104*6dbdd20aSAndroid Build Coastguard Worker proto_merger \
105*6dbdd20aSAndroid Build Coastguard Worker -u third_party/perfetto/protos/perfetto/trace/perfetto_trace.proto \
106*6dbdd20aSAndroid Build Coastguard Worker -U . \
107*6dbdd20aSAndroid Build Coastguard Worker -i <path to logs proto>/perfetto_log.proto \
108*6dbdd20aSAndroid Build Coastguard Worker -I . \
109*6dbdd20aSAndroid Build Coastguard Worker --allowlist /tmp/allowlist.txt \
110*6dbdd20aSAndroid Build Coastguard Worker -r perfetto.protos.Trace \
111*6dbdd20aSAndroid Build Coastguard Worker --output /tmp/output.proto
112*6dbdd20aSAndroid Build Coastguard Worker )";
113*6dbdd20aSAndroid Build Coastguard Worker
Main(int argc,char ** argv)114*6dbdd20aSAndroid Build Coastguard Worker int Main(int argc, char** argv) {
115*6dbdd20aSAndroid Build Coastguard Worker static const option long_options[] = {
116*6dbdd20aSAndroid Build Coastguard Worker {"help", no_argument, nullptr, 'h'},
117*6dbdd20aSAndroid Build Coastguard Worker {"version", no_argument, nullptr, 'v'},
118*6dbdd20aSAndroid Build Coastguard Worker {"input", required_argument, nullptr, 'i'},
119*6dbdd20aSAndroid Build Coastguard Worker {"input-include", required_argument, nullptr, 'I'},
120*6dbdd20aSAndroid Build Coastguard Worker {"upstream", required_argument, nullptr, 'u'},
121*6dbdd20aSAndroid Build Coastguard Worker {"upstream-include", required_argument, nullptr, 'U'},
122*6dbdd20aSAndroid Build Coastguard Worker {"allowlist", required_argument, nullptr, 'a'},
123*6dbdd20aSAndroid Build Coastguard Worker {"upstream-root-message", required_argument, nullptr, 'r'},
124*6dbdd20aSAndroid Build Coastguard Worker {"output", required_argument, nullptr, 'o'},
125*6dbdd20aSAndroid Build Coastguard Worker {nullptr, 0, nullptr, 0}};
126*6dbdd20aSAndroid Build Coastguard Worker
127*6dbdd20aSAndroid Build Coastguard Worker std::string input;
128*6dbdd20aSAndroid Build Coastguard Worker std::string input_include;
129*6dbdd20aSAndroid Build Coastguard Worker std::string upstream;
130*6dbdd20aSAndroid Build Coastguard Worker std::string upstream_include;
131*6dbdd20aSAndroid Build Coastguard Worker std::string allowlist;
132*6dbdd20aSAndroid Build Coastguard Worker std::string upstream_root_message;
133*6dbdd20aSAndroid Build Coastguard Worker std::string output;
134*6dbdd20aSAndroid Build Coastguard Worker
135*6dbdd20aSAndroid Build Coastguard Worker for (;;) {
136*6dbdd20aSAndroid Build Coastguard Worker int option =
137*6dbdd20aSAndroid Build Coastguard Worker getopt_long(argc, argv, "hvi:I:u:U:a:r:o:", long_options, nullptr);
138*6dbdd20aSAndroid Build Coastguard Worker
139*6dbdd20aSAndroid Build Coastguard Worker if (option == -1)
140*6dbdd20aSAndroid Build Coastguard Worker break; // EOF.
141*6dbdd20aSAndroid Build Coastguard Worker
142*6dbdd20aSAndroid Build Coastguard Worker if (option == 'v') {
143*6dbdd20aSAndroid Build Coastguard Worker printf("%s\n", base::GetVersionString());
144*6dbdd20aSAndroid Build Coastguard Worker return 0;
145*6dbdd20aSAndroid Build Coastguard Worker }
146*6dbdd20aSAndroid Build Coastguard Worker
147*6dbdd20aSAndroid Build Coastguard Worker if (option == 'i') {
148*6dbdd20aSAndroid Build Coastguard Worker input = optarg;
149*6dbdd20aSAndroid Build Coastguard Worker continue;
150*6dbdd20aSAndroid Build Coastguard Worker }
151*6dbdd20aSAndroid Build Coastguard Worker
152*6dbdd20aSAndroid Build Coastguard Worker if (option == 'I') {
153*6dbdd20aSAndroid Build Coastguard Worker input_include = optarg;
154*6dbdd20aSAndroid Build Coastguard Worker continue;
155*6dbdd20aSAndroid Build Coastguard Worker }
156*6dbdd20aSAndroid Build Coastguard Worker
157*6dbdd20aSAndroid Build Coastguard Worker if (option == 'u') {
158*6dbdd20aSAndroid Build Coastguard Worker upstream = optarg;
159*6dbdd20aSAndroid Build Coastguard Worker continue;
160*6dbdd20aSAndroid Build Coastguard Worker }
161*6dbdd20aSAndroid Build Coastguard Worker
162*6dbdd20aSAndroid Build Coastguard Worker if (option == 'U') {
163*6dbdd20aSAndroid Build Coastguard Worker upstream_include = optarg;
164*6dbdd20aSAndroid Build Coastguard Worker continue;
165*6dbdd20aSAndroid Build Coastguard Worker }
166*6dbdd20aSAndroid Build Coastguard Worker
167*6dbdd20aSAndroid Build Coastguard Worker if (option == 'a') {
168*6dbdd20aSAndroid Build Coastguard Worker allowlist = optarg;
169*6dbdd20aSAndroid Build Coastguard Worker continue;
170*6dbdd20aSAndroid Build Coastguard Worker }
171*6dbdd20aSAndroid Build Coastguard Worker
172*6dbdd20aSAndroid Build Coastguard Worker if (option == 'r') {
173*6dbdd20aSAndroid Build Coastguard Worker upstream_root_message = optarg;
174*6dbdd20aSAndroid Build Coastguard Worker continue;
175*6dbdd20aSAndroid Build Coastguard Worker }
176*6dbdd20aSAndroid Build Coastguard Worker
177*6dbdd20aSAndroid Build Coastguard Worker if (option == 'o') {
178*6dbdd20aSAndroid Build Coastguard Worker output = optarg;
179*6dbdd20aSAndroid Build Coastguard Worker continue;
180*6dbdd20aSAndroid Build Coastguard Worker }
181*6dbdd20aSAndroid Build Coastguard Worker
182*6dbdd20aSAndroid Build Coastguard Worker if (option == 'h') {
183*6dbdd20aSAndroid Build Coastguard Worker fprintf(stdout, kUsage);
184*6dbdd20aSAndroid Build Coastguard Worker return 0;
185*6dbdd20aSAndroid Build Coastguard Worker }
186*6dbdd20aSAndroid Build Coastguard Worker
187*6dbdd20aSAndroid Build Coastguard Worker fprintf(stderr, kUsage);
188*6dbdd20aSAndroid Build Coastguard Worker return 1;
189*6dbdd20aSAndroid Build Coastguard Worker }
190*6dbdd20aSAndroid Build Coastguard Worker
191*6dbdd20aSAndroid Build Coastguard Worker if (input.empty()) {
192*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Input proto (--input) should be specified");
193*6dbdd20aSAndroid Build Coastguard Worker return 1;
194*6dbdd20aSAndroid Build Coastguard Worker }
195*6dbdd20aSAndroid Build Coastguard Worker
196*6dbdd20aSAndroid Build Coastguard Worker if (input_include.empty()) {
197*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG(
198*6dbdd20aSAndroid Build Coastguard Worker "Input include directory (--input-include) should be specified");
199*6dbdd20aSAndroid Build Coastguard Worker return 1;
200*6dbdd20aSAndroid Build Coastguard Worker }
201*6dbdd20aSAndroid Build Coastguard Worker
202*6dbdd20aSAndroid Build Coastguard Worker if (upstream.empty()) {
203*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Upstream proto (--upstream) should be specified");
204*6dbdd20aSAndroid Build Coastguard Worker return 1;
205*6dbdd20aSAndroid Build Coastguard Worker }
206*6dbdd20aSAndroid Build Coastguard Worker
207*6dbdd20aSAndroid Build Coastguard Worker if (upstream_include.empty()) {
208*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG(
209*6dbdd20aSAndroid Build Coastguard Worker "Upstream include directory (--upstream-include) should be specified");
210*6dbdd20aSAndroid Build Coastguard Worker return 1;
211*6dbdd20aSAndroid Build Coastguard Worker }
212*6dbdd20aSAndroid Build Coastguard Worker
213*6dbdd20aSAndroid Build Coastguard Worker if (output.empty()) {
214*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Output file (--output) should be specified");
215*6dbdd20aSAndroid Build Coastguard Worker return 1;
216*6dbdd20aSAndroid Build Coastguard Worker }
217*6dbdd20aSAndroid Build Coastguard Worker
218*6dbdd20aSAndroid Build Coastguard Worker if (!allowlist.empty() && upstream_root_message.empty()) {
219*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG(
220*6dbdd20aSAndroid Build Coastguard Worker "Need to specifiy upstream root message (--upstream-root-message) when "
221*6dbdd20aSAndroid Build Coastguard Worker "specifying allowlist");
222*6dbdd20aSAndroid Build Coastguard Worker return 1;
223*6dbdd20aSAndroid Build Coastguard Worker }
224*6dbdd20aSAndroid Build Coastguard Worker
225*6dbdd20aSAndroid Build Coastguard Worker std::string input_contents;
226*6dbdd20aSAndroid Build Coastguard Worker if (!base::ReadFile(input_include + "/" + input, &input_contents)) {
227*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Failed to read input");
228*6dbdd20aSAndroid Build Coastguard Worker return 1;
229*6dbdd20aSAndroid Build Coastguard Worker }
230*6dbdd20aSAndroid Build Coastguard Worker
231*6dbdd20aSAndroid Build Coastguard Worker static constexpr char kPremable[] =
232*6dbdd20aSAndroid Build Coastguard Worker "// --- PREAMBLE ENDS HERE - EVERYTHING BELOW AUTOGENERATED ---\n";
233*6dbdd20aSAndroid Build Coastguard Worker size_t input_premable_idx = input_contents.find(kPremable);
234*6dbdd20aSAndroid Build Coastguard Worker std::string input_preamble =
235*6dbdd20aSAndroid Build Coastguard Worker input_premable_idx == std::string::npos
236*6dbdd20aSAndroid Build Coastguard Worker ? ""
237*6dbdd20aSAndroid Build Coastguard Worker : input_contents.substr(0, input_premable_idx + strlen(kPremable));
238*6dbdd20aSAndroid Build Coastguard Worker
239*6dbdd20aSAndroid Build Coastguard Worker ImportResult input_proto = ImportProto(input, input_include);
240*6dbdd20aSAndroid Build Coastguard Worker ProtoFile input_file = ProtoFileFromDescriptor(std::move(input_preamble),
241*6dbdd20aSAndroid Build Coastguard Worker *input_proto.file_descriptor);
242*6dbdd20aSAndroid Build Coastguard Worker
243*6dbdd20aSAndroid Build Coastguard Worker ImportResult upstream_proto = ImportProto(upstream, upstream_include);
244*6dbdd20aSAndroid Build Coastguard Worker ProtoFile upstream_file =
245*6dbdd20aSAndroid Build Coastguard Worker ProtoFileFromDescriptor("", *upstream_proto.file_descriptor);
246*6dbdd20aSAndroid Build Coastguard Worker
247*6dbdd20aSAndroid Build Coastguard Worker Allowlist allowed;
248*6dbdd20aSAndroid Build Coastguard Worker if (!allowlist.empty()) {
249*6dbdd20aSAndroid Build Coastguard Worker std::string allowlist_contents;
250*6dbdd20aSAndroid Build Coastguard Worker if (!base::ReadFile(allowlist, &allowlist_contents)) {
251*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Failed to read allowlist");
252*6dbdd20aSAndroid Build Coastguard Worker return 1;
253*6dbdd20aSAndroid Build Coastguard Worker }
254*6dbdd20aSAndroid Build Coastguard Worker
255*6dbdd20aSAndroid Build Coastguard Worker auto* desc = upstream_proto.importer->pool()->FindMessageTypeByName(
256*6dbdd20aSAndroid Build Coastguard Worker upstream_root_message);
257*6dbdd20aSAndroid Build Coastguard Worker if (!desc) {
258*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG(
259*6dbdd20aSAndroid Build Coastguard Worker "Failed to find root message descriptor in upstream proto file");
260*6dbdd20aSAndroid Build Coastguard Worker return 1;
261*6dbdd20aSAndroid Build Coastguard Worker }
262*6dbdd20aSAndroid Build Coastguard Worker
263*6dbdd20aSAndroid Build Coastguard Worker auto field_list = base::SplitString(allowlist_contents, "\n");
264*6dbdd20aSAndroid Build Coastguard Worker base::Status status = AllowlistFromFieldList(*desc, field_list, allowed);
265*6dbdd20aSAndroid Build Coastguard Worker if (!status.ok()) {
266*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Failed creating allowlist: %s", status.c_message());
267*6dbdd20aSAndroid Build Coastguard Worker return 1;
268*6dbdd20aSAndroid Build Coastguard Worker }
269*6dbdd20aSAndroid Build Coastguard Worker }
270*6dbdd20aSAndroid Build Coastguard Worker
271*6dbdd20aSAndroid Build Coastguard Worker ProtoFile merged;
272*6dbdd20aSAndroid Build Coastguard Worker base::Status status =
273*6dbdd20aSAndroid Build Coastguard Worker MergeProtoFiles(input_file, upstream_file, allowed, merged);
274*6dbdd20aSAndroid Build Coastguard Worker if (!status.ok()) {
275*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Failed merging protos: %s", status.c_message());
276*6dbdd20aSAndroid Build Coastguard Worker return 1;
277*6dbdd20aSAndroid Build Coastguard Worker }
278*6dbdd20aSAndroid Build Coastguard Worker
279*6dbdd20aSAndroid Build Coastguard Worker base::ScopedFile output_file(
280*6dbdd20aSAndroid Build Coastguard Worker base::OpenFile(output, O_CREAT | O_WRONLY | O_TRUNC, 0664));
281*6dbdd20aSAndroid Build Coastguard Worker if (!output_file) {
282*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ELOG("Failed opening output file: %s", output.c_str());
283*6dbdd20aSAndroid Build Coastguard Worker return 1;
284*6dbdd20aSAndroid Build Coastguard Worker }
285*6dbdd20aSAndroid Build Coastguard Worker std::string out = ProtoFileToDotProto(merged);
286*6dbdd20aSAndroid Build Coastguard Worker base::WriteAll(*output_file, out.c_str(), out.size());
287*6dbdd20aSAndroid Build Coastguard Worker
288*6dbdd20aSAndroid Build Coastguard Worker return 0;
289*6dbdd20aSAndroid Build Coastguard Worker }
290*6dbdd20aSAndroid Build Coastguard Worker
291*6dbdd20aSAndroid Build Coastguard Worker } // namespace
292*6dbdd20aSAndroid Build Coastguard Worker } // namespace proto_merger
293*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
294*6dbdd20aSAndroid Build Coastguard Worker
main(int argc,char ** argv)295*6dbdd20aSAndroid Build Coastguard Worker int main(int argc, char** argv) {
296*6dbdd20aSAndroid Build Coastguard Worker return perfetto::proto_merger::Main(argc, argv);
297*6dbdd20aSAndroid Build Coastguard Worker }
298