• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2022 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import("../../gn/perfetto.gni")
16
17# Prevent that this file is accidentally included in embedder builds.
18assert(enable_perfetto_site)
19
20nodejs_bin = rebase_path("../../tools/node", root_build_dir)
21
22# The destination directory where the website will be built. GN pollutes
23# root_out_dir with all sorts of files, so we use a subdirectory.
24perfetto_website_out_dir = "$root_out_dir/site"
25
26# The directory containing all the markdown sources for the docs.
27src_doc_dir = "../../docs"
28
29group("site") {
30  deps = [
31    ":all_mdfiles",
32    ":assets",
33    ":gen_index",
34    ":gen_sql_stats_html",
35    ":gen_sql_tables_html",
36    ":gen_stdlib_docs_html",
37    ":gen_toc",
38    ":gen_trace_config_proto",
39    ":gen_trace_packet_proto",
40    ":gen_ui_plugin_api_html",
41    ":node_assets",
42    ":readme",
43    ":style_scss",
44  ]
45}
46
47# Runs a nodejs script using the hermetic node toolchain.
48# Args:
49# * script: The .js script to execute
50# * inputs
51# * outputs
52# * deps
53# * depfile
54template("nodejs_script") {
55  assert(defined(invoker.script), "Need script in $target_name")
56
57  action(target_name) {
58    forward_variables_from(invoker,
59                           [
60                             "outputs",
61                             "depfile",
62                           ])
63    deps = [ ":node_modules" ]
64    if (defined(invoker.deps)) {
65      deps += invoker.deps
66    }
67    script = "../../gn/standalone/build_tool_wrapper.py"
68    inputs = [ invoker.script ]
69    inputs += invoker.inputs
70    args = [
71      nodejs_bin,
72      rebase_path(invoker.script, root_build_dir),
73    ]
74    args += invoker.args
75  }
76}
77
78# Installs the node modules specified in package.json
79action("node_modules") {
80  script = "../../gn/standalone/build_tool_wrapper.py"
81  stamp_file = "$target_out_dir/.$target_name.stamp"
82  cur_dir = rebase_path(".", root_build_dir)
83  args = [
84    "--stamp",
85    rebase_path(stamp_file, root_build_dir),
86    "--chdir=$cur_dir",
87    rebase_path("../../tools/pnpm", root_build_dir),
88    "install",
89    "--shamefully-hoist",
90    "--frozen-lockfile",
91  ]
92  inputs = [
93    "../../tools/npm",
94    "package.json",
95    "pnpm-lock.yaml",
96  ]
97  outputs = [ stamp_file ]
98}
99
100# Renders a markdown file into html.
101# Args:
102# * markdown: Optional. The source markdown file
103# * html_template: Optional. The html template to use
104# * out_html: The generated html, relative to `perfetto_website_out_dir`
105# * deps
106template("md_to_html") {
107  assert(defined(invoker.out_html), "Need out_html in $target_name")
108  assert(defined(invoker.html_template) || defined(invoker.markdown),
109         "Need html_template or markdown in $target_name")
110  nodejs_script(target_name) {
111    forward_variables_from(invoker, [ "deps" ])
112    script = "src/markdown_render.js"
113    inputs = []
114    if (defined(invoker.markdown)) {
115      inputs += [ invoker.markdown ]
116    }
117    depfile = "${target_gen_dir}/$target_name.d"
118    if (defined(invoker.html_template)) {
119      inputs += [ invoker.html_template ]
120    }
121    outputs = [ "${perfetto_website_out_dir}/${invoker.out_html}" ]
122    args = [
123      "--odir",
124      rebase_path(perfetto_website_out_dir, root_build_dir),
125      "-o",
126      rebase_path("${perfetto_website_out_dir}/${invoker.out_html}",
127                  root_build_dir),
128      "--depfile",
129      rebase_path(depfile, root_build_dir),
130    ]
131    if (defined(invoker.markdown)) {
132      args += [
133        "-i",
134        rebase_path(invoker.markdown, root_build_dir),
135      ]
136    }
137    if (defined(invoker.html_template)) {
138      args += [
139        "-t",
140        rebase_path(invoker.html_template, root_build_dir),
141      ]
142    }
143  }
144}
145
146md_to_html("gen_toc") {
147  markdown = "${src_doc_dir}/toc.md"
148  out_html = "docs/_nav.html"
149}
150
151md_to_html("gen_index") {
152  html_template = "src/template_index.html"
153  deps = [ ":gen_toc" ]
154  out_html = "index.html"
155}
156
157nodejs_script("style_scss") {
158  script = "node_modules/sass/sass.js"
159  input = "src/assets/style.scss"
160  inputs = [ input ]
161  output = "${perfetto_website_out_dir}/assets/style.css"
162  outputs = [ output ]
163  args = [
164    "--quiet",
165    rebase_path(input, root_build_dir),
166    rebase_path(output, root_build_dir),
167  ]
168  deps = [ ":node_modules" ]
169}
170
171sql_stats_md = "${target_gen_dir}/sql-stats.md"
172
173nodejs_script("gen_sql_stats_md") {
174  script = "src/gen_stats_reference.js"
175  input = "../../src/trace_processor/storage/stats.h"
176  inputs = [ input ]
177  outputs = [ sql_stats_md ]
178  args = [
179    "-i",
180    rebase_path(input, root_build_dir),
181    "-o",
182    rebase_path(sql_stats_md, root_build_dir),
183  ]
184}
185
186md_to_html("gen_sql_stats_html") {
187  markdown = sql_stats_md
188  html_template = "src/template_markdown.html"
189  deps = [
190    ":gen_sql_stats_md",
191    ":gen_toc",
192  ]
193  out_html = "docs/analysis/sql-stats"
194}
195
196ui_plugin_api_md = "${target_gen_dir}/ui-plugin-api.md"
197
198nodejs_script("gen_ui_plugin_api_md") {
199  script = "src/gen_ui_reference.js"
200  input = "../../ui/src/public/index.ts"
201  inputs = [ input ]
202  outputs = [ ui_plugin_api_md ]
203  args = [
204    "-i",
205    rebase_path(input, root_build_dir),
206    "-o",
207    rebase_path(ui_plugin_api_md, root_build_dir),
208  ]
209}
210
211md_to_html("gen_ui_plugin_api_html") {
212  markdown = ui_plugin_api_md
213  html_template = "src/template_markdown.html"
214  deps = [
215    ":gen_toc",
216    ":gen_ui_plugin_api_md",
217  ]
218  out_html = "docs/reference/ui-plugin-api"
219}
220
221# Generates a html reference for a proto
222# Args:
223# * proto: The path to a .proto file
224# * message_name: The proto message name
225# * out_html
226template("proto_reference") {
227  sql_stats_md = "${target_gen_dir}/${target_name}.md"
228  nodejs_script("${target_name}_md") {
229    script = "src/gen_proto_reference.js"
230    inputs = [ invoker.proto ]
231    outputs = [ sql_stats_md ]
232    args = [
233      "-i",
234      rebase_path(invoker.proto, root_build_dir),
235      "-p",
236      invoker.message_name,
237      "-o",
238      rebase_path(sql_stats_md, root_build_dir),
239    ]
240  }
241
242  md_to_html(target_name) {
243    markdown = sql_stats_md
244    html_template = "src/template_markdown.html"
245    deps = [
246      ":${target_name}_md",
247      ":gen_toc",
248    ]
249    out_html = invoker.out_html
250  }
251}
252
253proto_reference("gen_trace_config_proto") {
254  proto = "../../protos/perfetto/config/trace_config.proto"
255  message_name = "perfetto.protos.TraceConfig"
256  out_html = "docs/reference/trace-config-proto"
257}
258
259proto_reference("gen_trace_packet_proto") {
260  proto = "../../protos/perfetto/trace/trace_packet.proto"
261  message_name = "perfetto.protos.TracePacket"
262  out_html = "docs/reference/trace-packet-proto"
263}
264
265# WARNING: this does globbing at generation time. Incremental builds are not
266# going to work properly if files are added/removed. `gn gen` needs to be
267# rerun.
268sql_tables =
269    exec_script("../../gn/standalone/glob.py",
270                [
271                  "--root=" + rebase_path("../../src/trace_processor/tables",
272                                          root_build_dir),
273                  "--filter=*.h",
274                ],
275                "list lines")
276
277src_sql_tables = []
278
279foreach(i, sql_tables) {
280  src_sql_tables += [ rebase_path(i, ".", root_build_dir) ]
281}
282
283sql_tables_md = "${target_gen_dir}/sql-tables.md"
284stdlib_docs_md = "${target_gen_dir}/stdlib_docs.md"
285
286action("gen_stdlib_docs_md") {
287  script = "src/gen_stdlib_docs_md.py"
288  label_info = get_label_info(
289          "../../src/trace_processor/perfetto_sql/stdlib:stdlib_json_docs",
290          "target_gen_dir")
291  absolute_input_path = label_info + "/stdlib_docs.json"
292  deps = [
293    "../../python:trace_processor_stdlib_docs",
294    "../../src/trace_processor/perfetto_sql/stdlib:stdlib_json_docs",
295  ]
296  outputs = [ stdlib_docs_md ]
297  args = [
298    "--input",
299    rebase_path(absolute_input_path, root_build_dir),
300    "--output",
301    rebase_path(stdlib_docs_md, root_build_dir),
302  ]
303}
304
305md_to_html("gen_stdlib_docs_html") {
306  markdown = stdlib_docs_md
307  html_template = "src/template_markdown.html"
308  deps = [
309    ":gen_stdlib_docs_md",
310    ":gen_toc",
311  ]
312  out_html = "docs/analysis/stdlib-docs"
313}
314
315nodejs_script("gen_sql_tables_md") {
316  python_label = "../../src/trace_processor/tables:tables_python_docs"
317  python_docs_json = get_label_info(python_label, "target_gen_dir") + "/" +
318                     get_label_info(python_label, "name") + ".json"
319
320  script = "src/gen_sql_tables_reference.js"
321  inputs = src_sql_tables
322  deps = [ python_label ]
323  outputs = [ sql_tables_md ]
324  args = [
325    "-o",
326    rebase_path(sql_tables_md, root_build_dir),
327  ]
328  foreach(file, src_sql_tables) {
329    args += [
330      "-i",
331      rebase_path(file, root_build_dir),
332    ]
333  }
334  args += [
335    "-j",
336    rebase_path(python_docs_json, root_build_dir),
337  ]
338}
339
340md_to_html("gen_sql_tables_html") {
341  markdown = sql_tables_md
342  html_template = "src/template_markdown.html"
343  deps = [
344    ":gen_sql_tables_md",
345    ":gen_toc",
346  ]
347  out_html = "docs/analysis/sql-tables"
348}
349
350md_to_html("readme") {
351  markdown = "${src_doc_dir}/README.md"
352  html_template = "src/template_markdown.html"
353  out_html = "docs/index.html"
354  deps = [ ":gen_toc" ]
355}
356
357# WARNING: this does globbing at generation time. Incremental builds are not
358# going to work properly if files are added/removed. `gn gen` needs to be
359# rerun.
360mdfiles = exec_script("../../gn/standalone/glob.py",
361                      [
362                        "--root=" + rebase_path(src_doc_dir, root_build_dir),
363                        "--filter=*.md",
364                      ],
365                      "list lines")
366
367mdfiles -= [
368  rebase_path("../../docs/README.md", root_build_dir),
369  rebase_path("../../docs/toc.md", root_build_dir),
370]
371
372mdtargets = []
373
374foreach(source, mdfiles) {
375  filename = rebase_path(string_replace(source, ".md", ""),
376                         rebase_path("../../docs", root_build_dir))
377
378  md_to_html("mdfile_${source}") {
379    markdown = rebase_path(source, ".", root_build_dir)
380    html_template = "src/template_markdown.html"
381    out_html = "docs/${filename}"
382    deps = [ ":gen_toc" ]
383  }
384  mdtargets += [ ":mdfile_${source}" ]
385}
386
387group("all_mdfiles") {
388  deps = mdtargets
389}
390
391copy("node_assets") {
392  sources = [
393    "node_modules/highlight.js/styles/tomorrow-night.css",
394    "node_modules/mermaid/dist/mermaid.min.js",
395  ]
396  deps = [ ":node_modules" ]
397
398  outputs = [ "${perfetto_website_out_dir}/assets/{{source_file_part}}" ]
399}
400
401# WARNING: this does globbing at generation time. Incremental builds are not
402# going to work properly if files are added/removed. `gn gen` needs to be
403# rerun.
404assets = exec_script("../../gn/standalone/glob.py",
405                     [
406                       "--root=" + rebase_path("src/assets", root_build_dir),
407                       "--filter=*.png",
408                       "--filter=*.js",
409                     ],
410                     "list lines")
411
412src_assets = []
413
414foreach(i, assets) {
415  src_assets += [ rebase_path(i, ".", root_build_dir) ]
416}
417
418copy("assets") {
419  sources = src_assets
420  outputs = [ "${perfetto_website_out_dir}/assets/{{source_file_part}}" ]
421}
422