summaryrefslogtreecommitdiff
path: root/chromium/tools
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 15:28:34 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:54:51 +0000
commit2a19c63448c84c1805fb1a585c3651318bb86ca7 (patch)
treeeb17888e8531aa6ee5e85721bd553b832a7e5156 /chromium/tools
parentb014812705fc80bff0a5c120dfcef88f349816dc (diff)
downloadqtwebengine-chromium-2a19c63448c84c1805fb1a585c3651318bb86ca7.tar.gz
BASELINE: Update Chromium to 69.0.3497.70
Change-Id: I2b7b56e4e7a8b26656930def0d4575dc32b900a0 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/tools')
-rw-r--r--chromium/tools/accessibility/inspect/README.md32
-rw-r--r--chromium/tools/accessibility/inspect/ax_dump_events.cc3
-rw-r--r--chromium/tools/accessibility/inspect/ax_dump_tree.cc15
-rw-r--r--chromium/tools/accessibility/inspect/ax_tree_server.cc2
-rw-r--r--chromium/tools/accessibility/inspect/chrome-events.ps112
-rw-r--r--chromium/tools/accessibility/inspect/chrome-tree.ps113
-rw-r--r--chromium/tools/accessibility/inspect/chromium-events.ps112
-rw-r--r--chromium/tools/accessibility/inspect/chromium-tree.ps113
-rw-r--r--chromium/tools/accessibility/inspect/example-tree-filters.txt8
-rw-r--r--chromium/tools/accessibility/inspect/ff-events.ps15
-rw-r--r--chromium/tools/accessibility/inspect/ff-tree.ps15
-rwxr-xr-xchromium/tools/accessibility/rebase_dump_accessibility_tree_test.py22
-rw-r--r--chromium/tools/android/BUILD.gn7
-rw-r--r--chromium/tools/android/forwarder2/BUILD.gn2
-rw-r--r--chromium/tools/android/io_benchmark/BUILD.gn14
-rw-r--r--chromium/tools/android/md5sum/BUILD.gn8
-rw-r--r--chromium/tools/android/memdump/BUILD.gn1
-rw-r--r--chromium/tools/battor_agent/BUILD.gn1
-rw-r--r--chromium/tools/battor_agent/battor_connection_impl_unittest.cc29
-rw-r--r--chromium/tools/binary_size/BUILD.gn1
-rw-r--r--chromium/tools/binary_size/README.md32
-rwxr-xr-xchromium/tools/binary_size/diagnose_bloat.py95
-rw-r--r--chromium/tools/binary_size/html_report_faq.md80
-rw-r--r--chromium/tools/binary_size/libsupersize/apkanalyzer.py11
-rw-r--r--chromium/tools/binary_size/libsupersize/archive.py184
-rwxr-xr-xchromium/tools/binary_size/libsupersize/bcanalyzer.py379
-rwxr-xr-xchromium/tools/binary_size/libsupersize/bcanalyzer_test.py146
-rw-r--r--chromium/tools/binary_size/libsupersize/concurrent.py28
-rwxr-xr-xchromium/tools/binary_size/libsupersize/concurrent_test.py31
-rw-r--r--chromium/tools/binary_size/libsupersize/console.py15
-rw-r--r--chromium/tools/binary_size/libsupersize/file_format.py216
-rw-r--r--chromium/tools/binary_size/libsupersize/html_report.py414
-rwxr-xr-xchromium/tools/binary_size/libsupersize/integration_test.py92
-rw-r--r--chromium/tools/binary_size/libsupersize/linker_map_parser.py65
-rwxr-xr-xchromium/tools/binary_size/libsupersize/main.py6
-rw-r--r--chromium/tools/binary_size/libsupersize/models.py53
-rw-r--r--[-rwxr-xr-x]chromium/tools/binary_size/libsupersize/nm.py574
-rwxr-xr-xchromium/tools/binary_size/libsupersize/obj_analyzer.py371
-rw-r--r--chromium/tools/binary_size/libsupersize/path_util.py11
-rw-r--r--chromium/tools/binary_size/libsupersize/start_server.py51
-rw-r--r--chromium/tools/binary_size/libsupersize/static/favicon.icobin0 -> 25995 bytes
-rw-r--r--chromium/tools/binary_size/libsupersize/static/index.html603
-rw-r--r--chromium/tools/binary_size/libsupersize/static/infocard-ui.js328
-rw-r--r--chromium/tools/binary_size/libsupersize/static/infocard.css113
-rw-r--r--chromium/tools/binary_size/libsupersize/static/options.css291
-rw-r--r--chromium/tools/binary_size/libsupersize/static/shared.js141
-rw-r--r--chromium/tools/binary_size/libsupersize/static/start-worker.js95
-rw-r--r--chromium/tools/binary_size/libsupersize/static/state.js402
-rw-r--r--chromium/tools/binary_size/libsupersize/static/tree-ui.js411
-rw-r--r--chromium/tools/binary_size/libsupersize/static/tree-worker.js759
-rw-r--r--chromium/tools/binary_size/libsupersize/string_extract.py249
-rw-r--r--chromium/tools/binary_size/libsupersize/template/D3SymbolTreeMap.js930
-rw-r--r--chromium/tools/binary_size/libsupersize/template/index.html517
-rw-r--r--chromium/tools/binary_size/libsupersize/template/test-data-generator.html157
-rw-r--r--chromium/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/args.gn (renamed from chromium/tools/binary_size/libsupersize/testdata/mock_output_directory/args.gn)0
-rw-r--r--chromium/tools/binary_size/libsupersize/third_party/gvr-android-sdk/libgvr_shim_static_arm.a3
-rw-r--r--chromium/tools/binary_size/supersize.pydeps3
-rwxr-xr-xchromium/tools/binary_size/trybot_commit_size_checker.py70
-rw-r--r--chromium/tools/cfi/blacklist.txt1
-rwxr-xr-xchromium/tools/checkperms/checkperms.py3
-rw-r--r--chromium/tools/chrome_proxy/webdriver/bypass.py6
-rw-r--r--chromium/tools/chrome_proxy/webdriver/lite_page.py112
-rw-r--r--chromium/tools/chrome_proxy/webdriver/lofi.py43
-rw-r--r--chromium/tools/chrome_proxy/webdriver/variations_combinations.py4
-rw-r--r--chromium/tools/clang/base_bind_rewriters/BaseBindRewriters.cpp72
-rw-r--r--chromium/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp2
-rw-r--r--chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp28
-rw-r--r--chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.h7
-rw-r--r--chromium/tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h3
-rw-r--r--chromium/tools/clang/blink_gc_plugin/CMakeLists.txt1
-rw-r--r--chromium/tools/clang/blink_gc_plugin/CheckTraceWrappersVisitor.cpp103
-rw-r--r--chromium/tools/clang/blink_gc_plugin/CheckTraceWrappersVisitor.h39
-rw-r--r--chromium/tools/clang/blink_gc_plugin/CollectVisitor.cpp6
-rw-r--r--chromium/tools/clang/blink_gc_plugin/CollectVisitor.h2
-rw-r--r--chromium/tools/clang/blink_gc_plugin/Config.cpp31
-rw-r--r--chromium/tools/clang/blink_gc_plugin/Config.h16
-rw-r--r--chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp9
-rw-r--r--chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.h4
-rw-r--r--chromium/tools/clang/blink_gc_plugin/RecordInfo.cpp123
-rw-r--r--chromium/tools/clang/blink_gc_plugin/RecordInfo.h28
-rw-r--r--chromium/tools/clang/plugins/OWNERS2
-rwxr-xr-xchromium/tools/clang/pylib/clang/compile_db.py11
-rwxr-xr-xchromium/tools/clang/scripts/generate_compdb.py17
-rwxr-xr-xchromium/tools/clang/scripts/package.py3
-rwxr-xr-xchromium/tools/clang/scripts/run_tool.py14
-rwxr-xr-xchromium/tools/clang/scripts/update.py59
-rw-r--r--chromium/tools/clang/translation_unit/TranslationUnitGenerator.cpp12
-rw-r--r--chromium/tools/clang/translation_unit/test_files/compile_commands.json.template7
-rw-r--r--chromium/tools/clang/translation_unit/test_files/includes_self.cc6
-rw-r--r--chromium/tools/clang/translation_unit/test_files/includes_self.cc.filepaths.expected1
-rw-r--r--chromium/tools/clang/translation_unit/test_files/test.cc.filepaths.expected4
-rwxr-xr-xchromium/tools/clang/translation_unit/test_translation_unit.py2
-rw-r--r--chromium/tools/code_coverage/test_suite.txt9
-rw-r--r--chromium/tools/cygprofile/BUILD.gn33
-rw-r--r--chromium/tools/cygprofile/delayed_dumper.cc54
-rw-r--r--chromium/tools/cygprofile/lightweight_cygprofile.cc224
-rw-r--r--chromium/tools/cygprofile/lightweight_cygprofile.h37
-rw-r--r--chromium/tools/cygprofile/lightweight_cygprofile_perftest.cc123
-rwxr-xr-xchromium/tools/cygprofile/orderfile_generator_backend.py42
-rwxr-xr-xchromium/tools/cygprofile/profile_android_startup.py108
-rwxr-xr-xchromium/tools/determinism/compare_build_artifacts.py18
-rw-r--r--chromium/tools/determinism/deterministic_build_whitelist.pyl1
-rw-r--r--chromium/tools/dump_process_memory/BUILD.gn18
-rw-r--r--chromium/tools/dump_process_memory/OWNERS3
-rwxr-xr-xchromium/tools/dump_process_memory/analyze_dumps.py253
-rw-r--r--chromium/tools/dump_process_memory/dump_process.cc259
-rw-r--r--chromium/tools/emacs/trybot-mac.txt6
-rwxr-xr-xchromium/tools/fuchsia/comparative_tester/comparative_tester.py430
-rwxr-xr-xchromium/tools/fuchsia/comparative_tester/generate_perf_report.py289
-rw-r--r--chromium/tools/fuchsia/comparative_tester/target_spec.py25
-rw-r--r--chromium/tools/fuchsia/comparative_tester/test_results.py186
-rwxr-xr-xchromium/tools/fuchsia/local-sdk.py2
-rw-r--r--chromium/tools/gdb/gdbinit4
-rw-r--r--chromium/tools/gn/BUILD.gn374
-rw-r--r--chromium/tools/gn/DEPS3
-rw-r--r--chromium/tools/gn/OWNERS3
-rw-r--r--chromium/tools/gn/README.md19
-rw-r--r--chromium/tools/gn/action_target_generator.cc221
-rw-r--r--chromium/tools/gn/action_target_generator.h41
-rw-r--r--chromium/tools/gn/action_target_generator_unittest.cc122
-rw-r--r--chromium/tools/gn/action_values.cc31
-rw-r--r--chromium/tools/gn/action_values.h70
-rw-r--r--chromium/tools/gn/analyzer.cc486
-rw-r--r--chromium/tools/gn/analyzer.h104
-rw-r--r--chromium/tools/gn/analyzer_unittest.cc594
-rw-r--r--chromium/tools/gn/args.cc424
-rw-r--r--chromium/tools/gn/args.h147
-rw-r--r--chromium/tools/gn/args_unittest.cc81
-rw-r--r--chromium/tools/gn/bin/compare_test_lists.py101
-rw-r--r--chromium/tools/gn/bin/gn-format.py59
-rwxr-xr-xchromium/tools/gn/bin/help_as_html.py105
-rwxr-xr-xchromium/tools/gn/bin/roll_gn.py461
-rw-r--r--chromium/tools/gn/binary_target_generator.cc182
-rw-r--r--chromium/tools/gn/binary_target_generator.h40
-rw-r--r--chromium/tools/gn/bootstrap/OWNERS6
-rwxr-xr-xchromium/tools/gn/bootstrap/bootstrap.py1037
-rw-r--r--chromium/tools/gn/bootstrap/build.ninja.template19
-rw-r--r--chromium/tools/gn/bootstrap/build_aix.ninja.template19
-rw-r--r--chromium/tools/gn/bootstrap/build_mac.ninja.template19
-rw-r--r--chromium/tools/gn/bootstrap/build_vs.ninja.template28
-rw-r--r--chromium/tools/gn/build_settings.cc77
-rw-r--r--chromium/tools/gn/build_settings.h140
-rw-r--r--chromium/tools/gn/builder.cc604
-rw-r--r--chromium/tools/gn/builder.h148
-rw-r--r--chromium/tools/gn/builder_record.cc74
-rw-r--r--chromium/tools/gn/builder_record.h113
-rw-r--r--chromium/tools/gn/builder_unittest.cc248
-rw-r--r--chromium/tools/gn/bundle_data.cc170
-rw-r--r--chromium/tools/gn/bundle_data.h199
-rw-r--r--chromium/tools/gn/bundle_data_target_generator.cc94
-rw-r--r--chromium/tools/gn/bundle_data_target_generator.h33
-rw-r--r--chromium/tools/gn/bundle_file_rule.cc66
-rw-r--r--chromium/tools/gn/bundle_file_rule.h51
-rw-r--r--chromium/tools/gn/c_include_iterator.cc175
-rw-r--r--chromium/tools/gn/c_include_iterator.h57
-rw-r--r--chromium/tools/gn/c_include_iterator_unittest.cc159
-rw-r--r--chromium/tools/gn/command_analyze.cc133
-rw-r--r--chromium/tools/gn/command_args.cc505
-rw-r--r--chromium/tools/gn/command_check.cc256
-rw-r--r--chromium/tools/gn/command_clean.cc129
-rw-r--r--chromium/tools/gn/command_desc.cc516
-rw-r--r--chromium/tools/gn/command_format.cc1119
-rw-r--r--chromium/tools/gn/command_format.h27
-rw-r--r--chromium/tools/gn/command_format_unittest.cc108
-rw-r--r--chromium/tools/gn/command_gen.cc477
-rw-r--r--chromium/tools/gn/command_help.cc316
-rw-r--r--chromium/tools/gn/command_ls.cc112
-rw-r--r--chromium/tools/gn/command_path.cc415
-rw-r--r--chromium/tools/gn/command_refs.cc501
-rw-r--r--chromium/tools/gn/commands.cc568
-rw-r--r--chromium/tools/gn/commands.h201
-rw-r--r--chromium/tools/gn/config.cc50
-rw-r--r--chromium/tools/gn/config.h71
-rw-r--r--chromium/tools/gn/config_unittest.cc85
-rw-r--r--chromium/tools/gn/config_values.cc46
-rw-r--r--chromium/tools/gn/config_values.h98
-rw-r--r--chromium/tools/gn/config_values_extractors.cc35
-rw-r--r--chromium/tools/gn/config_values_extractors.h107
-rw-r--r--chromium/tools/gn/config_values_extractors_unittest.cc138
-rw-r--r--chromium/tools/gn/config_values_generator.cc128
-rw-r--r--chromium/tools/gn/config_values_generator.h45
-rw-r--r--chromium/tools/gn/copy_target_generator.cc43
-rw-r--r--chromium/tools/gn/copy_target_generator.h28
-rw-r--r--chromium/tools/gn/create_bundle_target_generator.cc301
-rw-r--r--chromium/tools/gn/create_bundle_target_generator.h45
-rw-r--r--chromium/tools/gn/deps_iterator.cc55
-rw-r--r--chromium/tools/gn/deps_iterator.h72
-rw-r--r--chromium/tools/gn/desc_builder.cc729
-rw-r--r--chromium/tools/gn/desc_builder.h27
-rw-r--r--chromium/tools/gn/docs/cross_compiles.md125
-rw-r--r--chromium/tools/gn/docs/faq.md52
-rw-r--r--chromium/tools/gn/docs/hacking.md23
-rw-r--r--chromium/tools/gn/docs/language.md540
-rw-r--r--chromium/tools/gn/docs/quick_start.md365
-rw-r--r--chromium/tools/gn/docs/reference.md6405
-rw-r--r--chromium/tools/gn/docs/standalone.md44
-rw-r--r--chromium/tools/gn/docs/style_guide.md286
-rw-r--r--chromium/tools/gn/docs/update_binaries.md5
-rw-r--r--chromium/tools/gn/eclipse_writer.cc172
-rw-r--r--chromium/tools/gn/eclipse_writer.h67
-rw-r--r--chromium/tools/gn/err.cc202
-rw-r--r--chromium/tools/gn/err.h99
-rw-r--r--chromium/tools/gn/escape.cc202
-rw-r--r--chromium/tools/gn/escape.h80
-rw-r--r--chromium/tools/gn/escape_unittest.cc64
-rw-r--r--chromium/tools/gn/example/.gn2
-rw-r--r--chromium/tools/gn/example/BUILD.gn30
-rw-r--r--chromium/tools/gn/example/README.txt4
-rw-r--r--chromium/tools/gn/example/build/BUILD.gn19
-rw-r--r--chromium/tools/gn/example/build/BUILDCONFIG.gn38
-rw-r--r--chromium/tools/gn/example/build/toolchain/BUILD.gn86
-rw-r--r--chromium/tools/gn/example/hello.cc13
-rw-r--r--chromium/tools/gn/example/hello_shared.cc9
-rw-r--r--chromium/tools/gn/example/hello_shared.h32
-rw-r--r--chromium/tools/gn/example/hello_static.cc9
-rw-r--r--chromium/tools/gn/example/hello_static.h10
-rw-r--r--chromium/tools/gn/exec_process.cc260
-rw-r--r--chromium/tools/gn/exec_process.h25
-rw-r--r--chromium/tools/gn/exec_process_unittest.cc131
-rw-r--r--chromium/tools/gn/filesystem_utils.cc1063
-rw-r--r--chromium/tools/gn/filesystem_utils.h304
-rw-r--r--chromium/tools/gn/filesystem_utils_unittest.cc850
-rw-r--r--chromium/tools/gn/format_test_data/001.gn2
-rw-r--r--chromium/tools/gn/format_test_data/001.golden3
-rw-r--r--chromium/tools/gn/format_test_data/002.gn6
-rw-r--r--chromium/tools/gn/format_test_data/002.golden6
-rw-r--r--chromium/tools/gn/format_test_data/003.gn10
-rw-r--r--chromium/tools/gn/format_test_data/003.golden10
-rw-r--r--chromium/tools/gn/format_test_data/004.gn10
-rw-r--r--chromium/tools/gn/format_test_data/004.golden13
-rw-r--r--chromium/tools/gn/format_test_data/005.gn5
-rw-r--r--chromium/tools/gn/format_test_data/005.golden5
-rw-r--r--chromium/tools/gn/format_test_data/006.gn9
-rw-r--r--chromium/tools/gn/format_test_data/006.golden5
-rw-r--r--chromium/tools/gn/format_test_data/007.gn9
-rw-r--r--chromium/tools/gn/format_test_data/007.golden11
-rw-r--r--chromium/tools/gn/format_test_data/008.gn1
-rw-r--r--chromium/tools/gn/format_test_data/008.golden5
-rw-r--r--chromium/tools/gn/format_test_data/009.gn2
-rw-r--r--chromium/tools/gn/format_test_data/009.golden9
-rw-r--r--chromium/tools/gn/format_test_data/010.gn2
-rw-r--r--chromium/tools/gn/format_test_data/010.golden9
-rw-r--r--chromium/tools/gn/format_test_data/011.gn4
-rw-r--r--chromium/tools/gn/format_test_data/011.golden13
-rw-r--r--chromium/tools/gn/format_test_data/012.gn16
-rw-r--r--chromium/tools/gn/format_test_data/012.golden22
-rw-r--r--chromium/tools/gn/format_test_data/013.gn7
-rw-r--r--chromium/tools/gn/format_test_data/013.golden7
-rw-r--r--chromium/tools/gn/format_test_data/014.gn6
-rw-r--r--chromium/tools/gn/format_test_data/014.golden5
-rw-r--r--chromium/tools/gn/format_test_data/015.gn4
-rw-r--r--chromium/tools/gn/format_test_data/015.golden6
-rw-r--r--chromium/tools/gn/format_test_data/016.gn1
-rw-r--r--chromium/tools/gn/format_test_data/016.golden1
-rw-r--r--chromium/tools/gn/format_test_data/017.gn15
-rw-r--r--chromium/tools/gn/format_test_data/017.golden16
-rw-r--r--chromium/tools/gn/format_test_data/018.gn3
-rw-r--r--chromium/tools/gn/format_test_data/018.golden3
-rw-r--r--chromium/tools/gn/format_test_data/019.gn23
-rw-r--r--chromium/tools/gn/format_test_data/019.golden23
-rw-r--r--chromium/tools/gn/format_test_data/020.gn5
-rw-r--r--chromium/tools/gn/format_test_data/020.golden5
-rw-r--r--chromium/tools/gn/format_test_data/021.gn33
-rw-r--r--chromium/tools/gn/format_test_data/021.golden61
-rw-r--r--chromium/tools/gn/format_test_data/022.gn6
-rw-r--r--chromium/tools/gn/format_test_data/022.golden6
-rw-r--r--chromium/tools/gn/format_test_data/023.gn38
-rw-r--r--chromium/tools/gn/format_test_data/023.golden88
-rw-r--r--chromium/tools/gn/format_test_data/024.gn1
-rw-r--r--chromium/tools/gn/format_test_data/024.golden2
-rw-r--r--chromium/tools/gn/format_test_data/025.gn5
-rw-r--r--chromium/tools/gn/format_test_data/025.golden9
-rw-r--r--chromium/tools/gn/format_test_data/026.gn6
-rw-r--r--chromium/tools/gn/format_test_data/026.golden7
-rw-r--r--chromium/tools/gn/format_test_data/027.gn3
-rw-r--r--chromium/tools/gn/format_test_data/027.golden5
-rw-r--r--chromium/tools/gn/format_test_data/028.gn9
-rw-r--r--chromium/tools/gn/format_test_data/028.golden7
-rw-r--r--chromium/tools/gn/format_test_data/029.gn9
-rw-r--r--chromium/tools/gn/format_test_data/029.golden9
-rw-r--r--chromium/tools/gn/format_test_data/030.gn12
-rw-r--r--chromium/tools/gn/format_test_data/030.golden12
-rw-r--r--chromium/tools/gn/format_test_data/031.gn8
-rw-r--r--chromium/tools/gn/format_test_data/031.golden8
-rw-r--r--chromium/tools/gn/format_test_data/032.gn6
-rw-r--r--chromium/tools/gn/format_test_data/032.golden7
-rw-r--r--chromium/tools/gn/format_test_data/033.gn8
-rw-r--r--chromium/tools/gn/format_test_data/033.golden8
-rw-r--r--chromium/tools/gn/format_test_data/034.gn13
-rw-r--r--chromium/tools/gn/format_test_data/035.gn1
-rw-r--r--chromium/tools/gn/format_test_data/035.golden1
-rw-r--r--chromium/tools/gn/format_test_data/036.gn9
-rw-r--r--chromium/tools/gn/format_test_data/036.golden9
-rw-r--r--chromium/tools/gn/format_test_data/037.gn5
-rw-r--r--chromium/tools/gn/format_test_data/037.golden6
-rw-r--r--chromium/tools/gn/format_test_data/038.gn4
-rw-r--r--chromium/tools/gn/format_test_data/038.golden3
-rw-r--r--chromium/tools/gn/format_test_data/039.gn6
-rw-r--r--chromium/tools/gn/format_test_data/039.golden4
-rw-r--r--chromium/tools/gn/format_test_data/040.gn9
-rw-r--r--chromium/tools/gn/format_test_data/041.gn12
-rw-r--r--chromium/tools/gn/format_test_data/041.golden12
-rw-r--r--chromium/tools/gn/format_test_data/042.gn44
-rw-r--r--chromium/tools/gn/format_test_data/042.golden110
-rw-r--r--chromium/tools/gn/format_test_data/043.gn6
-rw-r--r--chromium/tools/gn/format_test_data/043.golden7
-rw-r--r--chromium/tools/gn/format_test_data/044.gn10
-rw-r--r--chromium/tools/gn/format_test_data/044.golden11
-rw-r--r--chromium/tools/gn/format_test_data/045.gn10
-rw-r--r--chromium/tools/gn/format_test_data/045.golden14
-rw-r--r--chromium/tools/gn/format_test_data/046.gn22
-rw-r--r--chromium/tools/gn/format_test_data/046.golden19
-rw-r--r--chromium/tools/gn/format_test_data/047.gn7
-rw-r--r--chromium/tools/gn/format_test_data/047.golden10
-rw-r--r--chromium/tools/gn/format_test_data/048.gn19
-rw-r--r--chromium/tools/gn/format_test_data/048.golden19
-rw-r--r--chromium/tools/gn/format_test_data/049.gn14
-rw-r--r--chromium/tools/gn/format_test_data/050.gn10
-rw-r--r--chromium/tools/gn/format_test_data/050.golden27
-rw-r--r--chromium/tools/gn/format_test_data/051.gn6
-rw-r--r--chromium/tools/gn/format_test_data/051.golden7
-rw-r--r--chromium/tools/gn/format_test_data/052.gn11
-rw-r--r--chromium/tools/gn/format_test_data/052.golden12
-rw-r--r--chromium/tools/gn/format_test_data/053.gn7
-rw-r--r--chromium/tools/gn/format_test_data/053.golden8
-rw-r--r--chromium/tools/gn/format_test_data/054.gn7
-rw-r--r--chromium/tools/gn/format_test_data/054.golden8
-rw-r--r--chromium/tools/gn/format_test_data/055.gn10
-rw-r--r--chromium/tools/gn/format_test_data/055.golden11
-rw-r--r--chromium/tools/gn/format_test_data/056.gn45
-rw-r--r--chromium/tools/gn/format_test_data/056.golden45
-rw-r--r--chromium/tools/gn/format_test_data/057.gn24
-rw-r--r--chromium/tools/gn/format_test_data/057.golden24
-rw-r--r--chromium/tools/gn/format_test_data/058.gn2
-rw-r--r--chromium/tools/gn/format_test_data/058.golden2
-rw-r--r--chromium/tools/gn/format_test_data/059.gn10
-rw-r--r--chromium/tools/gn/format_test_data/059.golden11
-rw-r--r--chromium/tools/gn/format_test_data/060.gn2
-rw-r--r--chromium/tools/gn/format_test_data/060.golden2
-rw-r--r--chromium/tools/gn/format_test_data/061.gn9
-rw-r--r--chromium/tools/gn/format_test_data/061.golden9
-rw-r--r--chromium/tools/gn/format_test_data/062.gn122
-rw-r--r--chromium/tools/gn/format_test_data/062.golden132
-rw-r--r--chromium/tools/gn/format_test_data/063.gn36
-rw-r--r--chromium/tools/gn/format_test_data/063.golden36
-rw-r--r--chromium/tools/gn/format_test_data/064.gn3
-rw-r--r--chromium/tools/gn/format_test_data/064.golden5
-rw-r--r--chromium/tools/gn/format_test_data/065.gn4
-rw-r--r--chromium/tools/gn/format_test_data/065.golden8
-rw-r--r--chromium/tools/gn/format_test_data/066.gn30
-rw-r--r--chromium/tools/gn/format_test_data/066.golden28
-rw-r--r--chromium/tools/gn/format_test_data/067.gn8
-rw-r--r--chromium/tools/gn/format_test_data/067.golden17
-rw-r--r--chromium/tools/gn/format_test_data/068.gn3
-rw-r--r--chromium/tools/gn/format_test_data/068.golden3
-rw-r--r--chromium/tools/gn/format_test_data/069.gn3
-rw-r--r--chromium/tools/gn/format_test_data/069.golden5
-rw-r--r--chromium/tools/gn/format_test_data/070.gn15
-rw-r--r--chromium/tools/gn/format_test_data/070.golden14
-rw-r--r--chromium/tools/gn/function_exec_script.cc271
-rw-r--r--chromium/tools/gn/function_foreach.cc113
-rw-r--r--chromium/tools/gn/function_foreach_unittest.cc100
-rw-r--r--chromium/tools/gn/function_forward_variables_from.cc241
-rw-r--r--chromium/tools/gn/function_forward_variables_from_unittest.cc244
-rw-r--r--chromium/tools/gn/function_get_label_info.cc144
-rw-r--r--chromium/tools/gn/function_get_label_info_unittest.cc107
-rw-r--r--chromium/tools/gn/function_get_path_info.cc250
-rw-r--r--chromium/tools/gn/function_get_path_info_unittest.cc120
-rw-r--r--chromium/tools/gn/function_get_target_outputs.cc141
-rw-r--r--chromium/tools/gn/function_get_target_outputs_unittest.cc110
-rw-r--r--chromium/tools/gn/function_process_file_template.cc115
-rw-r--r--chromium/tools/gn/function_process_file_template_unittest.cc64
-rw-r--r--chromium/tools/gn/function_read_file.cc79
-rw-r--r--chromium/tools/gn/function_rebase_path.cc295
-rw-r--r--chromium/tools/gn/function_rebase_path_unittest.cc181
-rw-r--r--chromium/tools/gn/function_set_default_toolchain.cc86
-rw-r--r--chromium/tools/gn/function_set_defaults.cc76
-rw-r--r--chromium/tools/gn/function_template.cc227
-rw-r--r--chromium/tools/gn/function_template_unittest.cc29
-rw-r--r--chromium/tools/gn/function_toolchain.cc1099
-rw-r--r--chromium/tools/gn/function_toolchain_unittest.cc60
-rw-r--r--chromium/tools/gn/function_write_file.cc103
-rw-r--r--chromium/tools/gn/function_write_file_unittest.cc93
-rw-r--r--chromium/tools/gn/functions.cc1296
-rw-r--r--chromium/tools/gn/functions.h512
-rw-r--r--chromium/tools/gn/functions_target.cc797
-rw-r--r--chromium/tools/gn/functions_target_unittest.cc124
-rw-r--r--chromium/tools/gn/functions_unittest.cc172
-rw-r--r--chromium/tools/gn/gn_main.cc144
-rw-r--r--chromium/tools/gn/group_target_generator.cc24
-rw-r--r--chromium/tools/gn/group_target_generator.h27
-rw-r--r--chromium/tools/gn/header_checker.cc600
-rw-r--r--chromium/tools/gn/header_checker.h198
-rw-r--r--chromium/tools/gn/header_checker_unittest.cc382
-rw-r--r--chromium/tools/gn/import_manager.cc157
-rw-r--r--chromium/tools/gn/import_manager.h53
-rw-r--r--chromium/tools/gn/inherited_libraries.cc74
-rw-r--r--chromium/tools/gn/inherited_libraries.h71
-rw-r--r--chromium/tools/gn/inherited_libraries_unittest.cc135
-rw-r--r--chromium/tools/gn/input_conversion.cc324
-rw-r--r--chromium/tools/gn/input_conversion.h30
-rw-r--r--chromium/tools/gn/input_conversion_unittest.cc274
-rw-r--r--chromium/tools/gn/input_file.cc30
-rw-r--r--chromium/tools/gn/input_file.h65
-rw-r--r--chromium/tools/gn/input_file_manager.cc323
-rw-r--r--chromium/tools/gn/input_file_manager.h155
-rw-r--r--chromium/tools/gn/item.cc60
-rw-r--r--chromium/tools/gn/item.h82
-rw-r--r--chromium/tools/gn/json_project_writer.cc220
-rw-r--r--chromium/tools/gn/json_project_writer.h26
-rw-r--r--chromium/tools/gn/label.cc332
-rw-r--r--chromium/tools/gn/label.h128
-rw-r--r--chromium/tools/gn/label_pattern.cc276
-rw-r--r--chromium/tools/gn/label_pattern.h80
-rw-r--r--chromium/tools/gn/label_pattern_unittest.cc86
-rw-r--r--chromium/tools/gn/label_ptr.h117
-rw-r--r--chromium/tools/gn/label_unittest.cc95
-rw-r--r--chromium/tools/gn/last_commit_position.py100
-rw-r--r--chromium/tools/gn/lib_file.cc30
-rw-r--r--chromium/tools/gn/lib_file.h58
-rw-r--r--chromium/tools/gn/loader.cc429
-rw-r--r--chromium/tools/gn/loader.h182
-rw-r--r--chromium/tools/gn/loader_unittest.cc264
-rw-r--r--chromium/tools/gn/location.cc77
-rw-r--r--chromium/tools/gn/location.h61
-rw-r--r--chromium/tools/gn/misc/OWNERS2
-rw-r--r--chromium/tools/gn/misc/emacs/gn-mode.el191
-rw-r--r--chromium/tools/gn/misc/tm/GN.tmLanguage102
-rw-r--r--chromium/tools/gn/misc/tm/GN.tmPreferences22
-rw-r--r--chromium/tools/gn/misc/vim/README.chromium5
-rw-r--r--chromium/tools/gn/misc/vim/autoload/gn.vim26
-rw-r--r--chromium/tools/gn/misc/vim/ftdetect/gnfiletype.vim27
-rw-r--r--chromium/tools/gn/misc/vim/ftplugin/gn.vim12
-rw-r--r--chromium/tools/gn/misc/vim/syntax/gn.vim84
-rw-r--r--chromium/tools/gn/ninja_action_target_writer.cc239
-rw-r--r--chromium/tools/gn/ninja_action_target_writer.h63
-rw-r--r--chromium/tools/gn/ninja_action_target_writer_unittest.cc485
-rw-r--r--chromium/tools/gn/ninja_binary_target_writer.cc1090
-rw-r--r--chromium/tools/gn/ninja_binary_target_writer.h160
-rw-r--r--chromium/tools/gn/ninja_binary_target_writer_unittest.cc1125
-rw-r--r--chromium/tools/gn/ninja_build_writer.cc594
-rw-r--r--chromium/tools/gn/ninja_build_writer.h72
-rw-r--r--chromium/tools/gn/ninja_build_writer_unittest.cc154
-rw-r--r--chromium/tools/gn/ninja_bundle_data_target_writer.cc33
-rw-r--r--chromium/tools/gn/ninja_bundle_data_target_writer.h23
-rw-r--r--chromium/tools/gn/ninja_bundle_data_target_writer_unittest.cc53
-rw-r--r--chromium/tools/gn/ninja_copy_target_writer.cc119
-rw-r--r--chromium/tools/gn/ninja_copy_target_writer.h27
-rw-r--r--chromium/tools/gn/ninja_copy_target_writer_unittest.cc94
-rw-r--r--chromium/tools/gn/ninja_create_bundle_target_writer.cc332
-rw-r--r--chromium/tools/gn/ninja_create_bundle_target_writer.h71
-rw-r--r--chromium/tools/gn/ninja_create_bundle_target_writer_unittest.cc457
-rw-r--r--chromium/tools/gn/ninja_group_target_writer.cc33
-rw-r--r--chromium/tools/gn/ninja_group_target_writer.h23
-rw-r--r--chromium/tools/gn/ninja_group_target_writer_unittest.cc50
-rw-r--r--chromium/tools/gn/ninja_target_writer.cc330
-rw-r--r--chromium/tools/gn/ninja_target_writer.h72
-rw-r--r--chromium/tools/gn/ninja_target_writer_unittest.cc164
-rw-r--r--chromium/tools/gn/ninja_toolchain_writer.cc128
-rw-r--r--chromium/tools/gn/ninja_toolchain_writer.h58
-rw-r--r--chromium/tools/gn/ninja_toolchain_writer_unittest.cc25
-rw-r--r--chromium/tools/gn/ninja_utils.cc29
-rw-r--r--chromium/tools/gn/ninja_utils.h25
-rw-r--r--chromium/tools/gn/ninja_writer.cc55
-rw-r--r--chromium/tools/gn/ninja_writer.h51
-rw-r--r--chromium/tools/gn/operators.cc783
-rw-r--r--chromium/tools/gn/operators.h25
-rw-r--r--chromium/tools/gn/operators_unittest.cc390
-rw-r--r--chromium/tools/gn/ordered_set.h71
-rw-r--r--chromium/tools/gn/output_file.cc50
-rw-r--r--chromium/tools/gn/output_file.h66
-rw-r--r--chromium/tools/gn/parse_node_value_adapter.cc45
-rw-r--r--chromium/tools/gn/parse_node_value_adapter.h55
-rw-r--r--chromium/tools/gn/parse_tree.cc859
-rw-r--r--chromium/tools/gn/parse_tree.h546
-rw-r--r--chromium/tools/gn/parse_tree_unittest.cc255
-rw-r--r--chromium/tools/gn/parser.cc884
-rw-r--r--chromium/tools/gn/parser.h149
-rw-r--r--chromium/tools/gn/parser_fuzzer.cc71
-rw-r--r--chromium/tools/gn/parser_unittest.cc744
-rw-r--r--chromium/tools/gn/path_output.cc171
-rw-r--r--chromium/tools/gn/path_output.h91
-rw-r--r--chromium/tools/gn/path_output_unittest.cc284
-rw-r--r--chromium/tools/gn/pattern.cc190
-rw-r--r--chromium/tools/gn/pattern.h92
-rw-r--r--chromium/tools/gn/pattern_unittest.cc64
-rw-r--r--chromium/tools/gn/pool.cc45
-rw-r--r--chromium/tools/gn/pool.h41
-rw-r--r--chromium/tools/gn/qt_creator_writer.cc176
-rw-r--r--chromium/tools/gn/qt_creator_writer.h56
-rw-r--r--chromium/tools/gn/runtime_deps.cc314
-rw-r--r--chromium/tools/gn/runtime_deps.h28
-rw-r--r--chromium/tools/gn/runtime_deps_unittest.cc448
-rw-r--r--chromium/tools/gn/scheduler.cc199
-rw-r--r--chromium/tools/gn/scheduler.h146
-rw-r--r--chromium/tools/gn/scope.cc576
-rw-r--r--chromium/tools/gn/scope.h397
-rw-r--r--chromium/tools/gn/scope_per_file_provider.cc119
-rw-r--r--chromium/tools/gn/scope_per_file_provider.h51
-rw-r--r--chromium/tools/gn/scope_per_file_provider_unittest.cc55
-rw-r--r--chromium/tools/gn/scope_unittest.cc336
-rw-r--r--chromium/tools/gn/settings.cc34
-rw-r--r--chromium/tools/gn/settings.h120
-rw-r--r--chromium/tools/gn/setup.cc818
-rw-r--r--chromium/tools/gn/setup.h173
-rw-r--r--chromium/tools/gn/source_dir.cc159
-rw-r--r--chromium/tools/gn/source_dir.h163
-rw-r--r--chromium/tools/gn/source_dir_unittest.cc187
-rw-r--r--chromium/tools/gn/source_file.cc65
-rw-r--r--chromium/tools/gn/source_file.h109
-rw-r--r--chromium/tools/gn/source_file_type.cc34
-rw-r--r--chromium/tools/gn/source_file_type.h31
-rw-r--r--chromium/tools/gn/source_file_unittest.cc19
-rw-r--r--chromium/tools/gn/standard_out.cc335
-rw-r--r--chromium/tools/gn/standard_out.h41
-rw-r--r--chromium/tools/gn/string_utils.cc345
-rw-r--r--chromium/tools/gn/string_utils.h53
-rw-r--r--chromium/tools/gn/string_utils_unittest.cc157
-rw-r--r--chromium/tools/gn/substitution_list.cc70
-rw-r--r--chromium/tools/gn/substitution_list.h47
-rw-r--r--chromium/tools/gn/substitution_pattern.cc149
-rw-r--r--chromium/tools/gn/substitution_pattern.h78
-rw-r--r--chromium/tools/gn/substitution_pattern_unittest.cc49
-rw-r--r--chromium/tools/gn/substitution_type.cc264
-rw-r--r--chromium/tools/gn/substitution_type.h144
-rw-r--r--chromium/tools/gn/substitution_writer.cc608
-rw-r--r--chromium/tools/gn/substitution_writer.h254
-rw-r--r--chromium/tools/gn/substitution_writer_unittest.cc337
-rw-r--r--chromium/tools/gn/switches.cc290
-rw-r--r--chromium/tools/gn/switches.h107
-rw-r--r--chromium/tools/gn/target.cc874
-rw-r--r--chromium/tools/gn/target.h402
-rw-r--r--chromium/tools/gn/target_generator.cc392
-rw-r--r--chromium/tools/gn/target_generator.h84
-rw-r--r--chromium/tools/gn/target_unittest.cc1051
-rw-r--r--chromium/tools/gn/template.cc127
-rw-r--r--chromium/tools/gn/template.h67
-rw-r--r--chromium/tools/gn/template_unittest.cc93
-rw-r--r--chromium/tools/gn/test_with_scheduler.cc8
-rw-r--r--chromium/tools/gn/test_with_scheduler.h27
-rw-r--r--chromium/tools/gn/test_with_scope.cc222
-rw-r--r--chromium/tools/gn/test_with_scope.h120
-rw-r--r--chromium/tools/gn/token.cc28
-rw-r--r--chromium/tools/gn/token.h86
-rw-r--r--chromium/tools/gn/tokenizer.cc409
-rw-r--r--chromium/tools/gn/tokenizer.h90
-rw-r--r--chromium/tools/gn/tokenizer_unittest.cc228
-rw-r--r--chromium/tools/gn/tool.cc29
-rw-r--r--chromium/tools/gn/tool.h236
-rw-r--r--chromium/tools/gn/toolchain.cc180
-rw-r--r--chromium/tools/gn/toolchain.h146
-rw-r--r--chromium/tools/gn/trace.cc339
-rw-r--r--chromium/tools/gn/trace.h106
-rw-r--r--chromium/tools/gn/tutorial/hello.cc17
-rw-r--r--chromium/tools/gn/tutorial/hello.h14
-rw-r--r--chromium/tools/gn/tutorial/hello_world.cc10
-rw-r--r--chromium/tools/gn/tutorial/say_hello.cc14
-rw-r--r--chromium/tools/gn/unique_vector.h178
-rw-r--r--chromium/tools/gn/unique_vector_unittest.cc45
-rw-r--r--chromium/tools/gn/value.cc222
-rw-r--r--chromium/tools/gn/value.h135
-rw-r--r--chromium/tools/gn/value_extractors.cc257
-rw-r--r--chromium/tools/gn/value_extractors.h89
-rw-r--r--chromium/tools/gn/value_unittest.cc43
-rw-r--r--chromium/tools/gn/variables.cc2089
-rw-r--r--chromium/tools/gn/variables.h333
-rw-r--r--chromium/tools/gn/visibility.cc114
-rw-r--r--chromium/tools/gn/visibility.h68
-rw-r--r--chromium/tools/gn/visibility_unittest.cc53
-rw-r--r--chromium/tools/gn/visual_studio_utils.cc139
-rw-r--r--chromium/tools/gn/visual_studio_utils.h50
-rw-r--r--chromium/tools/gn/visual_studio_utils_unittest.cc103
-rw-r--r--chromium/tools/gn/visual_studio_writer.cc908
-rw-r--r--chromium/tools/gn/visual_studio_writer.h166
-rw-r--r--chromium/tools/gn/visual_studio_writer_unittest.cc165
-rw-r--r--chromium/tools/gn/xcode_object.cc990
-rw-r--r--chromium/tools/gn/xcode_object.h464
-rw-r--r--chromium/tools/gn/xcode_object_unittest.cc435
-rw-r--r--chromium/tools/gn/xcode_writer.cc664
-rw-r--r--chromium/tools/gn/xcode_writer.h89
-rw-r--r--chromium/tools/gn/xml_element_writer.cc114
-rw-r--r--chromium/tools/gn/xml_element_writer.h124
-rw-r--r--chromium/tools/gn/xml_element_writer_unittest.cc93
-rw-r--r--chromium/tools/grit/grit/format/chrome_messages_json.py2
-rwxr-xr-xchromium/tools/grit/grit/format/chrome_messages_json_unittest.py6
-rwxr-xr-xchromium/tools/grit/grit/format/html_inline.py7
-rwxr-xr-xchromium/tools/grit/grit/format/html_inline_unittest.py87
-rwxr-xr-xchromium/tools/grit/grit/gather/chrome_html.py1
-rwxr-xr-xchromium/tools/grit/grit/node/include.py1
-rwxr-xr-xchromium/tools/grit/grit/tool/build.py7
-rwxr-xr-xchromium/tools/grit/grit/tool/xmb.py2
-rwxr-xr-xchromium/tools/grit/grit_info.py2
-rw-r--r--chromium/tools/grit/grit_rule.gni17
-rw-r--r--chromium/tools/gritsettings/resource_ids42
-rw-r--r--chromium/tools/gritsettings/startup_resources_mac.txt1
-rw-r--r--chromium/tools/gritsettings/translation_expectations.pyl2
-rwxr-xr-xchromium/tools/idl_parser/idl_lexer.py2
-rwxr-xr-xchromium/tools/idl_parser/idl_parser.py21
-rw-r--r--chromium/tools/idl_parser/test_lexer/values.in1
-rw-r--r--chromium/tools/idl_parser/test_parser/interface_web.idl19
-rw-r--r--chromium/tools/imagediff/BUILD.gn1
-rwxr-xr-xchromium/tools/include_tracer.py126
-rw-r--r--chromium/tools/ipc_fuzzer/BUILD.gn5
-rw-r--r--chromium/tools/ipc_fuzzer/message_replay/BUILD.gn2
-rw-r--r--chromium/tools/ipc_fuzzer/message_replay/DEPS3
-rw-r--r--chromium/tools/ipc_fuzzer/message_replay/replay_process.cc57
-rw-r--r--chromium/tools/ipc_fuzzer/message_replay/replay_process.h12
-rw-r--r--chromium/tools/json_schema_compiler/feature_compiler.py48
-rw-r--r--chromium/tools/json_schema_compiler/js_externs_generator.py17
-rwxr-xr-xchromium/tools/json_schema_compiler/js_externs_generator_test.py81
-rw-r--r--chromium/tools/json_schema_compiler/js_interface_generator.py3
-rwxr-xr-xchromium/tools/json_schema_compiler/js_interface_generator_test.py4
-rw-r--r--chromium/tools/json_schema_compiler/js_util.py18
-rw-r--r--chromium/tools/json_schema_compiler/json_features.gni11
-rw-r--r--chromium/tools/json_schema_compiler/test/BUILD.gn2
-rw-r--r--chromium/tools/luci-go/OWNERS2
-rw-r--r--chromium/tools/luci-go/README.md7
-rw-r--r--chromium/tools/luci-go/linux64/isolate.sha12
-rw-r--r--chromium/tools/luci-go/mac64/isolate.sha12
-rw-r--r--chromium/tools/luci-go/win64/isolate.exe.sha12
-rwxr-xr-xchromium/tools/mb/mb.py16
-rw-r--r--chromium/tools/mb/mb_config.pyl289
-rw-r--r--chromium/tools/metrics/actions/README.md14
-rw-r--r--chromium/tools/metrics/actions/actions.xml1616
-rw-r--r--chromium/tools/metrics/histograms/README.md62
-rw-r--r--chromium/tools/metrics/histograms/enums.xml1872
-rw-r--r--chromium/tools/metrics/histograms/histograms.xml8547
-rw-r--r--chromium/tools/metrics/histograms/print_style.py13
-rw-r--r--chromium/tools/metrics/rappor/rappor.xml16
-rw-r--r--chromium/tools/metrics/ukm/ukm.xml542
-rw-r--r--chromium/tools/perf/clear_system_cache/BUILD.gn1
-rw-r--r--chromium/tools/perf/contrib/vr_benchmarks/BUILD.gn4
-rwxr-xr-xchromium/tools/polymer/generate_compiled_resources_gyp.py97
-rwxr-xr-xchromium/tools/resources/optimize-png-files.sh25
-rw-r--r--chromium/tools/traffic_annotation/auditor/BUILD.gn2
-rw-r--r--chromium/tools/traffic_annotation/auditor/README.md2
-rw-r--r--chromium/tools/traffic_annotation/auditor/traffic_annotation_exporter.cc5
-rw-r--r--chromium/tools/traffic_annotation/bin/README.md4
-rw-r--r--chromium/tools/traffic_annotation/bin/win32/traffic_annotation_auditor.exe.sha12
-rwxr-xr-xchromium/tools/traffic_annotation/scripts/traffic_annotation_auditor_tests.py39
-rw-r--r--chromium/tools/traffic_annotation/summary/annotations.xml33
-rw-r--r--chromium/tools/v8_context_snapshot/BUILD.gn2
-rw-r--r--chromium/tools/v8_context_snapshot/DEPS2
-rw-r--r--chromium/tools/v8_context_snapshot/v8_context_snapshot_generator.cc4
-rwxr-xr-xchromium/tools/valgrind/asan/third_party/asan_symbolize.py8
-rwxr-xr-xchromium/tools/variations/fieldtrial_to_struct.py73
-rw-r--r--chromium/tools/variations/fieldtrial_to_struct_unittest.py35
-rw-r--r--chromium/tools/variations/fieldtrial_util.py11
-rw-r--r--chromium/tools/variations/fieldtrial_util_unittest.py30
-rw-r--r--chromium/tools/variations/unittest_data/DEPS3
-rw-r--r--chromium/tools/variations/unittest_data/expected_output.cc25
-rw-r--r--chromium/tools/variations/unittest_data/expected_output.h3
-rw-r--r--chromium/tools/variations/unittest_data/test_config.json8
-rw-r--r--chromium/tools/win/ShowGlobals/ShowGlobals.cc11
-rw-r--r--chromium/tools/win/ShowGlobals/ShowGlobals.vcxproj10
-rw-r--r--chromium/tools/win/static_initializers/static_initializers.cc22
-rw-r--r--chromium/tools/xdisplaycheck/BUILD.gn4
657 files changed, 17884 insertions, 82786 deletions
diff --git a/chromium/tools/accessibility/inspect/README.md b/chromium/tools/accessibility/inspect/README.md
index af2ee4e969b..a4efc2a7410 100644
--- a/chromium/tools/accessibility/inspect/README.md
+++ b/chromium/tools/accessibility/inspect/README.md
@@ -1,9 +1,35 @@
-# ax_dump_events
+# Inspect tools
+
+Note: please see convenience scripts section, it makes the tools much easier to use.
+
+## ax_dump_events
This tool helps monitor accessibility events. It currently works on Windows,
and Mac is TBD.
-Events are currently dumped to the console. To use it, run
+Events are dumped to the console. To use it, run
`ax_dump_events --pid=[processid]`
-Press Ctrl+C to quit. \ No newline at end of file
+Press Ctrl+C to quit.
+
+## ax_dump_tree
+
+This tool helps monitor accessibility events. It currently works on Windows,
+and Mac is TBD.
+
+Events are dumped to the console. To use it, run
+`ax_dump_events --window=[hwnd]`
+
+Notes:
+* To use a hex window handle prefix it with `0x`.
+* For json output, use the `--json` option
+* To filter certain properties, use `--filters=[path-to-filters.txt]` where the filters text file has a series of `@ALLOW` and/or `@DENY` lines. See example-tree-filters.txt in tools/accessibility/inspect.
+
+## Convenience PowerShell scripts
+
+Run these scripts to avoid the difficulty of looking up the process id or window handle you want to inspect.
+Sometimes there may be several windows open for the given app, and disambuation. In this case, after you run the script, it will list top level windows/processes and ask you to re-run with an argument that includes a substring from the window title you want to inspect the tree/events for. For example, `chrome-tree live` will inspect a tab with the name "Live region tests" (the title matcher is case insensitive).
+
+* chrome-tree and chrome-events for official Google Chrome (has 'Google Chrome' in the window title)
+* chromium-tree and chromium-events for Chrome you built yourself (has 'Chromium' in the window title)
+* ff-tree and ff-events for Firefox
diff --git a/chromium/tools/accessibility/inspect/ax_dump_events.cc b/chromium/tools/accessibility/inspect/ax_dump_events.cc
index fbd77a23f79..c111eecaae3 100644
--- a/chromium/tools/accessibility/inspect/ax_dump_events.cc
+++ b/chromium/tools/accessibility/inspect/ax_dump_events.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <iostream>
#include <string>
#include "base/at_exit.h"
@@ -35,6 +36,8 @@ int main(int argc, char** argv) {
std::unique_ptr<content::AXEventServer> server(
new content::AXEventServer(pid));
}
+ } else {
+ std::cout << "* Error: No process id provided via --pid=[process-id].";
}
return 0;
diff --git a/chromium/tools/accessibility/inspect/ax_dump_tree.cc b/chromium/tools/accessibility/inspect/ax_dump_tree.cc
index 7eb549a89e6..4888634ea3d 100644
--- a/chromium/tools/accessibility/inspect/ax_dump_tree.cc
+++ b/chromium/tools/accessibility/inspect/ax_dump_tree.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <iostream>
#include <string>
#include "base/at_exit.h"
@@ -9,7 +10,6 @@
#include "base/strings/string_number_conversions.h"
#include "tools/accessibility/inspect/ax_tree_server.h"
-char kPidSwitch[] = "pid";
char kWindowSwitch[] = "window";
char kFiltersSwitch[] = "filters";
char kJsonSwitch[] = "json";
@@ -48,16 +48,9 @@ int main(int argc, char** argv) {
new content::AXTreeServer(widget, filters_path, use_json));
return 0;
}
- }
- std::string pid_str =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kPidSwitch);
- if (!pid_str.empty()) {
- int pid;
- if (StringToInt(pid_str, &pid)) {
- base::ProcessId process_id = static_cast<base::ProcessId>(pid);
- std::unique_ptr<content::AXTreeServer> server(
- new content::AXTreeServer(process_id, filters_path, use_json));
- }
+ } else {
+ std::cout
+ << "* Error: No window handle provided via --window=[window-handle].";
}
return 0;
}
diff --git a/chromium/tools/accessibility/inspect/ax_tree_server.cc b/chromium/tools/accessibility/inspect/ax_tree_server.cc
index 89d0501f281..7cfcf97b6c2 100644
--- a/chromium/tools/accessibility/inspect/ax_tree_server.cc
+++ b/chromium/tools/accessibility/inspect/ax_tree_server.cc
@@ -35,7 +35,7 @@ AXTreeServer::AXTreeServer(base::ProcessId pid,
formatter->BuildAccessibilityTreeForProcess(pid);
if (!dict) {
- std::cout << "Failed to get accessibility tree";
+ std::cout << "Error: Failed to get accessibility tree";
return;
}
diff --git a/chromium/tools/accessibility/inspect/chrome-events.ps1 b/chromium/tools/accessibility/inspect/chrome-events.ps1
new file mode 100644
index 00000000000..a43c726a8f4
--- /dev/null
+++ b/chromium/tools/accessibility/inspect/chrome-events.ps1
@@ -0,0 +1,12 @@
+# Powershell script to dump accessibility events for Chrome. Takes optional first argument with part of window title to disambiguate the desired process.
+$all = ps | where {$_.ProcessName -eq 'chrome'} |where MainWindowTitle -like "*$($args[0])*chrome" | select id, MainWindowTitle
+echo $all
+echo ""
+If (@($all).length -gt 1) {
+ echo "Multiple matching processes, please disambuate: include part of the desired window's title as a first argument."
+ exit
+}
+$id = ps | where {$_.ProcessName -eq 'chrome'} | where MainWindowTitle -like "*$($args[0])*chrome*" | select id -ExpandProperty id | Out-String
+$id_arg = "--pid=" + $id
+$exe = ".\ax_dump_events.exe"
+& $exe $id_arg
diff --git a/chromium/tools/accessibility/inspect/chrome-tree.ps1 b/chromium/tools/accessibility/inspect/chrome-tree.ps1
new file mode 100644
index 00000000000..c0bb8a709f0
--- /dev/null
+++ b/chromium/tools/accessibility/inspect/chrome-tree.ps1
@@ -0,0 +1,13 @@
+# Powershell script to dump accessibility tree for Chrome. Takes optional first argument with part of window title to disambiguate the desired window.
+$all = ps | where {$_.ProcessName -eq 'chrome'} |where MainWindowTitle -like "*$($args[0])*Google Chrome" | select MainWindowHandle, MainWindowTitle
+echo $all
+echo ""
+If (@($all).length -gt 1) {
+ echo "Multiple matching windows, please disambuate: include part of the desired window's title as a first argument."
+ exit
+}
+
+$hwnd = Get-Process | Where-Object {$_.ProcessName -eq 'chrome'} | where MainWindowTitle -like "*$($args[0])*Google Chrome*" | select MainWindowHandle -ExpandProperty MainWindowHandle | Out-String
+$hwnd_arg = "--window=" + $hwnd
+$exe = ".\ax_dump_tree.exe"
+& $exe $hwnd_arg \ No newline at end of file
diff --git a/chromium/tools/accessibility/inspect/chromium-events.ps1 b/chromium/tools/accessibility/inspect/chromium-events.ps1
new file mode 100644
index 00000000000..ad1a8d6063e
--- /dev/null
+++ b/chromium/tools/accessibility/inspect/chromium-events.ps1
@@ -0,0 +1,12 @@
+# Powershell script to dump accessibility events for Chromium. Takes optional first argument with part of window title to disambiguate the desired process.
+$all = ps | where {$_.ProcessName -eq 'chrome'} |where MainWindowTitle -like "*$($args[0])*chromium" | select id, MainWindowTitle
+echo $all
+echo ""
+If (@($all).length -gt 1) {
+ echo "Multiple matching processes, please disambuate: include part of the desired window's title as a first argument."
+ exit
+}
+$id = ps | where {$_.ProcessName -eq 'chrome'} | where MainWindowTitle -like "*$($args[0])*chromium*" | select id -ExpandProperty id | Out-String
+$id_arg = "--pid=" + $id
+$exe = ".\ax_dump_events.exe"
+& $exe $id_arg
diff --git a/chromium/tools/accessibility/inspect/chromium-tree.ps1 b/chromium/tools/accessibility/inspect/chromium-tree.ps1
new file mode 100644
index 00000000000..8c77fff09c9
--- /dev/null
+++ b/chromium/tools/accessibility/inspect/chromium-tree.ps1
@@ -0,0 +1,13 @@
+# Powershell script to dump accessibility tree for Chromium. Takes optional first argument with part of window title to disambiguate the desired window.
+$all = ps | where {$_.ProcessName -eq 'chrome'} |where MainWindowTitle -like "*$($args[0])*Google Chrome" | select MainWindowHandle, MainWindowTitle
+echo $all
+echo ""
+If (@($all).length -gt 1) {
+ echo "Multiple matching windows, please disambuate: include part of the desired window's title as a first argument."
+ exit
+}
+
+$hwnd = Get-Process | where {$_.ProcessName -eq 'chrome'} | where MainWindowTitle -like "*$($args[0])*Chromium*" | select MainWindowHandle -ExpandProperty MainWindowHandle | Out-String
+$hwnd_arg = "--window=" + $hwnd
+$exe = ".\ax_dump_tree.exe"
+& $exe $hwnd_arg \ No newline at end of file
diff --git a/chromium/tools/accessibility/inspect/example-tree-filters.txt b/chromium/tools/accessibility/inspect/example-tree-filters.txt
new file mode 100644
index 00000000000..1a27b52bca6
--- /dev/null
+++ b/chromium/tools/accessibility/inspect/example-tree-filters.txt
@@ -0,0 +1,8 @@
+# Sample filters to use with ax_dump_tree, e.g. with --filters=[path-to-filters.txt]
+@ALLOW:role*
+@ALLOW:name*
+@ALLOW:rowtext*
+@ALLOW:coltext*
+@ALLOW:font*
+@DENY:font-family*
+@DENY:font-size*
diff --git a/chromium/tools/accessibility/inspect/ff-events.ps1 b/chromium/tools/accessibility/inspect/ff-events.ps1
new file mode 100644
index 00000000000..b6ecae3e9ff
--- /dev/null
+++ b/chromium/tools/accessibility/inspect/ff-events.ps1
@@ -0,0 +1,5 @@
+# Powershell script to dump entire accessibility tree for Firefox, all windows + tabs.
+$id = ps | where Processname -like firefox | where MainWindowTitle -like "*Firefox" | select id -ExpandProperty id | Out-String
+$id_arg = "--pid=" + $id
+$exe = ".\ax_dump_events.exe"
+& $exe $id_arg \ No newline at end of file
diff --git a/chromium/tools/accessibility/inspect/ff-tree.ps1 b/chromium/tools/accessibility/inspect/ff-tree.ps1
new file mode 100644
index 00000000000..999c239171c
--- /dev/null
+++ b/chromium/tools/accessibility/inspect/ff-tree.ps1
@@ -0,0 +1,5 @@
+# Powershell script to dump entire accessibility tree for Firefox, all windows + tabs.
+$hwnd = Get-Process | Where-Object {$_.ProcessName -eq 'firefox'} | where MainWindowTitle -like "*Firefox" | select MainWindowHandle -ExpandProperty MainWindowHandle | Out-String
+$hwnd_arg = "--window=" + $hwnd
+$exe = ".\ax_dump_tree.exe"
+& $exe $hwnd_arg \ No newline at end of file
diff --git a/chromium/tools/accessibility/rebase_dump_accessibility_tree_test.py b/chromium/tools/accessibility/rebase_dump_accessibility_tree_test.py
index bdcfaf325c2..92c7f3f2a50 100755
--- a/chromium/tools/accessibility/rebase_dump_accessibility_tree_test.py
+++ b/chromium/tools/accessibility/rebase_dump_accessibility_tree_test.py
@@ -111,18 +111,18 @@ def Run():
#print(json.dumps(data, indent=4))
for builder in data:
- #print builder['result']
+ print builder['builder_name'], builder['result']
if builder['result'] == 'FAILURE':
- url = builder['url']
- tokens = url.split('/')
- if len(tokens) < 9:
- continue
- bucket = tokens[4]
- platform = tokens[6]
- build = tokens[8]
- logdog_prefix = 'chromium/bb/%s/%s/%s' % (bucket, platform, build)
- logdog_steps = '%s/+/recipes/steps/**' % logdog_prefix
- logdog_query = 'cit logdog query -results 999 -path "%s"' % logdog_steps
+ logdog_tokens = [
+ 'chromium',
+ 'buildbucket',
+ 'cr-buildbucket.appspot.com',
+ builder['buildbucket_id'],
+ '+',
+ 'steps',
+ '**']
+ logdog_path = '/'.join(logdog_tokens)
+ logdog_query = 'cit logdog query -results 999 -path "%s"' % logdog_path
print (BRIGHT_COLOR + '=> %s' + NORMAL_COLOR) % logdog_query
steps = os.popen(logdog_query).readlines()
a11y_step = None
diff --git a/chromium/tools/android/BUILD.gn b/chromium/tools/android/BUILD.gn
index 3fdc092dea4..23279725c68 100644
--- a/chromium/tools/android/BUILD.gn
+++ b/chromium/tools/android/BUILD.gn
@@ -71,3 +71,10 @@ group("push_apps_to_background") {
"//tools/android/push_apps_to_background:push_apps_to_background_apk",
]
}
+
+group("io_benchmark") {
+ deps = [
+ "//tools/android/io_benchmark",
+ ]
+ testonly = true
+}
diff --git a/chromium/tools/android/forwarder2/BUILD.gn b/chromium/tools/android/forwarder2/BUILD.gn
index b674344d6dc..c77915a776b 100644
--- a/chromium/tools/android/forwarder2/BUILD.gn
+++ b/chromium/tools/android/forwarder2/BUILD.gn
@@ -43,7 +43,6 @@ if (current_toolchain == default_toolchain) {
]
deps = [
"//base",
- "//build/config:exe_and_shlib_deps",
"//tools/android/common",
]
data_deps = [
@@ -86,7 +85,6 @@ if (current_toolchain != default_toolchain) {
]
deps = [
"//base",
- "//build/config:exe_and_shlib_deps",
"//tools/android/common",
]
}
diff --git a/chromium/tools/android/io_benchmark/BUILD.gn b/chromium/tools/android/io_benchmark/BUILD.gn
new file mode 100644
index 00000000000..f8d406314a7
--- /dev/null
+++ b/chromium/tools/android/io_benchmark/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+executable("io_benchmark") {
+ sources = [
+ "io_benchmark.cc",
+ ]
+ deps = [
+ "//base",
+ "//base/test:test_support",
+ ]
+ testonly = true
+}
diff --git a/chromium/tools/android/md5sum/BUILD.gn b/chromium/tools/android/md5sum/BUILD.gn
index ef8e6db414e..36a81e08d49 100644
--- a/chromium/tools/android/md5sum/BUILD.gn
+++ b/chromium/tools/android/md5sum/BUILD.gn
@@ -21,15 +21,7 @@ executable("md5sum_bin") {
]
deps = [
"//base",
- "//build/config:exe_and_shlib_deps",
]
-
- # md5sum uses //base, and is built when chrome_apk is. As a consequence,
- # it references the instrumentation function, meaning that //tools/cygprofile
- # is required to link.
- if (is_android && use_order_profiling) {
- deps += [ "//tools/cygprofile" ]
- }
}
if (current_toolchain == default_toolchain) {
diff --git a/chromium/tools/android/memdump/BUILD.gn b/chromium/tools/android/memdump/BUILD.gn
index f047218b987..dafc7ec1d6f 100644
--- a/chromium/tools/android/memdump/BUILD.gn
+++ b/chromium/tools/android/memdump/BUILD.gn
@@ -8,6 +8,5 @@ executable("memdump") {
]
deps = [
"//base",
- "//build/config:exe_and_shlib_deps",
]
}
diff --git a/chromium/tools/battor_agent/BUILD.gn b/chromium/tools/battor_agent/BUILD.gn
index 5339b67f3ce..f1f9f17db32 100644
--- a/chromium/tools/battor_agent/BUILD.gn
+++ b/chromium/tools/battor_agent/BUILD.gn
@@ -14,7 +14,6 @@ executable("battor_agent") {
deps = [
":battor_agent_lib",
"//base",
- "//build/config:exe_and_shlib_deps",
"//build/win:default_exe_manifest",
]
}
diff --git a/chromium/tools/battor_agent/battor_connection_impl_unittest.cc b/chromium/tools/battor_agent/battor_connection_impl_unittest.cc
index 2ce35ca9cb4..eddce4d707e 100644
--- a/chromium/tools/battor_agent/battor_connection_impl_unittest.cc
+++ b/chromium/tools/battor_agent/battor_connection_impl_unittest.cc
@@ -201,7 +201,16 @@ TEST_F(BattOrConnectionImplTest, FlushConnectionSucceedsOnlyAfterTimeout) {
ASSERT_TRUE(GetFlushSuccess());
}
-TEST_F(BattOrConnectionImplTest, FlushConnectionFlushesAlreadyReadBuffer) {
+#if defined(ADDRESS_SANITIZER)
+// https://crbug.com/843729
+#define MAYBE_FlushConnectionFlushesAlreadyReadBuffer \
+ DISABLED_FlushConnectionFlushesAlreadyReadBuffer
+#else
+#define MAYBE_FlushConnectionFlushesAlreadyReadBuffer \
+ FlushConnectionFlushesAlreadyReadBuffer
+#endif
+TEST_F(BattOrConnectionImplTest,
+ MAYBE_FlushConnectionFlushesAlreadyReadBuffer) {
OpenConnection();
ASSERT_TRUE(IsOpenComplete());
ASSERT_TRUE(GetOpenSuccess());
@@ -263,8 +272,16 @@ TEST_F(BattOrConnectionImplTest, FlushConnectionNewBytesRestartQuietPeriod) {
ASSERT_TRUE(IsFlushComplete());
}
+#if defined(ADDRESS_SANITIZER)
+// https://crbug.com/843729
+#define MAYBE_FlushConnectionFlushesBytesReceivedInQuietPeriod \
+ DISABLED_FlushConnectionFlushesBytesReceivedInQuietPeriod
+#else
+#define MAYBE_FlushConnectionFlushesBytesReceivedInQuietPeriod \
+ FlushConnectionFlushesBytesReceivedInQuietPeriod
+#endif
TEST_F(BattOrConnectionImplTest,
- FlushConnectionFlushesBytesReceivedInQuietPeriod) {
+ MAYBE_FlushConnectionFlushesBytesReceivedInQuietPeriod) {
OpenConnection();
ASSERT_TRUE(IsOpenComplete());
ASSERT_TRUE(GetOpenSuccess());
@@ -311,7 +328,13 @@ TEST_F(BattOrConnectionImplTest, FlushConnectionFlushesMultipleReadsOfData) {
ASSERT_TRUE(GetReadSuccess());
}
-TEST_F(BattOrConnectionImplTest, FlushIncompleteBeforeTimeout) {
+#if defined(ADDRESS_SANITIZER)
+// https://crbug.com/843729
+#define MAYBE_FlushIncompleteBeforeTimeout DISABLED_FlushIncompleteBeforeTimeout
+#else
+#define MAYBE_FlushIncompleteBeforeTimeout FlushIncompleteBeforeTimeout
+#endif
+TEST_F(BattOrConnectionImplTest, MAYBE_FlushIncompleteBeforeTimeout) {
OpenConnection();
ASSERT_TRUE(IsOpenComplete());
ASSERT_TRUE(GetOpenSuccess());
diff --git a/chromium/tools/binary_size/BUILD.gn b/chromium/tools/binary_size/BUILD.gn
index fb3ded94fdb..55e574acba5 100644
--- a/chromium/tools/binary_size/BUILD.gn
+++ b/chromium/tools/binary_size/BUILD.gn
@@ -10,5 +10,6 @@ python_library("binary_size_trybot_py") {
pydeps_file = "supersize.pydeps"
data = [
"diagnose_bloat.py",
+ "trybot_commit_size_checker.py",
]
}
diff --git a/chromium/tools/binary_size/README.md b/chromium/tools/binary_size/README.md
index 8a98fe7b5d1..2d4ed3e38d5 100644
--- a/chromium/tools/binary_size/README.md
+++ b/chromium/tools/binary_size/README.md
@@ -232,16 +232,34 @@ tools/binary_size/supersize archive chrome.size --elf-file out/Release/chrome -v
Creates an interactive size breakdown (by source path) as a stand-alone html
report.
-Example output: https://agrieve.github.io/chrome/
+Example output: https://notwoods.github.io/chrome-supersize-reports/
Example Usage:
``` bash
-tools/binary_size/supersize html_report chrome.size --report-dir size-report -v
-xdg-open size-report/index.html
+# Creates the data file ./report.ndjson, generated based on ./chrome.size
+tools/binary_size/supersize html_report chrome.size --report-file report.ndjson -v
-# Report showing Dex method counts rather than binary size:
-tools/binary_size/supersize html_report chrome.size --report-dir size-report -v --method-count
+# Includes every symbol in the data file, although it will take longer to load.
+tools/binary_size/supersize html_report chrome.size --report-file report.ndjson --all-symbols
+
+# Create a data file showing a diff between two .size files.
+tools/binary_size/supersize html_report after.size --diff-with before.size --report-file report.ndjson
+```
+
+### Usage: start_server
+
+Locally view the data file generated by `html_report`, by starting a web server
+that links to a data file.
+
+Example Usage:
+
+``` bash
+# Starts a local server to view the data in ./report.ndjson
+tools/binary_size/supersize start_server report.ndjson
+
+# Set a custom address and port.
+tools/binary_size/supersize start_server report.ndjson -a localhost -p 8080
```
### Usage: diff
@@ -297,10 +315,6 @@ Example session:
1. More `console` features:
* Add `SplitByName()` - Like `GroupByName()`, but recursive.
* A canned query, that does what ShowGlobals does (as described in [Windows Binary Sizes](https://www.chromium.org/developers/windows-binary-sizes)).
-1. More `html_report` features:
- * Able to render size diffs (tint negative size red).
- * Break down by other groupings (Create from result of `SplitByName()`)
- * Render as simple tree view rather than 2d boxes
1. Integrate with `resource_sizes.py` so that it tracks size of major
components separately: chrome vs blink vs skia vs v8.
1. Add dependency graph info, perhaps just on a per-file basis.
diff --git a/chromium/tools/binary_size/diagnose_bloat.py b/chromium/tools/binary_size/diagnose_bloat.py
index ff201f38a58..ed69755367e 100755
--- a/chromium/tools/binary_size/diagnose_bloat.py
+++ b/chromium/tools/binary_size/diagnose_bloat.py
@@ -36,6 +36,10 @@ _DEFAULT_OUT_DIR = os.path.join(_SRC_ROOT, 'out', 'binary-size-build')
_BINARY_SIZE_DIR = os.path.join(_SRC_ROOT, 'tools', 'binary_size')
_RESOURCE_SIZES_PATH = os.path.join(
_SRC_ROOT, 'build', 'android', 'resource_sizes.py')
+_LLVM_TOOLS_DIR = os.path.join(
+ _SRC_ROOT, 'third_party', 'llvm-build', 'Release+Asserts', 'bin')
+_DOWNLOAD_OBJDUMP_PATH = os.path.join(
+ _SRC_ROOT, 'tools', 'clang', 'scripts', 'download_objdump.py')
_DiffResult = collections.namedtuple('DiffResult', ['name', 'value', 'units'])
@@ -62,7 +66,8 @@ class BaseDiff(object):
@property
def summary_stat(self):
- return None
+ """Returns a tuple of (name, value, units) for the most important metric."""
+ raise NotImplementedError()
def Summary(self):
"""A short description that summarizes the source of binary size bloat."""
@@ -85,7 +90,7 @@ class BaseDiff(object):
class NativeDiff(BaseDiff):
# E.g.: Section Sizes (Total=1.2 kb (1222 bytes)):
_RE_SUMMARY_STAT = re.compile(
- r'Section Sizes \(Total=(?P<value>\d+) ?(?P<units>\w+)')
+ r'Section Sizes \(Total=(?P<value>-?[0-9\.]+) ?(?P<units>\w+)')
_SUMMARY_STAT_NAME = 'Native Library Delta'
def __init__(self, size_name, supersize_path):
@@ -100,7 +105,7 @@ class NativeDiff(BaseDiff):
if m:
return _DiffResult(
NativeDiff._SUMMARY_STAT_NAME, m.group('value'), m.group('units'))
- return None
+ raise Exception('Could not extract total from:\n' + self._diff)
def DetailedResults(self):
return self._diff.splitlines()
@@ -116,8 +121,10 @@ class NativeDiff(BaseDiff):
class ResourceSizesDiff(BaseDiff):
+ # Ordered by output appearance.
_SUMMARY_SECTIONS = (
- 'Breakdown', 'Dex', 'Specifics', 'StaticInitializersCount')
+ 'Specifics', 'InstallSize', 'InstallBreakdown', 'Dex',
+ 'StaticInitializersCount')
# Sections where it makes sense to sum subsections into a section total.
_AGGREGATE_SECTIONS = (
'InstallBreakdown', 'Breakdown', 'MainLibInfo', 'Uncompressed')
@@ -135,13 +142,18 @@ class ResourceSizesDiff(BaseDiff):
if 'normalized' in subsection_name:
full_name = '{} {}'.format(section_name, subsection_name)
return _DiffResult(full_name, value, units)
- return None
+ raise Exception('Could not find "normalized" in: ' + repr(self._diff))
def DetailedResults(self):
return self._ResultLines()
def Summary(self):
- return self._ResultLines(
+ header_lines = [
+ 'For an explanation of these metrics, see:',
+ ('https://chromium.googlesource.com/chromium/src/+/master/docs/speed/'
+ 'binary_size/metrics.md#Metrics-for-Android'),
+ '']
+ return header_lines + self._ResultLines(
include_sections=ResourceSizesDiff._SUMMARY_SECTIONS)
def ProduceDiff(self, before_dir, after_dir):
@@ -165,7 +177,7 @@ class ResourceSizesDiff(BaseDiff):
def _ResultLines(self, include_sections=None):
"""Generates diff lines for the specified sections (defaults to all)."""
- ret = []
+ section_lines = collections.defaultdict(list)
for section_name, section_results in self._diff.iteritems():
section_no_target = re.sub(r'^.*_', '', section_name)
if not include_sections or section_no_target in include_sections:
@@ -177,16 +189,20 @@ class ResourceSizesDiff(BaseDiff):
if value == 0 and include_sections:
continue
section_sum += value
- subsection_lines.append('{:>+10,} {} {}'.format(value, units, name))
- section_header = section_name
+ subsection_lines.append('{:>+14,} {} {}'.format(value, units, name))
+ section_header = section_no_target
if section_no_target in ResourceSizesDiff._AGGREGATE_SECTIONS:
section_header += ' ({:+,} {})'.format(section_sum, units)
+ section_header += ':'
# Omit sections with empty subsections.
if subsection_lines:
- ret.append(section_header)
- ret.extend(subsection_lines)
- if not ret:
- ret = ['Empty ' + self.name]
+ section_lines[section_no_target].append(section_header)
+ section_lines[section_no_target].extend(subsection_lines)
+ if not section_lines:
+ return ['Empty ' + self.name]
+ ret = []
+ for k in include_sections or sorted(section_lines):
+ ret.extend(section_lines[k])
return ret
def _LoadResults(self, archive_dir):
@@ -354,7 +370,7 @@ class _BuildArchive(object):
self._slow_options = slow_options
self._save_unstripped = save_unstripped
- def ArchiveBuildResults(self, supersize_path):
+ def ArchiveBuildResults(self, supersize_path, tool_prefix=None):
"""Save build artifacts necessary for diffing."""
logging.info('Saving build results to: %s', self.dir)
_EnsureDirsExist(self.dir)
@@ -362,7 +378,7 @@ class _BuildArchive(object):
self._ArchiveFile(self.build.abs_apk_path)
self._ArchiveFile(self.build.abs_apk_path + '.mapping')
self._ArchiveResourceSizes()
- self._ArchiveSizeFile(supersize_path)
+ self._ArchiveSizeFile(supersize_path, tool_prefix)
if self._save_unstripped:
self._ArchiveFile(self.build.abs_main_lib_path)
self.metadata.Write()
@@ -396,7 +412,7 @@ class _BuildArchive(object):
_Die('missing expected file: %s', filename)
shutil.copy(filename, self.dir)
- def _ArchiveSizeFile(self, supersize_path):
+ def _ArchiveSizeFile(self, supersize_path, tool_prefix):
existing_size_file = self.build.abs_apk_path + '.size'
if os.path.exists(existing_size_file):
logging.info('Found existing .size file')
@@ -404,6 +420,8 @@ class _BuildArchive(object):
else:
supersize_cmd = [supersize_path, 'archive', self.archived_size_path,
'--elf-file', self.build.abs_main_lib_path]
+ if tool_prefix:
+ supersize_cmd += ['--tool-prefix', tool_prefix]
if self.build.IsCloud():
supersize_cmd += ['--no-source-paths']
else:
@@ -474,10 +492,12 @@ class _DiffArchiveManager(object):
# Print cached file if all builds were cached.
if os.path.exists(path):
_PrintFile(path)
- if self.build_archives:
+ if self.build_archives and len(self.build_archives) <= 2:
+ if not all(a.Exists() for a in self.build_archives):
+ return
supersize_path = os.path.join(_BINARY_SIZE_DIR, 'supersize')
size2 = ''
- if len(self.build_archives) > 1:
+ if len(self.build_archives) == 2:
size2 = os.path.relpath(self.build_archives[-1].archived_size_path)
logging.info('Enter supersize console via: %s console %s %s',
os.path.relpath(supersize_path),
@@ -606,8 +626,9 @@ def _SyncAndBuild(archive, build, subrepo, no_gclient, extra_rev):
# commits on a branch.
_GitCmd(['checkout', '--detach'], subrepo)
logging.info('Syncing to %s', archive.rev)
- if _GclientSyncCmd(archive.rev, subrepo):
- return False
+ ret = _GclientSyncCmd(archive.rev, subrepo)
+ if ret:
+ return ret
with _ApplyPatch(extra_rev, subrepo):
return build.Run()
@@ -788,14 +809,22 @@ def _PrintFile(path):
@contextmanager
def _TmpCopyBinarySizeDir():
- """Recursively copy files to a temp dir and yield supersize path."""
+ """Recursively copy files to a temp dir and yield temp paths."""
# Needs to be at same level of nesting as the real //tools/binary_size
# since supersize uses this to find d3 in //third_party.
tmp_dir = tempfile.mkdtemp(dir=_SRC_ROOT)
try:
bs_dir = os.path.join(tmp_dir, 'binary_size')
shutil.copytree(_BINARY_SIZE_DIR, bs_dir)
- yield os.path.join(bs_dir, 'supersize')
+ # We also copy the tools supersize needs, but only if they exist.
+ tool_prefix = None
+ if os.path.exists(_DOWNLOAD_OBJDUMP_PATH):
+ if not os.path.exists(os.path.join(_LLVM_TOOLS_DIR, 'llvm-readelf')):
+ _RunCmd([_DOWNLOAD_OBJDUMP_PATH])
+ tools_dir = os.path.join(bs_dir, 'bintools')
+ tool_prefix = os.path.join(tools_dir, 'llvm-')
+ shutil.copytree(_LLVM_TOOLS_DIR, tools_dir)
+ yield (os.path.join(bs_dir, 'supersize'), tool_prefix)
finally:
shutil.rmtree(tmp_dir)
@@ -829,21 +858,20 @@ def _DiffMain(args):
parser.add_argument('--diff-output', required=True)
args = parser.parse_args(args)
- if args.diff_type == 'native':
+ is_native_diff = args.diff_type == 'native'
+ if is_native_diff:
supersize_path = os.path.join(_BINARY_SIZE_DIR, 'supersize')
diff = NativeDiff(args.apk_name + '.size', supersize_path)
else:
- diff = ResourceSizesDiff(args.apk_name, args.apk_name + '.json')
+ diff = ResourceSizesDiff(args.apk_name)
diff.ProduceDiff(args.before_dir, args.after_dir)
- with open(args.diff_output, 'w') as f:
- f.writelines(l + '\n' for l in diff.DetailedResults())
+ lines = diff.DetailedResults() if is_native_diff else diff.Summary()
- stat = diff.summary_stat
- if stat:
- print 'Summary: {} {} {}'.format(*stat)
- else:
- print 'Missing Summary!'
+ with open(args.diff_output, 'w') as f:
+ f.writelines(l + '\n' for l in lines)
+ stat = diff.summary_stat
+ f.write('\n{}={}\n'.format(*stat[:2]))
def main():
@@ -968,7 +996,8 @@ def main():
reference_rev = args.rev
_ValidateRevs(args.rev, reference_rev, subrepo, args.extra_rev)
revs = _GenerateRevList(args.rev, reference_rev, args.all, subrepo, args.step)
- with _TmpCopyBinarySizeDir() as supersize_path:
+ with _TmpCopyBinarySizeDir() as paths:
+ supersize_path, tool_prefix = paths
diffs = [NativeDiff(build.size_name, supersize_path)]
if build.IsAndroid():
diffs += [
@@ -999,7 +1028,7 @@ def main():
_Die('%d builds failed in a row, last failure was %s.',
consecutive_failures, archive.rev)
else:
- archive.ArchiveBuildResults(supersize_path)
+ archive.ArchiveBuildResults(supersize_path, tool_prefix)
consecutive_failures = 0
if i != 0:
diff --git a/chromium/tools/binary_size/html_report_faq.md b/chromium/tools/binary_size/html_report_faq.md
new file mode 100644
index 00000000000..9cd321e6524
--- /dev/null
+++ b/chromium/tools/binary_size/html_report_faq.md
@@ -0,0 +1,80 @@
+# Frequently Asked Questions
+
+[TOC]
+
+## Usage
+
+### How do I create a data file?
+See the [`html_report` command docs](README.md#Usage_html_report).
+
+### What do the different folder and file colors mean?
+Containers (folders, files, and components) have different colors depending on
+the symbols they contain. The color corresponds whatever symbol type has the
+most bytes in that container. The color is the same as that symbol type's icon.
+
+When hovering over the container, you can see a breakdown of all the symbol
+types inside. The first row of that table indicates the symbol type with the
+most bytes.
+
+### What does "Type", "Count", "Total size", and "Percent" refer to?
+When hovering over a container, a card appears breaking down the symbols stored
+within that container. The data appears as a pie chart and a table with the
+columns "Type", "Count", "Total size", and "Percent".
+
+- **Type** refers to the symbol type that row represents.
+- **Count** indicates the number of symbols of that type present in the
+ container.
+- **Total size** indicates how many bytes the symbols of that type take up in
+ total.
+- **Percent** indicates how much the total size of a symbol type takes up of the
+ total size of the container. It also correlates to the pie chart sizes.
+
+### Which keyboard shortcuts are supported?
+Once the symbol tree is focused on, various keyboard shortcuts are supported
+to navigate around the tree.
+
+The symbol tree can be focused by clicking on it or by pressing _Tab_ until
+the tree is focused.
+
+Key | Function
+--- | --------
+_Enter_ or _Space_ | Open or close a container, just like clicking on it
+↓ | Focus the node below the current node
+↑ | Focus the node above the current node
+→ | Move focus to the first child node, or open the current node if closed
+← | Move focus to the parent node, or close the current node if open
+_Home_ | Move focus to the topmost node
+_End_ | Move focus to the bottommost node
+_A-z_ | Focus the next node that starts with the given character
+_*_ | Expand all sibling containers of the current node.
+
+## Symbols
+
+### What are "Other entries"?
+The symbol type "Other entries" refers to symbols that don't fall in one of the
+defined symbol categories. This includes images and `.bin` files.
+
+### What are "Other small" symbols for?
+To reduce the size of the generated data file, small symbols are omitted by
+default. Small symbols of the same type are combined into an "Other small
+[type]" bucket.
+
+More symbols can be displayed by using the `--all-symbols` flag
+when generating the data file. However, the data file will be larger and will
+take longer to load.
+
+## Filters
+
+### What regular expressions syntax is supported?
+The contain and exclude regular expressions are evaluated against the full path
+of each symbol. Symbol names are appended onto the end of a path and prefixed
+with a `:` (`path/to/file:symbol`). The full path is displayed below the byte
+size on the info card, and also appears when hovering over a symbol's name.
+
+The "Symbols must contain" filter is applied before the "Symbols must exclude"
+filter.
+
+Example filter | Regular expression
+-------------- | ------------------
+Find symbols in `MyJavaClass` | `:MyJavaClass#`
+Find folders named `myfolder` | `myfolder/`
diff --git a/chromium/tools/binary_size/libsupersize/apkanalyzer.py b/chromium/tools/binary_size/libsupersize/apkanalyzer.py
index 9c55e1dfd35..1efc52fbdce 100644
--- a/chromium/tools/binary_size/libsupersize/apkanalyzer.py
+++ b/chromium/tools/binary_size/libsupersize/apkanalyzer.py
@@ -7,6 +7,7 @@
Assumes that apk_path.mapping and apk_path.jar.info is available.
"""
+import logging
import os
import subprocess
import zipfile
@@ -128,8 +129,14 @@ def CreateDexSymbols(apk_path, output_directory):
nodes = UndoHierarchicalSizing(_RunApkAnalyzer(apk_path, output_directory))
dex_expected_size = _ExpectedDexTotalSize(apk_path)
total_node_size = sum(map(lambda x: x[1], nodes))
- assert dex_expected_size >= total_node_size, (
- 'Node size too large, check for node processing errors.')
+ # TODO(agrieve): Figure out why this log is triggering for
+ # ChromeModernPublic.apk (https://crbug.com/851535).
+ # Reporting: dex_expected_size=6546088 total_node_size=6559549
+ if dex_expected_size < total_node_size:
+ logging.error(
+ 'Node size too large, check for node processing errors. '
+ 'dex_expected_size=%d total_node_size=%d', dex_expected_size,
+ total_node_size)
# We have more than 100KB of ids for methods, strings
id_metadata_overhead_size = dex_expected_size - total_node_size
symbols = []
diff --git a/chromium/tools/binary_size/libsupersize/archive.py b/chromium/tools/binary_size/libsupersize/archive.py
index d95108f629c..687f9d34061 100644
--- a/chromium/tools/binary_size/libsupersize/archive.py
+++ b/chromium/tools/binary_size/libsupersize/archive.py
@@ -30,11 +30,15 @@ import linker_map_parser
import models
import ninja_parser
import nm
+import obj_analyzer
import path_util
sys.path.insert(1, os.path.join(path_util.SRC_ROOT, 'tools', 'grit'))
from grit.format import data_pack
+_OWNERS_FILENAME = 'OWNERS'
+_COMPONENT_REGEX = re.compile(r'\s*#\s*COMPONENT\s*:\s*(\S+)')
+_FILE_PATH_REGEX = re.compile(r'\s*file://(\S+)')
# Holds computation state that is live only when an output directory exists.
_OutputDirectoryContext = collections.namedtuple('_OutputDirectoryContext', [
@@ -92,6 +96,8 @@ class SectionSizeKnobs(object):
'META-INF/MANIFEST.MF',
])
+ self.src_root = path_util.SRC_ROOT
+
def _OpenMaybeGz(path):
"""Calls `gzip.open()` if |path| ends in ".gz", otherwise calls `open()`."""
@@ -215,6 +221,11 @@ def _NormalizeNames(raw_symbols):
def _NormalizeObjectPath(path):
+ """Normalizes object paths.
+
+ Prefixes are removed: obj/, ../../
+ Archive names made more pathy: foo/bar.a(baz.o) -> foo/bar.a/baz.o
+ """
if path.startswith('obj/'):
# Convert obj/third_party/... -> third_party/...
path = path[4:]
@@ -538,6 +549,86 @@ def _CalculatePadding(raw_symbols):
'%r\nprev symbol: %r' % (symbol, prev_symbol))
+def _ParseComponentFromOwners(filename):
+ """Searches an OWNERS file for lines that start with `# COMPONENT:`.
+
+ If an OWNERS file has no COMPONENT but references another OWNERS file, follow
+ the reference and check that file instead.
+
+ Args:
+ filename: Path to the file to parse.
+ Returns:
+ The text that follows the `# COMPONENT:` prefix, such as 'component>name'.
+ Empty string if no component found or the file didn't exist.
+ """
+ reference_paths = []
+ try:
+ with open(filename) as f:
+ for line in f:
+ component_matches = _COMPONENT_REGEX.match(line)
+ path_matches = _FILE_PATH_REGEX.match(line)
+ if component_matches:
+ return component_matches.group(1)
+ elif path_matches:
+ reference_paths.append(path_matches.group(1))
+ except IOError:
+ return ''
+
+ if len(reference_paths) == 1:
+ newpath = os.path.join(path_util.SRC_ROOT, reference_paths[0])
+ return _ParseComponentFromOwners(newpath)
+ else:
+ return ''
+
+
+def _FindComponentRoot(start_path, cache, knobs):
+ """Searches all parent directories for COMPONENT in OWNERS files.
+
+ Args:
+ start_path: Path of directory to start searching from. Must be relative to
+ SRC_ROOT.
+ cache: Dict of OWNERS paths. Used instead of filesystem if paths are present
+ in the dict.
+ knobs: Instance of SectionSizeKnobs. Tunable knobs and options.
+
+ Returns:
+ COMPONENT belonging to |start_path|, or empty string if not found.
+ """
+ prev_dir = None
+ test_dir = start_path
+ # This loop will traverse the directory structure upwards until reaching
+ # SRC_ROOT, where test_dir and prev_dir will both equal an empty string.
+ while test_dir != prev_dir:
+ cached_component = cache.get(test_dir)
+ if cached_component:
+ return cached_component
+ elif cached_component is None:
+ owners_path = os.path.join(knobs.src_root, test_dir, _OWNERS_FILENAME)
+ component = _ParseComponentFromOwners(owners_path)
+ cache[test_dir] = component
+ if component:
+ return component
+ prev_dir = test_dir
+ test_dir = os.path.dirname(test_dir)
+ return ''
+
+
+def _PopulateComponents(raw_symbols, knobs):
+ """Populates the |component| field based on |source_path|.
+
+ Symbols without a |source_path| are skipped.
+
+ Args:
+ raw_symbols: list of Symbol objects.
+ knobs: Instance of SectionSizeKnobs. Tunable knobs and options.
+ """
+ seen_paths = {}
+ for symbol in raw_symbols:
+ if symbol.source_path:
+ folder_path = os.path.dirname(symbol.source_path)
+ symbol.component = _FindComponentRoot(folder_path, seen_paths, knobs)
+
+
def _AddNmAliases(raw_symbols, names_by_address):
"""Adds symbols that were removed by identical code folding."""
# Step 1: Create list of (index_of_symbol, name_list).
@@ -606,7 +697,25 @@ def LoadAndPostProcessSizeInfo(path):
return size_info
-def CreateMetadata(map_path, elf_path, apk_path, tool_prefix, output_directory):
+def CreateMetadata(map_path, elf_path, apk_path, tool_prefix, output_directory,
+ linker_name):
+ """Creates metadata dict.
+
+ Args:
+ map_path: Path to the linker .map(.gz) file to parse.
+ elf_path: Path to the corresponding unstripped ELF file. Used to find symbol
+ aliases and inlined functions. Can be None.
+ apk_path: Path to the .apk file to measure.
+ tool_prefix: Prefix for c++filt & nm.
+ output_directory: Build output directory.
+ linker_name: 'gold', 'lld_v#' (# is a number), 'lld-lto_v#', or None.
+
+ Returns:
+ None if |elf_path| is not supplied. Otherwise returns dict mapping string
+ constants to values.
+ If |elf_path| is supplied, git revision and elf info are included.
+ If |output_directory| is also supplied, then filenames will be included.
+ """
metadata = None
if elf_path:
logging.debug('Constructing metadata')
@@ -623,6 +732,7 @@ def CreateMetadata(map_path, elf_path, apk_path, tool_prefix, output_directory):
models.METADATA_ELF_ARCHITECTURE: architecture,
models.METADATA_ELF_MTIME: timestamp,
models.METADATA_ELF_BUILD_ID: build_id,
+ models.METADATA_LINKER_NAME: linker_name,
models.METADATA_TOOL_PREFIX: relative_tool_prefix,
}
@@ -652,7 +762,7 @@ def _ResolveThinArchivePaths(raw_symbols, thin_archives):
def _ParseElfInfo(map_path, elf_path, tool_prefix, track_string_literals,
- outdir_context=None):
+ outdir_context=None, linker_name=None):
"""Adds ELF section sizes and symbols."""
if elf_path:
# Run nm on the elf file to retrieve the list of symbol names per-address.
@@ -671,14 +781,14 @@ def _ParseElfInfo(map_path, elf_path, tool_prefix, track_string_literals,
# Rather than record all paths for each symbol, set the paths to be the
# common ancestor of all paths.
if outdir_context:
- bulk_analyzer = nm.BulkObjectFileAnalyzer(
+ bulk_analyzer = obj_analyzer.BulkObjectFileAnalyzer(
tool_prefix, outdir_context.output_directory)
bulk_analyzer.AnalyzePaths(outdir_context.elf_object_paths)
logging.info('Parsing Linker Map')
with _OpenMaybeGz(map_path) as map_file:
section_sizes, raw_symbols = (
- linker_map_parser.MapFileParser().Parse(map_file))
+ linker_map_parser.MapFileParser().Parse(linker_name, map_file))
if outdir_context and outdir_context.thin_archives:
_ResolveThinArchivePaths(raw_symbols, outdir_context.thin_archives)
@@ -770,7 +880,7 @@ def _ComputePakFileSymbols(
section_name = models.SECTION_PAK_NONTRANSLATED
overhead = (12 + 6) * compression_ratio # Header size plus extra offset
symbols_by_id[file_name] = models.Symbol(
- section_name, overhead, full_name='{}: overhead'.format(file_name))
+ section_name, overhead, full_name='Overhead: {}'.format(file_name))
for resource_id in sorted(contents.resources):
if resource_id in alias_map:
# 4 extra bytes of metadata (2 16-bit ints)
@@ -811,7 +921,7 @@ class _ResourceSourceMapper(object):
for dest, renamed_dest in renames.iteritems():
# Allow one more level of indirection due to renaming renamed files
renamed_dest = renames.get(renamed_dest, renamed_dest)
- actual_source = res_info.get(renamed_dest);
+ actual_source = res_info.get(renamed_dest)
if actual_source:
res_info[dest] = actual_source
return res_info
@@ -858,6 +968,7 @@ def _ParsePakInfoFile(pak_info_path):
def _ParsePakSymbols(
section_sizes, object_paths, output_directory, symbols_by_id):
+ object_paths_by_id = collections.defaultdict(list)
for path in object_paths:
whitelist_path = os.path.join(output_directory, path + '.whitelist')
if (not os.path.exists(whitelist_path)
@@ -872,10 +983,24 @@ def _ParsePakSymbols(
# resulting in resource_ids that don't end up being in the final apk.
if resource_id not in symbols_by_id:
continue
- symbols_by_id[resource_id].object_path = path
-
- raw_symbols = sorted(symbols_by_id.values(),
- key=lambda s: (s.section_name, s.address))
+ object_paths_by_id[resource_id].append(path)
+
+ raw_symbols = []
+ for resource_id, symbol in symbols_by_id.iteritems():
+ raw_symbols.append(symbol)
+ paths = set(object_paths_by_id[resource_id])
+ if paths:
+ symbol.object_path = paths.pop()
+ if paths:
+ aliases = symbol.aliases or [symbol]
+ symbol.aliases = aliases
+ for path in paths:
+ new_sym = models.Symbol(
+ symbol.section_name, symbol.size, address=symbol.address,
+ full_name=symbol.full_name, object_path=path, aliases=aliases)
+ aliases.append(new_sym)
+ raw_symbols.append(new_sym)
+ raw_symbols.sort(key=lambda s: (s.section_name, s.address))
raw_total = 0.0
int_total = 0
for symbol in raw_symbols:
@@ -1015,7 +1140,7 @@ def _CalculateElfOverhead(section_sizes, elf_path):
def CreateSectionSizesAndSymbols(
map_path=None, tool_prefix=None, output_directory=None, elf_path=None,
apk_path=None, track_string_literals=True, metadata=None,
- apk_so_path=None, pak_files=None, pak_info_file=None,
+ apk_so_path=None, pak_files=None, pak_info_file=None, linker_name=None,
knobs=SectionSizeKnobs()):
"""Creates sections sizes and symbols for a SizeInfo.
@@ -1028,6 +1153,11 @@ def CreateSectionSizesAndSymbols(
alias information will not be recorded.
track_string_literals: Whether to break down "** merge string" sections into
smaller symbols (requires output_directory).
+
+ Returns:
+ A tuple of (section_sizes, raw_symbols).
+ section_sizes is a dict mapping section names to their size
+ raw_symbols is a list of Symbol objects
"""
if apk_path and elf_path:
# Extraction takes around 1 second, so do it in parallel.
@@ -1069,7 +1199,8 @@ def CreateSectionSizesAndSymbols(
thin_archives=thin_archives)
section_sizes, raw_symbols = _ParseElfInfo(
- map_path, elf_path, tool_prefix, track_string_literals, outdir_context)
+ map_path, elf_path, tool_prefix, track_string_literals,
+ outdir_context=outdir_context, linker_name=linker_name)
elf_overhead_size = _CalculateElfOverhead(section_sizes, elf_path)
pak_symbols_by_id = None
@@ -1102,6 +1233,7 @@ def CreateSectionSizesAndSymbols(
raw_symbols.extend(pak_raw_symbols)
_ExtractSourcePathsAndNormalizeObjectPaths(raw_symbols, source_mapper)
+ _PopulateComponents(raw_symbols, knobs)
logging.info('Converting excessive aliases into shared-path symbols')
_CompactLargeAliasesIntoSharedSymbols(raw_symbols, knobs)
logging.debug('Connecting nm aliases')
@@ -1136,6 +1268,14 @@ def CreateSizeInfo(
def _DetectGitRevision(directory):
+ """Runs git rev-parse to get the SHA1 hash of the current revision.
+
+ Args:
+ directory: Path to directory where rev-parse command will be run.
+
+ Returns:
+ A string with the SHA1 hash, or None if an error occured.
+ """
try:
git_rev = subprocess.check_output(
['git', '-C', directory, 'rev-parse', 'HEAD'])
@@ -1194,7 +1334,7 @@ def _ParseGnArgs(args_path):
def _DetectLinkerName(map_path):
with _OpenMaybeGz(map_path) as map_file:
- return linker_map_parser.DetectLinkerNameFromMapFileHeader(next(map_file))
+ return linker_map_parser.DetectLinkerNameFromMapFile(map_file)
def _ElfInfoFromApk(apk_path, apk_so_path, tool_prefix):
@@ -1265,6 +1405,8 @@ def AddArguments(parser):
default=True, action='store_false',
help='Disable breaking down "** merge strings" into more '
'granular symbols.')
+ parser.add_argument('--source-directory',
+ help='Custom path to the root source directory.')
AddMainPathsArguments(parser)
@@ -1313,6 +1455,7 @@ def DeduceMainPaths(args, parser):
'linker map file.')
linker_name = _DetectLinkerName(map_path)
+ logging.info('Linker name: %s' % linker_name)
tool_prefix_finder = path_util.ToolPrefixFinder(
value=args.tool_prefix,
output_directory_finder=output_directory_finder,
@@ -1322,25 +1465,30 @@ def DeduceMainPaths(args, parser):
if not args.no_source_paths:
output_directory = output_directory_finder.Finalized()
return (output_directory, tool_prefix, apk_path, apk_so_path, elf_path,
- map_path)
+ map_path, linker_name)
def Run(args, parser):
if not args.size_file.endswith('.size'):
parser.error('size_file must end with .size')
- (output_directory, tool_prefix, apk_path, apk_so_path, elf_path, map_path) = (
- DeduceMainPaths(args, parser))
+ (output_directory, tool_prefix, apk_path, apk_so_path, elf_path, map_path,
+ linker_name) = (DeduceMainPaths(args, parser))
metadata = CreateMetadata(map_path, elf_path, apk_path, tool_prefix,
- output_directory)
+ output_directory, linker_name)
+
+ knobs = SectionSizeKnobs()
+ if args.source_directory:
+ knobs.src_root = args.source_directory
section_sizes, raw_symbols = CreateSectionSizesAndSymbols(
map_path=map_path, tool_prefix=tool_prefix, elf_path=elf_path,
apk_path=apk_path, output_directory=output_directory,
track_string_literals=args.track_string_literals,
metadata=metadata, apk_so_path=apk_so_path,
- pak_files=args.pak_file, pak_info_file=args.pak_info_file)
+ pak_files=args.pak_file, pak_info_file=args.pak_info_file,
+ linker_name=linker_name, knobs=knobs)
size_info = CreateSizeInfo(
section_sizes, raw_symbols, metadata=metadata, normalize_names=False)
diff --git a/chromium/tools/binary_size/libsupersize/bcanalyzer.py b/chromium/tools/binary_size/libsupersize/bcanalyzer.py
new file mode 100755
index 00000000000..edd1a1e7479
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/bcanalyzer.py
@@ -0,0 +1,379 @@
+#!/usr/bin/env python
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs bcanalyzer to extract data from LLVM Bitcode (BC) files.
+
+IsBitcodeFile():
+ Reads the magic header of a file to quickly decide whether it is a BC file.
+
+ParseTag():
+ Heuristically parses a single-line tag from bcanalyzer dump (exporeted for
+ testing).
+
+RunBcAnalyzerOnIntermediates():
+ BulkForkAndCall() target: Given BC file [paths], runs (llvm-)bcanalyzer on
+ each path, parses the output, extracts strings, and returns {path: [strings]}.
+
+This file can also be run stand-alone in order to test out the logic on smaller
+sample sizes.
+"""
+
+from __future__ import print_function
+
+import argparse
+import os
+import re
+import subprocess
+
+import concurrent
+import path_util
+
+
+# Upper bound on number of bytes per character in strings. 4-byte / 32-bit
+# strings are rare and are likely confused with 32-bit int arrays. So by
+# default, only accept up to 2-byte / 16-bit strings.
+_CHAR_WIDTH_LIMIT = 2
+
+_RE_SPLIT = re.compile(r'=(\d+)')
+# <TYPE_BLOCK_ID> children tags that should not be counted as types.
+# - <NUMENTRY> is meta data.
+# - <STRUCT_NAME> with the following <STRUCT_NAMED> (or other tag) are counted
+# as a single type entry.
+_NON_TYPE_TAGS = set(['NUMENTRY', 'STRUCT_NAME'])
+
+# Use bit-fields for tag types: 1 => Opening tag, 2 => Closed tag.
+OPENING_TAG = 1
+CLOSING_TAG = 2
+SELF_CLOSING_TAG = OPENING_TAG | CLOSING_TAG
+
+
+def _IsOpeningTag(tag_type):
+ return tag_type & 1
+
+
+def _IsClosingTag(tag_type):
+ return tag_type & 2
+
+
+def IsBitcodeFile(path):
+ try:
+ with open(path, 'rb') as f:
+ return f.read(4) == 'BC\xc0\xde'
+ except IOError:
+ return False
+
+
+def ParseTag(line):
+ """Heuristically parses a single-line tag from bcanalyzer dump.
+
+ Since input data are machine-generated, so we only need "good enough" parsing
+ logic that favors simplicity. For example, '</FOO/>' is accepted.
+
+ Args:
+ line: Stripped line that may have a single-line tag with trailing text.
+
+ Returns:
+ (tag_type, tag, attrib_pos) if successful, else (None) * 3. Details:
+ tag_type: One of {OPENING_TAG, CLOSING_TAG, SELF_CLOSING_TAG}.
+ tag: The tag name.
+ attrib_pos: Position in |line| to start parsing attributes.
+ """
+ # <TYPE_BLOCK_ID NumWords=103 BlockCodeSize=4>
+ # ==> (OPENING_TAG, 'TYPE_BLOCK_ID', 14).
+ # <ARRAY abbrevid=9 op0=1 op1=7/> Trailing text!
+ # ==> (SELF_CLOSING_TAG, 'ARRAY', 6).
+ # </TYPE_BLOCK_ID>
+ # ==> (CLOSING_TAG, 'TYPE_BLOCK_ID', 15).
+
+ # Assumes |line| is stripped, i.e., so no indent and no trailing new line.
+ if len(line) < 2 or line[0] != '<':
+ return (None, None, None)
+ tag_type, pos = (CLOSING_TAG, 2) if line[1] == '/' else (OPENING_TAG, 1)
+ for i in xrange(pos, len(line)):
+ if not line[i].isalnum() and line[i] != '_':
+ if i == pos or not line[i] in ' >/':
+ break
+ end = line.find('>', i)
+ if end < 0:
+ break
+ if line[end - 1] == '/':
+ return (SELF_CLOSING_TAG, line[pos:i], i)
+ return (tag_type, line[pos:i], i)
+ return (None, None, None)
+
+
+def _ParseOpItems(line, pos):
+ """Heuristically extracts op0=# op1=# ... values from a single-line tag."""
+ # <SETTYPE abbrevid=4 op0=42/>
+ # ^ pos = 8
+ # ==> iter([42]).
+ # <CSTRING abbrevid=11 op0=84 op1=101 op2=115 op3=116 op4=56 op5=97/>
+ # ^ pos = 8
+ # ==> iter([84, 101, 115, 116, 56, 97]).
+ # <STRING abbrevid=9 op0=1 op1=0 op2=0 op3=1 op4=1 op5=0/>
+ # ^ pos = 7
+ # ==> iter([1, 0, 0, 1, 1, 0]).
+ # <DATA op0=8412 op1=101 op2=1150 op3=116 op4=5200 op5=98 op6=0/>
+ # ^ pos = 5
+ # ==> iter([8412, 101, 1150, 116, 5200, 98, 0]).
+
+ # In particular, skip 'abbrevid=#'.
+ start = line.index(' op', pos)
+ end = line.index('>', start)
+ for t in _RE_SPLIT.finditer(line[start:end]):
+ yield int(t.group(1))
+
+
+# Emits uint16 values as a stream of 2 bytes (little-endian).
+def _UnpackUint16ListToBytes(items):
+ for item in items:
+ yield item & 0xFF
+ yield (item >> 8) & 0xFF
+
+
+# Emits uint32 values as a stream of 4 bytes (little-endian).
+def _UnpackUint32ListToBytes(items):
+ for item in items:
+ yield item & 0xFF
+ yield (item >> 8) & 0xFF
+ yield (item >> 16) & 0xFF
+ yield (item >> 24) & 0xFF
+
+
+class _BcIntArrayType:
+ """The specs of an integer array type."""
+
+ # Lookup table to map from width to an unpacker that splits ints into bytes.
+ _UNPACKER_MAP = {
+ 1: iter,
+ 2: _UnpackUint16ListToBytes,
+ 4: _UnpackUint32ListToBytes
+ }
+
+ def __init__(self, length, width):
+ # Number of elements in the array.
+ self.length = length
+ # Number of bytes per element.
+ self.width = width
+
+ def ParseOpItemsAsString(self, line, attrib_pos, add_null_at_end):
+ """Reads op0=# op=# ... values and returns them as a list of bytes.
+
+ Interprets each op0=# op1=# ... value as a |self.width|-byte integer, splits
+ them into component bytes (little-endian), and returns the result as string.
+
+ Args:
+ line: Stripped line of single-line tag with op0=# op1=# ... data.
+ attrib_pos: Position in |line| where attribute list starts.
+ add_null_add_end: Whether to append |'\x00' * self.width|.
+ """
+ items = _ParseOpItems(line, attrib_pos)
+ unpacker = _BcIntArrayType._UNPACKER_MAP[self.width]
+ s = ''.join(chr(t) for t in unpacker(items))
+ if add_null_at_end:
+ s += '\x00' * self.width
+ # Rather stringent check to ensure exact size match.
+ assert len(s) == self.length * self.width
+ return s
+
+
+class _BcTypeInfo:
+ """Stateful parser of <TYPE_BLOCK_ID>, specialized for integer arrays."""
+
+ # <TYPE_BLOCK_ID NumWords=103 BlockCodeSize=4>
+ # <NUMENTRY op0=9/> # Type ids should be in [0, 8].
+ # <INTEGER op0=8/> # Type id = 0: int8.
+ # <POINTER abbrevid=4 op0=0 op1=0/> # Type id = 1: Pointer to type id 0
+ # # ==> int8*.
+ # <ARRAY abbrevid=9 op0=4 op1=0/> # Type id = 2: Array with 4 elements
+ # # of type id 0 ==> int8[4]
+ # <STRUCT_NAME op0=115 op1=116 op2=114/> # Joins next Tag.
+ # <STRUCT_NAMED abbrevid=8 op0=0 op1=1/> # Type id = 3: Struct (unused).
+ # <FUNCTION abbrevid=5 op0=0 op1=12/> # Type id = 4: Function (unused).
+ # <INTEGER op0=16/> # Type id = 5: int16.
+ # <POINTER abbrevid=4 op0=5 op1=0/> # Type id = 6: Pointer to type id 5
+ # # ==> int16*.
+ # <INTEGER op0=32/> # Type id = 7: int32.
+ # <ARRAY abbrevid=9 op0=5 op1=4/> # Type id = 8: Array with 4 elements
+ # # of type id 5 ==> int16[4]
+ # <TYPE_BLOCK_ID>
+
+ def __init__(self):
+ # Auto-incrementing current type id.
+ self.cur_type_id = 0
+ # Maps from type id (of an integer) to number of bits.
+ self.int_types = {}
+ # Maps from type id (of an integer array) to _BcIntArrayType.
+ self.int_array_types = {}
+
+ def Feed(self, line, tag, attrib_pos):
+ """Parses a single-line tag and store integer and integer array types.
+
+ Args:
+ line: Stripped line of single-line tag with op0=# op1=# ... data.
+ tag: The tag type in |line| (child tag of <TYPE_BLOCK_ID>).
+ attrib_pos: Position in |line| where attribute list starts.
+ """
+ if tag in _NON_TYPE_TAGS:
+ return
+ if tag == 'INTEGER':
+ num_bits = next(_ParseOpItems(line, attrib_pos)) # op0.
+ self.int_types[self.cur_type_id] = num_bits
+ elif tag == 'ARRAY':
+ [size, item_type_id] = list(_ParseOpItems(line, attrib_pos)) # op0, op1.
+ bits = self.int_types.get(item_type_id)
+ if bits is not None: # |bits| can be None for non-int arrays.
+ self.int_array_types[self.cur_type_id] = _BcIntArrayType(size, bits / 8)
+ self.cur_type_id += 1
+
+ def GetArrayType(self, idx):
+ return self.int_array_types.get(idx)
+
+
+def _ParseBcAnalyzer(lines):
+ """A generator to extract strings from bcanalyzer dump of a BC file."""
+
+ # ...
+ # <TYPE_BLOCK_ID NumWords=103 BlockCodeSize=4>
+ # ... (See above; parsed by _BcTypeInfo)
+ # <TYPE_BLOCK_ID>
+ # ...
+ # <CONSTANTS_BLOCK NumWords=93 BlockCodeSize=4>
+ # <SETTYPE abbrevid=4 op0=1/> # Current type id := 1 ==> int8*.
+ # <CE_INBOUNDS_GEP op0=3 op1=4 op2=1 op3=12 op4=57 op5=12 op6=57/>
+ # <SETTYPE abbrevid=4 op0=2/> # Current type id := 2 ==> int8[4].
+ # <CSTRING abbrevid=11 op0=70 op1=111 op2=111/> record string = 'Foo'
+ # <STRING abbrevid=11 op0=70 op1=111 op2=111 op3=1/> # {'F','o','o',1}.
+ # <SETTYPE abbrevid=6 op0=7/> # Current type id := 7 ==> int32.
+ # <INTEGER abbrevid=5 op0=2000/> # Stores 1000.
+ # <INTEGER abbrevid=5 op0=2001/> # Stores -1000.
+ # <SETTYPE abbrevid=4 op0=8/> # Current type id := 8 ==> int16[4].
+ # <NULL/>
+ # <DATA abbrevid=11 op0=8400 op1=10100 op2=11500 op3=0/>
+ # </CONSTANTS_BLOCK>
+ # ...
+
+ # Notes:
+ # - Only parse first <TYPE_BLOCK_ID> and first <CONSTANTS_BLOCK>.
+ # - <CONSTANTS_BLOCK> is stateful: A "current type id" exists, and that's set
+ # by <SETTYPE>, with op0= referring to type id.
+ # - For array lengths one needs to refer to the corresponding <ARRAY>.
+ # - Strings / arrays are in <CSTRING>, <STRING>, and <DATA>.
+ # - abbrevid=# is redundant (repeats tag type) and unused
+ # - Character data are stored in op0=# op1=# ..., one per character. These
+ # values should fit in the proper range, and can be fairly large.
+ # - <CSTRING> has implicit 0 at end.
+ # - Data lengths agree with the length in the matching <ARRAY> entry.
+ # - "record string" text is not very useful: It only appears if all
+ # characters are printable.
+ # - Signed vs. unsigned types are undistinguished.
+ # - In <INTEGER>, the op0= value is stored as 2 * abs(x) + (signed ? 0 : 1).
+ # - In <ARRAY> of int, values are coerced to unsigned type.
+ # - Strings and int arrays are undistinguished.
+ # - <CSTRING>: If an uint8 array happens to end with 0, then this gets used!
+ # - Arrays (or integers) of all-0 appear as <NULL/>. Presumably this gets
+ # placed into .bss section.
+
+ STATE_VOID = 0
+ STATE_TYPE_BLOCK = 1
+ STATE_CONST_BLOCK = 2
+ state = STATE_VOID
+
+ type_info = None
+ consts_cur_type = None
+
+ # State machine to parse the *first* <TYPE_BLOCK_ID> to initialize
+ # |type_info|, then the *first* <CONSTANTS_BLOCK> to yield strings.
+ for line in lines:
+ line = line.lstrip()
+ (tag_type, tag, attrib_pos) = ParseTag(line)
+ if tag_type is None:
+ continue
+ if state == STATE_VOID:
+ if _IsOpeningTag(tag_type):
+ if tag == 'TYPE_BLOCK_ID':
+ if type_info is None:
+ state = STATE_TYPE_BLOCK
+ type_info = _BcTypeInfo()
+ elif tag == 'CONSTANTS_BLOCK':
+ if type_info is not None:
+ state = STATE_CONST_BLOCK
+
+ elif state == STATE_TYPE_BLOCK:
+ if _IsClosingTag(tag_type) and tag == 'TYPE_BLOCK_ID':
+ state = STATE_VOID
+ else:
+ type_info.Feed(line, tag, attrib_pos)
+
+ elif state == STATE_CONST_BLOCK:
+ if _IsClosingTag(tag_type) and tag == 'CONSTANTS_BLOCK':
+ # Skip remaining data, including subsequent <CONSTANTS_BLOCK>s.
+ break
+ elif tag == 'SETTYPE':
+ consts_cur_type_id = next(_ParseOpItems(line, attrib_pos)) # op0.
+ consts_cur_type = type_info.GetArrayType(consts_cur_type_id)
+ elif consts_cur_type and consts_cur_type.width <= _CHAR_WIDTH_LIMIT:
+ if tag in ['CSTRING', 'STRING', 'DATA']:
+ # Exclude 32-bit / 4-byte strings since they're rarely used, and are
+ # likely confused with 32-bit int arrays.
+ s = consts_cur_type.ParseOpItemsAsString(
+ line, attrib_pos, tag == 'CSTRING')
+ yield (consts_cur_type, s)
+
+
+class _BcAnalyzerRunner:
+ """Helper to run bcanalyzer and extract output lines. """
+ def __init__(self, tool_prefix, output_directory):
+ self._args = [path_util.GetBcAnalyzerPath(tool_prefix), '--dump',
+ '--disable-histogram']
+ self._output_directory = output_directory
+
+ def RunOnFile(self, obj_file):
+ output = subprocess.check_output(self._args + [obj_file],
+ cwd=self._output_directory)
+ return output.splitlines()
+
+
+# This is a target for BulkForkAndCall().
+def RunBcAnalyzerOnIntermediates(target, tool_prefix, output_directory):
+ """Calls bcanalyzer and returns encoded map from path to strings.
+
+ Args:
+ target: A list of BC file paths.
+ """
+ assert isinstance(target, list)
+ runner = _BcAnalyzerRunner(tool_prefix, output_directory)
+ strings_by_path = {}
+ for t in target:
+ strings_by_path[t] = [s for _, s in _ParseBcAnalyzer(runner.RunOnFile(t))]
+ # Escape strings by repr() so there will be no special characters to interfere
+ # concurrent.EncodeDictOfLists() and decoding.
+ return concurrent.EncodeDictOfLists(strings_by_path, value_transform=repr)
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--tool-prefix', required=True)
+ parser.add_argument('--output-directory', default='.')
+ parser.add_argument('--char-width-limit', type=int)
+ parser.add_argument('objects', type=os.path.realpath, nargs='+')
+
+ args = parser.parse_args()
+ base_path = os.path.normpath(args.output_directory)
+ runner = _BcAnalyzerRunner(args.tool_prefix, args.output_directory)
+ if args.char_width_limit is not None:
+ global _CHAR_WIDTH_LIMIT
+ _CHAR_WIDTH_LIMIT = args.char_width_limit
+
+ for obj_path in args.objects:
+ rel_path = os.path.relpath(obj_path, base_path)
+ print('File: %s' % rel_path)
+ for cur_type, s in _ParseBcAnalyzer(runner.RunOnFile(obj_path)):
+ print(' char%d[%d]: %r' % (cur_type.width * 8, cur_type.length, s))
+ print('')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/binary_size/libsupersize/bcanalyzer_test.py b/chromium/tools/binary_size/libsupersize/bcanalyzer_test.py
new file mode 100755
index 00000000000..089d622a62b
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/bcanalyzer_test.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import ast
+import os
+import unittest
+
+import bcanalyzer
+import concurrent
+
+
+_SCRIPT_DIR = os.path.dirname(__file__)
+_TEST_DATA_DIR = os.path.join(_SCRIPT_DIR, 'testdata')
+_TEST_SOURCE_DIR = os.path.join(_TEST_DATA_DIR, 'mock_source_directory')
+_TEST_OUTPUT_DIR = os.path.join(_TEST_SOURCE_DIR, 'out', 'Release')
+_TEST_TOOL_PREFIX = os.path.join(
+ os.path.abspath(_TEST_DATA_DIR), 'mock_toolchain', 'llvm-')
+
+
+def _MakeString(bits, toks):
+ """Creates a multi-byte string from ASCII strings and/or ASCII codes.
+
+ Args:
+ bits: Number of bits per character, must be in {8, 16, 32}.
+ toks: A list of tokens, each of which is a ASCII strings or an integer
+ representing a character's ASCII value (e.g., 0 for terminating null).
+
+ Returns: A flattened string of the |bits|-bit string formed by |bit|-extending
+ the result of concatanating tokens.
+ """
+ s = ''.join(tok if isinstance(tok, basestring) else chr(tok) for tok in toks)
+ padding = '\x00' * ((bits - 8) / 8)
+ return ''.join(ch + padding for ch in s)
+
+
+class BcAnalyzerTest(unittest.TestCase):
+
+ def testParseTag(self):
+ # Valid cases.
+ self.assertEquals((bcanalyzer.OPENING_TAG, 'FOO', 4),
+ bcanalyzer.ParseTag('<FOO> trailing'))
+ self.assertEquals((bcanalyzer.OPENING_TAG, 'BAR', 4),
+ bcanalyzer.ParseTag('<BAR op0=3 op1=4>'))
+ self.assertEquals((bcanalyzer.CLOSING_TAG, 'FOO', 5),
+ bcanalyzer.ParseTag('</FOO>'))
+ self.assertEquals((bcanalyzer.SELF_CLOSING_TAG, 'FOO', 4),
+ bcanalyzer.ParseTag('<FOO/>'))
+ self.assertEquals((bcanalyzer.SELF_CLOSING_TAG, 'TOMATO2', 8),
+ bcanalyzer.ParseTag('<TOMATO2 />'))
+ # Not self-closing: For simplicity we requires '/>' with space.
+ self.assertEquals((bcanalyzer.OPENING_TAG, 'TOMATO2', 8),
+ bcanalyzer.ParseTag('<TOMATO2 / >'))
+ self.assertEquals((bcanalyzer.SELF_CLOSING_TAG, 'BAR', 4),
+ bcanalyzer.ParseTag('<BAR op0=3 op1=4/>'))
+ self.assertEquals((bcanalyzer.OPENING_TAG, 'FOO', 4),
+ bcanalyzer.ParseTag('<FOO> / trailing'))
+ self.assertEquals((bcanalyzer.SELF_CLOSING_TAG, 'STRUCT_NAME', 12),
+ bcanalyzer.ParseTag('<STRUCT_NAME abbrevid=7 op0=0/>'))
+ self.assertEquals((bcanalyzer.SELF_CLOSING_TAG, 'UnkownCode41', 13),
+ bcanalyzer.ParseTag('<UnkownCode41 op0=0 op1=4 op2=5/>'))
+ self.assertEquals((bcanalyzer.CLOSING_TAG, 'FOO_BAR', 9),
+ bcanalyzer.ParseTag('</FOO_BAR> \'/>trailing\''))
+ self.assertEquals((bcanalyzer.OPENING_TAG, 'A', 2),
+ bcanalyzer.ParseTag('<A>'))
+ self.assertEquals((bcanalyzer.OPENING_TAG, 'lower', 6),
+ bcanalyzer.ParseTag('<lower >'))
+ # An invalid tag (all numbers), but we allow for simplicity.
+ self.assertEquals((bcanalyzer.OPENING_TAG, '123', 4),
+ bcanalyzer.ParseTag('<123>'))
+ # Abominations that are allowed for simplicity.
+ self.assertEquals((bcanalyzer.SELF_CLOSING_TAG, 'FOO', 5),
+ bcanalyzer.ParseTag('</FOO/>'))
+ self.assertEquals((bcanalyzer.SELF_CLOSING_TAG, 'FOO', 4),
+ bcanalyzer.ParseTag('<FOO///////>'))
+ self.assertEquals((bcanalyzer.OPENING_TAG, 'FOO', 4),
+ bcanalyzer.ParseTag('<FOO>>>>>'))
+
+ # Invalid cases.
+ None3 = (None, None, None)
+ self.assertEquals(None3, bcanalyzer.ParseTag(''))
+ self.assertEquals(None3, bcanalyzer.ParseTag(' '))
+ self.assertEquals(None3, bcanalyzer.ParseTag('<>'))
+ self.assertEquals(None3, bcanalyzer.ParseTag('<> '))
+ self.assertEquals(None3, bcanalyzer.ParseTag('< >'))
+ self.assertEquals(None3, bcanalyzer.ParseTag('<<FOO>'))
+ self.assertEquals(None3, bcanalyzer.ParseTag('< FOO>'))
+ self.assertEquals(None3, bcanalyzer.ParseTag('<//FOO>'))
+ self.assertEquals(None3, bcanalyzer.ParseTag('</ FOO>'))
+ self.assertEquals(None3, bcanalyzer.ParseTag('< FOO />'))
+ self.assertEquals(None3, bcanalyzer.ParseTag('<FOO<>'))
+ self.assertEquals(None3, bcanalyzer.ParseTag('<NOEND'))
+ self.assertEquals(None3, bcanalyzer.ParseTag('some text'))
+ self.assertEquals(None3, bcanalyzer.ParseTag(' <UNTRIMMED>'))
+ self.assertEquals(None3, bcanalyzer.ParseTag('&lt;AAA&gt;'))
+
+ def testAnalyzer(self):
+ # Save global param in bcanalyzer.
+ saved_char_width_limit = bcanalyzer._CHAR_WIDTH_LIMIT
+
+ for width_limit, include_4byte_strings in [(2, False), (4, True)]:
+ # Tweak global param in bcanalyzer.
+ bcanalyzer._CHAR_WIDTH_LIMIT = width_limit
+
+ encoded_results = bcanalyzer.RunBcAnalyzerOnIntermediates(
+ ['test.o'], _TEST_TOOL_PREFIX, _TEST_OUTPUT_DIR)
+ results = concurrent.DecodeDictOfLists(
+ encoded_results, value_transform=ast.literal_eval)
+ self.assertEquals(['test.o'], results.keys())
+ str_list = results['test.o']
+
+ # See mock_bcanalyzer.py for details on the C++ test file.
+ expected = []
+ expected.append(_MakeString(8, ['Test1a', 0]))
+ expected.append(_MakeString(8, ['Test1b', 0]))
+ expected.append(_MakeString(8, ['Test2a', 0]))
+ expected.append(_MakeString(8, ['Test2b', 0]))
+ expected.append(_MakeString(16, ['Test3a', 0]))
+ expected.append(_MakeString(16, ['Test3b', 0]))
+ if include_4byte_strings:
+ expected.append(_MakeString(32, ['Test4a', 0]))
+ expected.append(_MakeString(32, ['Test4b', 0]))
+ expected.append(_MakeString(8, [1, 0, 0, 1, 1, 0]))
+ expected.append(_MakeString(8, [1, 0, 0, 1, 1, 1]))
+ expected.append(_MakeString(8, ['Test5a', 0]))
+ expected.append(_MakeString(8, ['Test5b', 1]))
+ expected.append(_MakeString(16, ['Test6a', 0]))
+ expected.append(_MakeString(16, ['Test6b', 1]))
+ if include_4byte_strings:
+ expected.append(_MakeString(32, ['Test7a', 0]))
+ expected.append(_MakeString(32, ['Test7b', 1]))
+ expected.append(_MakeString(8, ['Test8a', 0]))
+ expected.append(_MakeString(8, ['Test8b', 0]))
+ # Exclude |{u8a, u8b, u16a, u16b, u32a, u32b, u64a, u64b}|.
+ # Exclude |{s8empty, s16empty, s32empty}|.
+ expected.append(_MakeString(8, ['1a', 0]))
+ # Exclude |zeros|, which should be in .bss section.
+
+ self.assertEquals(expected, str_list)
+
+ # Restore globa param in bcanalyzer.
+ bcanalyzer._CHAR_WIDTH_LIMIT = saved_char_width_limit
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/chromium/tools/binary_size/libsupersize/concurrent.py b/chromium/tools/binary_size/libsupersize/concurrent.py
index 104308c05ee..b971d94518d 100644
--- a/chromium/tools/binary_size/libsupersize/concurrent.py
+++ b/chromium/tools/binary_size/libsupersize/concurrent.py
@@ -26,6 +26,7 @@ _silence_exceptions = False
# Used to pass parameters to forked processes without pickling.
_fork_params = None
+_fork_kwargs = None
class _ImmediateResult(object):
@@ -66,7 +67,7 @@ class _FuncWrapper(object):
def __call__(self, index, _=None):
try:
- return self._func(*_fork_params[index])
+ return self._func(*_fork_params[index], **_fork_kwargs)
except Exception, e:
# Only keep the exception type for builtin exception types or else risk
# further marshalling exceptions.
@@ -150,14 +151,18 @@ def _CheckForException(value):
sys.exit(1)
-def _MakeProcessPool(job_params):
+def _MakeProcessPool(job_params, **job_kwargs):
global _all_pools
global _fork_params
+ global _fork_kwargs
assert _fork_params is None
+ assert _fork_kwargs is None
pool_size = min(len(job_params), multiprocessing.cpu_count())
_fork_params = job_params
+ _fork_kwargs = job_kwargs
ret = multiprocessing.Pool(pool_size)
_fork_params = None
+ _fork_kwargs = None
if _all_pools is None:
_all_pools = []
atexit.register(_TerminatePools)
@@ -175,15 +180,18 @@ def ForkAndCall(func, args, decode_func=None):
pool = None
result = _ImmediateResult(func(*args))
else:
- pool = _MakeProcessPool([args])
+ pool = _MakeProcessPool([args]) # Omit |kwargs|.
result = pool.apply_async(_FuncWrapper(func), (0,))
pool.close()
return _WrappedResult(result, pool=pool, decode_func=decode_func)
-def BulkForkAndCall(func, arg_tuples):
+def BulkForkAndCall(func, arg_tuples, **kwargs):
"""Calls |func| in a fork'ed process for each set of args within |arg_tuples|.
+ Args:
+ kwargs: Common key word arguments to be passed to |func|.
+
Yields the return values as they come in.
"""
arg_tuples = list(arg_tuples)
@@ -192,10 +200,10 @@ def BulkForkAndCall(func, arg_tuples):
if DISABLE_ASYNC:
for args in arg_tuples:
- yield func(*args)
+ yield func(*args, **kwargs)
return
- pool = _MakeProcessPool(arg_tuples)
+ pool = _MakeProcessPool(arg_tuples, **kwargs)
wrapped_func = _FuncWrapper(func)
for result in pool.imap_unordered(wrapped_func, xrange(len(arg_tuples))):
_CheckForException(result)
@@ -215,7 +223,7 @@ def CallOnThread(func, *args, **kwargs):
return result
-def EncodeDictOfLists(d, key_transform=None):
+def EncodeDictOfLists(d, key_transform=None, value_transform=None):
"""Serializes a dict where values are lists of strings.
Does not support '' as keys, nor [''] as values.
@@ -226,7 +234,11 @@ def EncodeDictOfLists(d, key_transform=None):
if key_transform:
keys = (key_transform(k) for k in keys)
keys = '\x01'.join(keys)
- values = '\x01'.join('\x02'.join(x) for x in d.itervalues())
+ if value_transform:
+ values = '\x01'.join('\x02'.join(value_transform(y) for y in x) for x in
+ d.itervalues())
+ else:
+ values = '\x01'.join('\x02'.join(x) for x in d.itervalues())
return keys, values
diff --git a/chromium/tools/binary_size/libsupersize/concurrent_test.py b/chromium/tools/binary_size/libsupersize/concurrent_test.py
index 68f1fb8ae80..683e0e97d12 100755
--- a/chromium/tools/binary_size/libsupersize/concurrent_test.py
+++ b/chromium/tools/binary_size/libsupersize/concurrent_test.py
@@ -10,7 +10,8 @@ import unittest
import concurrent
-def _ForkTestHelper(test_instance, parent_pid, arg1, arg2, _=None):
+def _ForkTestHelper(arg1, arg2, pickle_me_not, test_instance, parent_pid):
+ _ = pickle_me_not # Suppress lint warning.
test_instance.assertNotEquals(os.getpid(), parent_pid)
return arg1 + arg2
@@ -96,12 +97,13 @@ class ConcurrentTest(unittest.TestCase):
def testForkAndCall_normal(self):
parent_pid = os.getpid()
result = concurrent.ForkAndCall(
- _ForkTestHelper, (self, parent_pid, 1, 2, Unpicklable()))
+ _ForkTestHelper, (1, 2, Unpicklable(), self, parent_pid))
self.assertEquals(3, result.get())
def testForkAndCall_exception(self):
parent_pid = os.getpid()
- result = concurrent.ForkAndCall(_ForkTestHelper, (self, parent_pid, 1, 'a'))
+ result = concurrent.ForkAndCall(
+ _ForkTestHelper, (1, 'a', None, self, parent_pid))
self.assertRaises(TypeError, result.get)
def testBulkForkAndCall_none(self):
@@ -111,20 +113,35 @@ class ConcurrentTest(unittest.TestCase):
def testBulkForkAndCall_few(self):
parent_pid = os.getpid()
results = concurrent.BulkForkAndCall(_ForkTestHelper, [
- (self, parent_pid, 1, 2, Unpicklable()),
- (self, parent_pid, 3, 4)])
+ (1, 2, Unpicklable(), self, parent_pid),
+ (3, 4, None, self, parent_pid)])
+ self.assertEquals({3, 7}, set(results))
+
+ def testBulkForkAndCall_few_kwargs(self):
+ parent_pid = os.getpid()
+ results = concurrent.BulkForkAndCall(_ForkTestHelper,
+ [(1, 2, Unpicklable()), (3, 4, None)],
+ test_instance=self, parent_pid=parent_pid)
self.assertEquals({3, 7}, set(results))
def testBulkForkAndCall_many(self):
parent_pid = os.getpid()
- args = [(self, parent_pid, 1, 2, Unpicklable())] * 100
+ args = [(1, 2, Unpicklable(), self, parent_pid) for _ in xrange(100)]
results = concurrent.BulkForkAndCall(_ForkTestHelper, args)
self.assertEquals([3] * 100, list(results))
+ def testBulkForkAndCall_many_kwargs(self):
+ parent_pid = os.getpid()
+ args = [(1, 2) for _ in xrange(100)]
+ results = concurrent.BulkForkAndCall(
+ _ForkTestHelper, args, pickle_me_not=Unpicklable(), test_instance=self,
+ parent_pid=parent_pid)
+ self.assertEquals([3] * 100, list(results))
+
def testBulkForkAndCall_exception(self):
parent_pid = os.getpid()
results = concurrent.BulkForkAndCall(_ForkTestHelper, [
- (self, parent_pid, 1, 'a')])
+ (1, 'a', self, parent_pid)])
self.assertRaises(TypeError, results.next)
if __name__ == '__main__':
diff --git a/chromium/tools/binary_size/libsupersize/console.py b/chromium/tools/binary_size/libsupersize/console.py
index c6756e532a9..0517acf9de5 100644
--- a/chromium/tools/binary_size/libsupersize/console.py
+++ b/chromium/tools/binary_size/libsupersize/console.py
@@ -23,8 +23,8 @@ import diff
import file_format
import match_util
import models
-import nm
import path_util
+import string_extract
# Number of lines before using less for Print().
@@ -122,7 +122,8 @@ class _Session(object):
elf_path = self._ElfPathForSymbol(
size_info, tool_prefix, elf_path)
- address, offset, _ = nm.LookupElfRodataInfo(elf_path, tool_prefix)
+ address, offset, _ = string_extract.LookupElfRodataInfo(
+ elf_path, tool_prefix)
adjust = offset - address
ret = []
with open(elf_path, 'rb') as f:
@@ -304,9 +305,11 @@ class _Session(object):
size_info, tool_prefix, elf_path)
args = [path_util.GetObjDumpPath(tool_prefix), '--disassemble', '--source',
- '--line-numbers', '--demangle',
- '--start-address=0x%x' % symbol.address,
+ '--line-numbers', '--start-address=0x%x' % symbol.address,
'--stop-address=0x%x' % symbol.end_address, elf_path]
+ # llvm-objdump does not support '--demangle' switch.
+ if not self._tool_prefix_finder.IsLld():
+ args.append('--demangle')
if self._disassemble_prefix_len is None:
prefix_len = self._DetectDisassemblePrefixLen(args)
if prefix_len is not None:
@@ -469,9 +472,11 @@ def Run(args, parser):
output_directory_finder = path_util.OutputDirectoryFinder(
value=args.output_directory,
any_path_within_output_directory=args.inputs[0])
+ linker_name = size_infos[-1].metadata.get(models.METADATA_LINKER_NAME)
tool_prefix_finder = path_util.ToolPrefixFinder(
value=args.tool_prefix,
- output_directory_finder=output_directory_finder)
+ output_directory_finder=output_directory_finder,
+ linker_name=linker_name)
session = _Session(size_infos, output_directory_finder, tool_prefix_finder)
if args.query:
diff --git a/chromium/tools/binary_size/libsupersize/file_format.py b/chromium/tools/binary_size/libsupersize/file_format.py
index 6ee24654478..cfe6f63d93a 100644
--- a/chromium/tools/binary_size/libsupersize/file_format.py
+++ b/chromium/tools/binary_size/libsupersize/file_format.py
@@ -2,13 +2,77 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-"""Deals with loading & saving .size files."""
+"""Deals with loading & saving .size files.
+
+The .size file is written in the following format. There are no section
+delimeters, instead the end of a section is usually determined by a row count
+on the first line of a section, followed by that amount of rows. In other
+cases, the sections have a known size.
+
+Header
+------
+4 lines long.
+Line 0 of the file is a header comment.
+Line 1 is the serialization version of the file.
+Line 2 is the number of characters in the metadata string.
+Line 3 is the metadata string, a stringified JSON object.
+
+Path list
+---------
+A list of paths. The first line is the size of the list,
+and the next N lines that follow are items in the list. Each item is a tuple
+of (object_path, source_path) where the two parts are tab seperated.
+
+Component list
+--------------
+A list of components. The first line is the size of the list,
+and the next N lines that follow are items in the list. Each item is a unique
+COMPONENT which is referenced later.
+This section is only present if 'has_components' is True in the metadata.
+
+Symbol counts
+-------------
+2 lines long.
+The first line is a tab seperated list of section names.
+The second line is a tab seperated list of symbol group lengths, in the same
+order as the previous line.
+
+Numeric values
+--------------
+In each section, the number of rows is the same as the number of section names
+in Symbol counts. The values on a row are space seperated, in the order of the
+symbols in each group.
+
+Addressses
+~~~~~~~~~~
+Symbol start addresses which are delta-encoded.
+
+Sizes
+~~~~~
+The number of bytes this symbol takes up.
+
+Path indicies
+~~~~~~~~~~~~~
+Indicies that reference paths in the prior Path list section. Delta-encoded.
+
+Component indicies
+~~~~~~~~~~~~~~~~~~
+Indicies that reference components in the prior Component list section.
+Delta-encoded.
+
+Symbols
+-------
+The final section contains details info on each symbol. Each line represents
+a single symbol. Values are tab seperated and follow this format:
+symbol.full_name, symbol.num_aliases, symbol.flags
+|num_aliases| will be omitted if the aliases of the symbol are the same as the
+previous line. |flags| will be omitted if there are no flags.
+"""
import cStringIO
-import calendar
import contextlib
-import datetime
import gzip
+import itertools
import json
import logging
import os
@@ -30,11 +94,20 @@ def _LogSize(file_obj, desc):
def _SaveSizeInfoToFile(size_info, file_obj):
+ """Saves size info to a .size file.
+
+ Args:
+ size_info: Data to write to the file
+ file_object: File opened for writing
+ """
+ # Created by supersize header
file_obj.write('# Created by //tools/binary_size\n')
file_obj.write('%s\n' % _SERIALIZATION_VERSION)
+ # JSON metadata
headers = {
'metadata': size_info.metadata,
'section_sizes': size_info.section_sizes,
+ 'has_components': True,
}
metadata_str = json.dumps(headers, file_obj, indent=2, sort_keys=True)
file_obj.write('%d\n' % len(metadata_str))
@@ -45,19 +118,33 @@ def _SaveSizeInfoToFile(size_info, file_obj):
# Store a single copy of all paths and have them referenced by index.
unique_path_tuples = sorted(set(
(s.object_path, s.source_path) for s in size_info.raw_symbols))
- path_tuples = dict.fromkeys(unique_path_tuples)
- for i, tup in enumerate(unique_path_tuples):
- path_tuples[tup] = i
+ path_tuples = {tup: i for i, tup in enumerate(unique_path_tuples)}
file_obj.write('%d\n' % len(unique_path_tuples))
file_obj.writelines('%s\t%s\n' % pair for pair in unique_path_tuples)
_LogSize(file_obj, 'paths') # For libchrome, adds 200kb.
+ # Store a single copy of all components and have them referenced by index.
+ unique_components = sorted(set(s.component for s in size_info.raw_symbols))
+ components = {comp: i for i, comp in enumerate(unique_components)}
+ file_obj.write('%d\n' % len(unique_components))
+ file_obj.writelines('%s\n' % comp for comp in unique_components)
+ _LogSize(file_obj, 'components')
+
# Symbol counts by section.
by_section = size_info.raw_symbols.GroupedBySectionName()
file_obj.write('%s\n' % '\t'.join(g.name for g in by_section))
file_obj.write('%s\n' % '\t'.join(str(len(g)) for g in by_section))
+ # Addresses, sizes, path indicies, component indicies
def write_numeric(func, delta=False):
+ """Write the result of func(symbol) for each symbol in each symbol group.
+
+ Each line written represents one symbol group in |by_section|.
+ The values in each line are space seperated and are the result of calling
+ |func| with the Nth symbol in the group.
+
+ If |delta| is True, the differences in values are written instead.
+ """
for group in by_section:
prev_value = 0
last_sym = group[-1]
@@ -79,6 +166,8 @@ def _SaveSizeInfoToFile(size_info, file_obj):
write_numeric(lambda s: path_tuples[(s.object_path, s.source_path)],
delta=True)
_LogSize(file_obj, 'path indices') # For libchrome: adds 125kb.
+ write_numeric(lambda s: components[s.component], delta=True)
+ _LogSize(file_obj, 'component indices')
prev_aliases = None
for group in by_section:
@@ -93,82 +182,145 @@ def _SaveSizeInfoToFile(size_info, file_obj):
_LogSize(file_obj, 'names (final)') # For libchrome: adds 3.5mb.
+def _ReadLine(file_iter):
+ """Read a line from a file object iterator and remove the newline character.
+
+ Args:
+ file_iter: File object iterator
+
+ Returns:
+ String
+ """
+ # str[:-1] removes the last character from a string, specifically the newline
+ return next(file_iter)[:-1]
+
+
+def _ReadValuesFromLine(file_iter, split):
+ """Read a list of values from a line in a file object iterator.
+
+ Args:
+ file_iter: File object iterator
+ split: Splits the line with the given string
+
+ Returns:
+ List of string values
+ """
+ return _ReadLine(file_iter).split(split)
+
+
def _LoadSizeInfoFromFile(file_obj, size_path):
- """Loads a size_info from the given file."""
+ """Loads a size_info from the given file.
+
+ See _SaveSizeInfoToFile for details on the .size file format.
+
+ Args:
+ file_obj: File to read, should be a GzipFile
+ """
lines = iter(file_obj)
- next(lines) # Comment line.
- actual_version = next(lines)[:-1]
+ _ReadLine(lines) # Line 0: Created by supersize header
+ actual_version = _ReadLine(lines)
assert actual_version == _SERIALIZATION_VERSION, (
'Version mismatch. Need to write some upgrade code.')
- json_len = int(next(lines))
+ # JSON metadata
+ json_len = int(_ReadLine(lines))
json_str = file_obj.read(json_len)
+
headers = json.loads(json_str)
section_sizes = headers['section_sizes']
metadata = headers.get('metadata')
+ has_components = headers.get('has_components', False)
lines = iter(file_obj)
- next(lines) # newline after closing } of json.
+ _ReadLine(lines)
+
+ # Path list
+ num_path_tuples = int(_ReadLine(lines)) # Line 4 - number of paths in list
+ # Read the path list values and store for later
+ path_tuples = [_ReadValuesFromLine(lines, split='\t')
+ for _ in xrange(num_path_tuples)]
- num_path_tuples = int(next(lines))
- path_tuples = [None] * num_path_tuples
- for i in xrange(num_path_tuples):
- path_tuples[i] = next(lines)[:-1].split('\t')
+ # Component list
+ if has_components:
+ num_components = int(_ReadLine(lines)) # number of components in list
+ components = [_ReadLine(lines) for _ in xrange(num_components)]
- section_names = next(lines)[:-1].split('\t')
- section_counts = [int(c) for c in next(lines)[:-1].split('\t')]
+ # Symbol counts by section.
+ section_names = _ReadValuesFromLine(lines, split='\t')
+ section_counts = [int(c) for c in _ReadValuesFromLine(lines, split='\t')]
+ # Addresses, sizes, path indicies, component indicies
def read_numeric(delta=False):
+ """Read numeric values, where each line corresponds to a symbol group.
+
+ The values in each line are space seperated.
+ If |delta| is True, the numbers are read as a value to add to the sum of the
+ prior values in the line, or as the amount to change by.
+ """
ret = []
delta_multiplier = int(delta)
for _ in section_counts:
value = 0
- fields = next(lines).split(' ')
- for i, f in enumerate(fields):
+ fields = []
+ for f in _ReadValuesFromLine(lines, split=' '):
value = value * delta_multiplier + int(f)
- fields[i] = value
+ fields.append(value)
ret.append(fields)
return ret
addresses = read_numeric(delta=True)
sizes = read_numeric(delta=False)
path_indices = read_numeric(delta=True)
+ if has_components:
+ component_indices = read_numeric(delta=True)
+ else:
+ component_indices = [None] * len(section_names)
raw_symbols = [None] * sum(section_counts)
symbol_idx = 0
- for section_index, cur_section_name in enumerate(section_names):
+ for (cur_section_name, cur_section_count, cur_addresses, cur_sizes,
+ cur_path_indicies, cur_component_indices) in itertools.izip(
+ section_names, section_counts, addresses, sizes, path_indices,
+ component_indices):
alias_counter = 0
- for i in xrange(section_counts[section_index]):
- parts = next(lines)[:-1].split('\t')
+ for i in xrange(cur_section_count):
+ parts = _ReadValuesFromLine(lines, split='\t')
+ full_name = parts[0]
flags_part = None
aliases_part = None
+ # aliases_part or flags_part may have been omitted.
if len(parts) == 3:
+ # full_name aliases_part flags_part
aliases_part = parts[1]
flags_part = parts[2]
elif len(parts) == 2:
if parts[1][0] == '0':
+ # full_name aliases_part
aliases_part = parts[1]
else:
+ # full_name flags_part
flags_part = parts[1]
- full_name = parts[0]
# Use a bit less RAM by using the same instance for this common string.
if full_name == models.STRING_LITERAL_NAME:
full_name = models.STRING_LITERAL_NAME
flags = int(flags_part, 16) if flags_part else 0
num_aliases = int(aliases_part, 16) if aliases_part else 0
+ # Skip the constructor to avoid default value checks
new_sym = models.Symbol.__new__(models.Symbol)
new_sym.section_name = cur_section_name
- new_sym.address = addresses[section_index][i]
- new_sym.size = sizes[section_index][i]
new_sym.full_name = full_name
- paths = path_tuples[path_indices[section_index][i]]
- new_sym.object_path = paths[0]
- new_sym.source_path = paths[1]
+ new_sym.address = cur_addresses[i]
+ new_sym.size = cur_sizes[i]
+ paths = path_tuples[cur_path_indicies[i]]
+ new_sym.object_path, new_sym.source_path = paths
+ component = components[cur_component_indices[i]] if has_components else ''
+ new_sym.component = component
new_sym.flags = flags
- new_sym.padding = 0 # Derived
- new_sym.template_name = '' # Derived
- new_sym.name = '' # Derived
+ # Derived
+ new_sym.padding = 0
+ new_sym.template_name = ''
+ new_sym.name = ''
if num_aliases:
assert alias_counter == 0
diff --git a/chromium/tools/binary_size/libsupersize/html_report.py b/chromium/tools/binary_size/libsupersize/html_report.py
index c47e354b784..fe8c3dd090e 100644
--- a/chromium/tools/binary_size/libsupersize/html_report.py
+++ b/chromium/tools/binary_size/libsupersize/html_report.py
@@ -4,227 +4,247 @@
"""Creates an html report that allows you to view binary size by component."""
-import argparse
+import codecs
+import collections
import json
import logging
import os
-import shutil
-import sys
import archive
-import path_util
-
-
-# Node dictionary keys. These are output in json read by the webapp so
-# keep them short to save file size.
-# Note: If these change, the webapp must also change.
-_METHOD_COUNT_MODE_KEY = 'methodCountMode'
-_NODE_TYPE_KEY = 'k'
-_NODE_TYPE_BUCKET = 'b'
-_NODE_TYPE_PATH = 'p'
-_NODE_TYPE_SYMBOL = 's'
-_NODE_NAME_KEY = 'n'
-_NODE_CHILDREN_KEY = 'children'
-_NODE_SYMBOL_TYPE_KEY = 't'
-_NODE_SYMBOL_TYPE_VTABLE = 'v'
-_NODE_SYMBOL_TYPE_GENERATED = '*'
-_NODE_SYMBOL_SIZE_KEY = 'value'
-_NODE_MAX_DEPTH_KEY = 'maxDepth'
-_NODE_LAST_PATH_ELEMENT_KEY = 'lastPathElement'
-
-# The display name of the bucket where we put symbols without path.
-_NAME_NO_PATH_BUCKET = '(No Path)'
-
-# Try to keep data buckets smaller than this to avoid killing the
-# graphing lib.
-_BIG_BUCKET_LIMIT = 3000
-
-
-def _GetOrMakeChildNode(node, node_type, name):
- child = node[_NODE_CHILDREN_KEY].get(name)
- if child is None:
- child = {
- _NODE_TYPE_KEY: node_type,
- _NODE_NAME_KEY: name,
+import diff
+import models
+
+
+_SYMBOL_TYPE_VTABLE = 'v'
+_SYMBOL_TYPE_GENERATED = '*'
+_SYMBOL_TYPE_DEX_METHOD = 'm'
+_SYMBOL_TYPE_OTHER = 'o'
+
+_COMPACT_FILE_PATH_KEY = 'p'
+_COMPACT_FILE_COMPONENT_INDEX_KEY = 'c'
+_COMPACT_FILE_SYMBOLS_KEY = 's'
+_COMPACT_SYMBOL_NAME_KEY = 'n'
+_COMPACT_SYMBOL_BYTE_SIZE_KEY = 'b'
+_COMPACT_SYMBOL_TYPE_KEY = 't'
+_COMPACT_SYMBOL_COUNT_KEY = 'u'
+
+_SMALL_SYMBOL_DESCRIPTIONS = {
+ 'b': 'Other small uninitialized data',
+ 'd': 'Other small initialized data',
+ 'r': 'Other small readonly data',
+ 't': 'Other small code',
+ 'v': 'Other small vtable entries',
+ '*': 'Other small generated symbols',
+ 'x': 'Other small dex non-method entries',
+ 'm': 'Other small dex methods',
+ 'p': 'Other small locale pak entries',
+ 'P': 'Other small non-locale pak entries',
+ 'o': 'Other small entries',
+}
+
+_DEFAULT_SYMBOL_COUNT = 250000
+
+
+def _GetSymbolType(symbol):
+ symbol_type = symbol.section
+ if symbol.name.endswith('[vtable]'):
+ symbol_type = _SYMBOL_TYPE_VTABLE
+ elif symbol.name.endswith(']'):
+ symbol_type = _SYMBOL_TYPE_GENERATED
+ if symbol_type not in _SMALL_SYMBOL_DESCRIPTIONS:
+ symbol_type = _SYMBOL_TYPE_OTHER
+ return symbol_type
+
+
+def _GetOrAddFileNode(symbol, file_nodes, components):
+ path = symbol.source_path or symbol.object_path
+ file_node = file_nodes.get(path)
+ if file_node is None:
+ component_index = components.GetOrAdd(symbol.component)
+ file_node = {
+ _COMPACT_FILE_PATH_KEY: path,
+ _COMPACT_FILE_COMPONENT_INDEX_KEY: component_index,
+ _COMPACT_FILE_SYMBOLS_KEY: [],
}
- if node_type != _NODE_TYPE_SYMBOL:
- child[_NODE_CHILDREN_KEY] = {}
- node[_NODE_CHILDREN_KEY][name] = child
- else:
- assert child[_NODE_TYPE_KEY] == node_type
- return child
-
-
-def _SplitLargeBucket(bucket):
- """Split the given node into sub-buckets when it's too big."""
- old_children = bucket[_NODE_CHILDREN_KEY]
- count = 0
- for symbol_type, symbol_bucket in old_children.iteritems():
- count += len(symbol_bucket[_NODE_CHILDREN_KEY])
- if count > _BIG_BUCKET_LIMIT:
- new_children = {}
- bucket[_NODE_CHILDREN_KEY] = new_children
- current_bucket = None
- index = 0
- for symbol_type, symbol_bucket in old_children.iteritems():
- for symbol_name, value in symbol_bucket[_NODE_CHILDREN_KEY].iteritems():
- if index % _BIG_BUCKET_LIMIT == 0:
- group_no = (index / _BIG_BUCKET_LIMIT) + 1
- node_name = '%s subgroup %d' % (_NAME_NO_PATH_BUCKET, group_no)
- current_bucket = _GetOrMakeChildNode(
- bucket, _NODE_TYPE_PATH, node_name)
- index += 1
- symbol_size = value[_NODE_SYMBOL_SIZE_KEY]
- _AddSymbolIntoFileNode(current_bucket, symbol_type, symbol_name,
- symbol_size, True)
-
-
-def _MakeChildrenDictsIntoLists(node):
- """Recursively converts all children from dicts -> lists."""
- children = node.get(_NODE_CHILDREN_KEY)
- if children:
- children = children.values() # Convert dict -> list.
- node[_NODE_CHILDREN_KEY] = children
- for child in children:
- _MakeChildrenDictsIntoLists(child)
- if len(children) > _BIG_BUCKET_LIMIT:
- logging.warning('Bucket found with %d entries. Might be unusable.',
- len(children))
-
-
-def _CombineSingleChildNodes(node):
- """Collapse "java"->"com"->"google" into ."java/com/google"."""
- children = node.get(_NODE_CHILDREN_KEY)
- if children:
- child = children[0]
- if len(children) == 1 and node[_NODE_TYPE_KEY] == child[_NODE_TYPE_KEY]:
- node[_NODE_NAME_KEY] = '{}/{}'.format(
- node[_NODE_NAME_KEY], child[_NODE_NAME_KEY])
- node[_NODE_CHILDREN_KEY] = child[_NODE_CHILDREN_KEY]
- _CombineSingleChildNodes(node)
- else:
- for child in children:
- _CombineSingleChildNodes(child)
-
-
-def _AddSymbolIntoFileNode(node, symbol_type, symbol_name, symbol_size,
- min_symbol_size):
- """Puts symbol into the file path node |node|."""
- node[_NODE_LAST_PATH_ELEMENT_KEY] = True
- # Don't bother with buckets when not including symbols.
- if min_symbol_size == 0:
- node = _GetOrMakeChildNode(node, _NODE_TYPE_BUCKET, symbol_type)
- node[_NODE_SYMBOL_TYPE_KEY] = symbol_type
-
- # 'node' is now the symbol-type bucket. Make the child entry.
- if not symbol_name or symbol_size >= min_symbol_size:
- node_name = symbol_name or '[Anonymous]'
- elif symbol_name.startswith('*'):
- node_name = symbol_name
+ file_nodes[path] = file_node
+ return file_node
+
+
+class IndexedSet(object):
+ """Set-like object where values are unique and indexed.
+
+ Values must be immutable.
+ """
+
+ def __init__(self):
+ self._index_dict = {} # Value -> Index dict
+ self.value_list = [] # List containing all the set items
+
+ def GetOrAdd(self, value):
+ """Get the index of the value in the list. Append it if not yet present."""
+ index = self._index_dict.get(value)
+ if index is None:
+ self.value_list.append(value)
+ index = len(self.value_list) - 1
+ self._index_dict[value] = index
+ return index
+
+
+def _MakeTreeViewList(symbols, include_all_symbols):
+ """Builds JSON data of the symbols for the tree view HTML report.
+
+ As the tree is built on the client-side, this function creates a flat list
+ of files, where each file object contains symbols that have the same path.
+
+ Args:
+ symbols: A SymbolGroup containing all symbols.
+ include_all_symbols: If true, include all symbols in the data file.
+ """
+ file_nodes = {}
+ components = IndexedSet()
+
+ # Build a container for symbols smaller than min_symbol_size
+ small_symbols = collections.defaultdict(dict)
+
+ # Dex methods (type "m") are whitelisted for the method_count mode on the
+ # UI. It's important to see details on all the methods.
+ dex_symbols = symbols.WhereIsDex()
+ ordered_symbols = dex_symbols.Inverted().Sorted()
+ if include_all_symbols:
+ symbol_count = len(ordered_symbols)
else:
- node_name = symbol_type
- node = _GetOrMakeChildNode(node, _NODE_TYPE_SYMBOL, node_name)
- node[_NODE_SYMBOL_SIZE_KEY] = node.get(_NODE_SYMBOL_SIZE_KEY, 0) + symbol_size
- node[_NODE_SYMBOL_TYPE_KEY] = symbol_type
-
-
-def _MakeCompactTree(symbols, min_symbol_size, method_count_mode):
- if method_count_mode:
- # Include all symbols and avoid bucket nodes.
- min_symbol_size = -1
- result = {
- _NODE_NAME_KEY: '/',
- _NODE_CHILDREN_KEY: {},
- _NODE_TYPE_KEY: 'p',
- _NODE_MAX_DEPTH_KEY: 0,
- _METHOD_COUNT_MODE_KEY: bool(method_count_mode),
+ symbol_count = max(_DEFAULT_SYMBOL_COUNT - len(dex_symbols), 0)
+
+ main_symbols = dex_symbols + ordered_symbols[:symbol_count]
+ extra_symbols = ordered_symbols[symbol_count:]
+
+ # Bundle symbols by the file they belong to,
+ # and add all the file buckets into file_nodes
+ for symbol in main_symbols:
+ symbol_type = _GetSymbolType(symbol)
+ symbol_size = round(symbol.pss, 2)
+ if symbol_size.is_integer():
+ symbol_size = int(symbol_size)
+ symbol_count = 1
+ if symbol.IsDelta() and symbol.diff_status == models.DIFF_STATUS_REMOVED:
+ symbol_count = -1
+
+ file_node = _GetOrAddFileNode(symbol, file_nodes, components)
+
+ is_dex_method = symbol_type == _SYMBOL_TYPE_DEX_METHOD
+ symbol_entry = {
+ _COMPACT_SYMBOL_NAME_KEY: symbol.template_name,
+ _COMPACT_SYMBOL_TYPE_KEY: symbol_type,
+ _COMPACT_SYMBOL_BYTE_SIZE_KEY: symbol_size,
+ }
+ # We use symbol count for the method count mode in the diff mode report.
+ # Negative values are used to indicate a symbol was removed, so it should
+ # count as -1 rather than the default, 1.
+ # We don't care about accurate counts for other symbol types currently,
+ # so this data is only included for methods.
+ if is_dex_method and symbol_count != 1:
+ symbol_entry[_COMPACT_SYMBOL_COUNT_KEY] = symbol_count
+ file_node[_COMPACT_FILE_SYMBOLS_KEY].append(symbol_entry)
+
+ for symbol in extra_symbols:
+ symbol_type = _GetSymbolType(symbol)
+
+ file_node = _GetOrAddFileNode(symbol, file_nodes, components)
+ path = file_node[_COMPACT_FILE_PATH_KEY]
+
+ small_type_symbol = small_symbols[path].get(symbol_type)
+ if small_type_symbol is None:
+ small_type_symbol = {
+ _COMPACT_SYMBOL_NAME_KEY: _SMALL_SYMBOL_DESCRIPTIONS[symbol_type],
+ _COMPACT_SYMBOL_TYPE_KEY: symbol_type,
+ _COMPACT_SYMBOL_BYTE_SIZE_KEY: 0,
+ }
+ small_symbols[path][symbol_type] = small_type_symbol
+ file_node[_COMPACT_FILE_SYMBOLS_KEY].append(small_type_symbol)
+
+ small_type_symbol[_COMPACT_SYMBOL_BYTE_SIZE_KEY] += symbol.pss
+
+ meta = {
+ 'components': components.value_list,
+ 'total': symbols.pss,
}
- for symbol in symbols:
- file_path = symbol.source_path or symbol.object_path or _NAME_NO_PATH_BUCKET
- node = result
- depth = 0
- for path_part in file_path.split(os.path.sep):
- if not path_part:
- continue
- depth += 1
- node = _GetOrMakeChildNode(node, _NODE_TYPE_PATH, path_part)
-
- symbol_type = symbol.section
- if symbol.name.endswith('[vtable]'):
- symbol_type = _NODE_SYMBOL_TYPE_VTABLE
- elif symbol.name.endswith(']'):
- symbol_type = _NODE_SYMBOL_TYPE_GENERATED
- symbol_size = 1 if method_count_mode else symbol.pss
- _AddSymbolIntoFileNode(node, symbol_type, symbol.template_name, symbol_size,
- min_symbol_size)
- depth += 2
- result[_NODE_MAX_DEPTH_KEY] = max(result[_NODE_MAX_DEPTH_KEY], depth)
-
- # The (no path) bucket can be extremely large if we failed to get
- # path information. Split it into subgroups if needed.
- no_path_bucket = result[_NODE_CHILDREN_KEY].get(_NAME_NO_PATH_BUCKET)
- if no_path_bucket and min_symbol_size == 0:
- _SplitLargeBucket(no_path_bucket)
-
- _MakeChildrenDictsIntoLists(result)
- _CombineSingleChildNodes(result)
-
- return result
-
-
-def _CopyTemplateFiles(dest_dir):
- d3_out = os.path.join(dest_dir, 'd3')
- if not os.path.exists(d3_out):
- os.makedirs(d3_out, 0755)
- d3_src = os.path.join(path_util.SRC_ROOT, 'third_party', 'd3', 'src')
- template_src = os.path.join(os.path.dirname(__file__), 'template')
- shutil.copy(os.path.join(d3_src, 'LICENSE'), d3_out)
- shutil.copy(os.path.join(d3_src, 'd3.js'), d3_out)
- shutil.copy(os.path.join(template_src, 'index.html'), dest_dir)
- shutil.copy(os.path.join(template_src, 'D3SymbolTreeMap.js'), dest_dir)
+ return meta, file_nodes.values()
+
+
+def _MakeDirIfDoesNotExist(rel_path):
+ """Ensures a directory exists."""
+ abs_path = os.path.abspath(rel_path)
+ try:
+ os.makedirs(abs_path)
+ except OSError:
+ if not os.path.isdir(abs_path):
+ raise
def AddArguments(parser):
parser.add_argument('input_file',
help='Path to input .size file.')
- parser.add_argument('--report-dir', metavar='PATH', required=True,
- help='Write output to the specified directory. An HTML '
- 'report is generated here.')
- parser.add_argument('--include-bss', action='store_true',
- help='Include symbols from .bss (which consume no real '
- 'space)')
- parser.add_argument('--min-symbol-size', type=float, default=1024,
- help='Minimum size (PSS) for a symbol to be included as '
- 'an independent node.')
- parser.add_argument('--method-count', action='store_true',
- help='Show dex method count rather than size')
+ parser.add_argument('--report-file', metavar='PATH', required=True,
+ help='Write generated data to the specified '
+ '.ndjson file.')
+ parser.add_argument('--all-symbols', action='store_true',
+ help='Include all symbols. Will cause the data file to '
+ 'take longer to load.')
+ parser.add_argument('--diff-with',
+ help='Diffs the input_file against an older .size file')
def Run(args, parser):
if not args.input_file.endswith('.size'):
parser.error('Input must end with ".size"')
+ if args.diff_with and not args.diff_with.endswith('.size'):
+ parser.error('Diff input must end with ".size"')
+ if not args.report_file.endswith('.ndjson'):
+ parser.error('Output must end with ".ndjson"')
logging.info('Reading .size file')
size_info = archive.LoadAndPostProcessSizeInfo(args.input_file)
- symbols = size_info.raw_symbols
- if args.method_count:
- symbols = symbols.WhereInSection('m')
- elif not args.include_bss:
- symbols = symbols.WhereInSection('b').Inverted()
-
- # Copy report boilerplate into output directory. This also proves that the
- # output directory is safe for writing, so there should be no problems writing
- # the nm.out file later.
- _CopyTemplateFiles(args.report_dir)
+ if args.diff_with:
+ before_size_info = archive.LoadAndPostProcessSizeInfo(args.diff_with)
+ after_size_info = size_info
+ size_info = diff.Diff(before_size_info, after_size_info)
+ symbols = size_info.raw_symbols
+ symbols = symbols.WhereDiffStatusIs(models.DIFF_STATUS_UNCHANGED).Inverted()
+ else:
+ symbols = size_info.raw_symbols
logging.info('Creating JSON objects')
- tree_root = _MakeCompactTree(symbols, args.min_symbol_size, args.method_count)
+ meta, tree_nodes = _MakeTreeViewList(symbols, args.all_symbols)
+ meta.update({
+ 'diff_mode': bool(args.diff_with),
+ 'section_sizes': size_info.section_sizes,
+ })
+ if args.diff_with:
+ meta.update({
+ 'before_metadata': size_info.before.metadata,
+ 'after_metadata': size_info.after.metadata,
+ })
+ else:
+ meta['metadata'] = size_info.metadata
logging.info('Serializing JSON')
- with open(os.path.join(args.report_dir, 'data.js'), 'w') as out_file:
- out_file.write('var tree_data=')
+ # Write newline-delimited JSON file
+ with codecs.open(args.report_file, 'w', encoding='ascii') as out_file:
# Use separators without whitespace to get a smaller file.
- json.dump(tree_root, out_file, ensure_ascii=False, check_circular=False,
- separators=(',', ':'))
+ json_dump_args = {
+ 'separators': (',', ':'),
+ 'ensure_ascii': True,
+ 'check_circular': False,
+ }
+
+ json.dump(meta, out_file, **json_dump_args)
+ out_file.write('\n')
+
+ for tree_node in tree_nodes:
+ json.dump(tree_node, out_file, **json_dump_args)
+ out_file.write('\n')
- logging.warning('Report saved to %s/index.html', args.report_dir)
+ logging.warning('Report saved to %s', args.report_file)
+ logging.warning('Open server by running: \n'
+ 'tools/binary_size/supersize start_server %s',
+ args.report_file)
diff --git a/chromium/tools/binary_size/libsupersize/integration_test.py b/chromium/tools/binary_size/libsupersize/integration_test.py
index 8fd8e64f53d..01c6343ed23 100755
--- a/chromium/tools/binary_size/libsupersize/integration_test.py
+++ b/chromium/tools/binary_size/libsupersize/integration_test.py
@@ -27,7 +27,8 @@ import models
_SCRIPT_DIR = os.path.dirname(__file__)
_TEST_DATA_DIR = os.path.join(_SCRIPT_DIR, 'testdata')
-_TEST_OUTPUT_DIR = os.path.join(_TEST_DATA_DIR, 'mock_output_directory')
+_TEST_SOURCE_DIR = os.path.join(_TEST_DATA_DIR, 'mock_source_directory')
+_TEST_OUTPUT_DIR = os.path.join(_TEST_SOURCE_DIR, 'out', 'Release')
_TEST_TOOL_PREFIX = os.path.join(
os.path.abspath(_TEST_DATA_DIR), 'mock_toolchain', '')
_TEST_APK_ROOT_DIR = os.path.join(_TEST_DATA_DIR, 'mock_apk')
@@ -170,6 +171,7 @@ class IntegrationTest(unittest.TestCase):
# Override for testing. Lower the bar for compacting symbols, to allow
# smaller test cases to be created.
knobs.max_same_name_alias_count = 3
+ knobs.src_root = _TEST_SOURCE_DIR
apk_path = None
apk_so_path = None
if use_apk:
@@ -181,23 +183,29 @@ class IntegrationTest(unittest.TestCase):
pak_files = [_TEST_APK_PAK_PATH]
pak_info_file = _TEST_PAK_INFO_PATH
metadata = None
+ linker_name = 'gold'
if use_elf:
with _AddMocksToPath():
metadata = archive.CreateMetadata(
_TEST_MAP_PATH, elf_path, apk_path, _TEST_TOOL_PREFIX,
- output_directory)
+ output_directory, linker_name)
section_sizes, raw_symbols = archive.CreateSectionSizesAndSymbols(
map_path=_TEST_MAP_PATH, tool_prefix=_TEST_TOOL_PREFIX,
elf_path=elf_path, output_directory=output_directory,
apk_path=apk_path, apk_so_path=apk_so_path, metadata=metadata,
- pak_files=pak_files, pak_info_file=pak_info_file, knobs=knobs)
+ pak_files=pak_files, pak_info_file=pak_info_file,
+ linker_name=linker_name, knobs=knobs)
IntegrationTest.cached_size_info[cache_key] = archive.CreateSizeInfo(
section_sizes, raw_symbols, metadata=metadata)
return copy.deepcopy(IntegrationTest.cached_size_info[cache_key])
def _DoArchive(self, archive_path, use_output_directory=True, use_elf=True,
use_apk=False, use_pak=False, debug_measures=False):
- args = [archive_path, '--map-file', _TEST_MAP_PATH]
+ args = [
+ archive_path,
+ '--map-file', _TEST_MAP_PATH,
+ '--source-directory', _TEST_SOURCE_DIR,
+ ]
if use_output_directory:
# Let autodetection find output_directory when --elf-file is used.
if not use_elf:
@@ -322,67 +330,105 @@ class IntegrationTest(unittest.TestCase):
size_info2 = self._CloneSizeInfo(use_elf=False)
size_info1.metadata = {"foo": 1, "bar": [1,2,3], "baz": "yes"}
size_info2.metadata = {"foo": 1, "bar": [1,3], "baz": "yes"}
- size_info1.symbols -= size_info1.symbols[:2]
- size_info2.symbols -= size_info2.symbols[-3:]
- size_info1.symbols[1].size -= 10
+
+ size_info1.raw_symbols -= size_info1.raw_symbols[:2]
+ size_info2.raw_symbols -= size_info2.raw_symbols[-3:]
+ changed_sym = size_info1.raw_symbols.WhereNameMatches('Patcher::Name_')[0]
+ changed_sym.size -= 10
+ padding_sym = size_info2.raw_symbols.WhereNameMatches('symbol gap 0')[0]
+ padding_sym.padding += 20
+ padding_sym.size += 20
d = diff.Diff(size_info1, size_info2)
- d.symbols = d.symbols.Sorted()
+ d.raw_symbols = d.raw_symbols.Sorted()
+ self.assertEquals(d.raw_symbols.CountsByDiffStatus()[1:], [2, 2, 3])
+ changed_sym = d.raw_symbols.WhereNameMatches('Patcher::Name_')[0]
+ padding_sym = d.raw_symbols.WhereNameMatches('symbol gap 0')[0]
+ # Padding-only deltas should sort after all non-padding changes.
+ padding_idx = d.raw_symbols.index(padding_sym)
+ self.assertLess(d.raw_symbols.index(changed_sym), padding_idx)
+ # And before bss.
+ self.assertTrue(d.raw_symbols[padding_idx + 1].IsBss())
+
return describe.GenerateLines(d, verbose=True)
def test_Diff_Aliases1(self):
size_info1 = self._CloneSizeInfo()
size_info2 = self._CloneSizeInfo()
- # Removing 1 alias should not change the size.
+ # Find a list of exact 4 symbols with the same aliases in |size_info2|:
+ # text@2a0010: BarAlias()
+ # text@2a0010: FooAlias()
+ # text@2a0010: blink::ContiguousContainerBase::shrinkToFit() @ path1
+ # text@2a0010: blink::ContiguousContainerBase::shrinkToFit() @ path2
+ # The blink::...::shrinkToFit() group has another member:
+ # text@2a0000: blink::ContiguousContainerBase::shrinkToFit() @ path3
a1, _, _, _ = (
size_info2.raw_symbols.Filter(lambda s: s.num_aliases == 4)[0].aliases)
+ # Remove FooAlias().
size_info2.raw_symbols -= [a1]
a1.aliases.remove(a1)
+
+ # From |size_info1| -> |size_info2|: 1 symbol is deleted.
d = diff.Diff(size_info1, size_info2)
+ # Total size should not change.
self.assertEquals(d.raw_symbols.pss, 0)
- self.assertEquals((0, 0, 1), _DiffCounts(d.raw_symbols))
- self.assertEquals((0, 0, 1), _DiffCounts(d.symbols.GroupedByFullName()))
-
- # Adding one alias should not change size.
+ # 1 symbol is erased, and PSS distributed among 3 remaining aliases, and
+ # considered as change.
+ self.assertEquals((3, 0, 1), _DiffCounts(d.raw_symbols))
+ # Grouping combines 2 x blink::ContiguousContainerBase::shrinkToFit(), so
+ # now ther are 2 changed aliases.
+ self.assertEquals((2, 0, 1), _DiffCounts(d.symbols.GroupedByFullName()))
+
+ # From |size_info2| -> |size_info1|: 1 symbol is added.
d = diff.Diff(size_info2, size_info1)
self.assertEquals(d.raw_symbols.pss, 0)
- self.assertEquals((0, 1, 0), _DiffCounts(d.raw_symbols))
- self.assertEquals((0, 1, 0), _DiffCounts(d.symbols.GroupedByFullName()))
+ self.assertEquals((3, 1, 0), _DiffCounts(d.raw_symbols))
+ self.assertEquals((2, 1, 0), _DiffCounts(d.symbols.GroupedByFullName()))
def test_Diff_Aliases2(self):
size_info1 = self._CloneSizeInfo()
size_info2 = self._CloneSizeInfo()
- # Removing 2 aliases should not change the size.
+ # Same list of 4 symbols as before.
a1, _, a2, _ = (
size_info2.raw_symbols.Filter(lambda s: s.num_aliases == 4)[0].aliases)
+ # Remove BarAlias() and blink::...::shrinkToFit().
size_info2.raw_symbols -= [a1, a2]
a1.aliases.remove(a1)
a1.aliases.remove(a2)
+
+ # From |size_info1| -> |size_info2|: 2 symbols are deleted.
d = diff.Diff(size_info1, size_info2)
self.assertEquals(d.raw_symbols.pss, 0)
- self.assertEquals((0, 0, 2), _DiffCounts(d.raw_symbols))
- self.assertEquals((1, 0, 1), _DiffCounts(d.symbols.GroupedByFullName()))
+ self.assertEquals((2, 0, 2), _DiffCounts(d.raw_symbols))
+ self.assertEquals((2, 0, 1), _DiffCounts(d.symbols.GroupedByFullName()))
- # Adding 2 aliases should not change size.
+ # From |size_info2| -> |size_info1|: 2 symbols are added.
d = diff.Diff(size_info2, size_info1)
self.assertEquals(d.raw_symbols.pss, 0)
- self.assertEquals((0, 2, 0), _DiffCounts(d.raw_symbols))
- self.assertEquals((1, 1, 0), _DiffCounts(d.symbols.GroupedByFullName()))
+ self.assertEquals((2, 2, 0), _DiffCounts(d.raw_symbols))
+ self.assertEquals((2, 1, 0), _DiffCounts(d.symbols.GroupedByFullName()))
def test_Diff_Aliases4(self):
size_info1 = self._CloneSizeInfo()
size_info2 = self._CloneSizeInfo()
- # Removing all 4 aliases should change the size.
+ # Same list of 4 symbols as before.
a1, a2, a3, a4 = (
size_info2.raw_symbols.Filter(lambda s: s.num_aliases == 4)[0].aliases)
+
+ # Remove all 4 aliases.
size_info2.raw_symbols -= [a1, a2, a3, a4]
+
+ # From |size_info1| -> |size_info2|: 4 symbols are deleted.
d = diff.Diff(size_info1, size_info2)
+ self.assertEquals(d.raw_symbols.pss, -a1.size)
self.assertEquals((0, 0, 4), _DiffCounts(d.raw_symbols))
+ # When grouped, BarAlias() and FooAlias() are deleted, but the
+ # blink::...::shrinkToFit() has 1 remaining symbol, so is changed.
self.assertEquals((1, 0, 2), _DiffCounts(d.symbols.GroupedByFullName()))
- # Adding all 4 aliases should change size.
+ # From |size_info2| -> |size_info1|: 4 symbols are added.
d = diff.Diff(size_info2, size_info1)
self.assertEquals(d.raw_symbols.pss, a1.size)
self.assertEquals((0, 4, 0), _DiffCounts(d.raw_symbols))
diff --git a/chromium/tools/binary_size/libsupersize/linker_map_parser.py b/chromium/tools/binary_size/libsupersize/linker_map_parser.py
index edd0f91a751..679b90124c4 100644
--- a/chromium/tools/binary_size/libsupersize/linker_map_parser.py
+++ b/chromium/tools/binary_size/libsupersize/linker_map_parser.py
@@ -287,6 +287,7 @@ class MapFileParserLld(object):
_LINE_RE_V0 = re.compile(r'([0-9a-f]+)\s+([0-9a-f]+)\s+(\d+) ( *)(.*)')
_LINE_RE_V1 = re.compile(
r'\s*[0-9a-f]+\s+([0-9a-f]+)\s+([0-9a-f]+)\s+(\d+) ( *)(.*)')
+ _LINE_RE = [_LINE_RE_V0, _LINE_RE_V1]
def __init__(self, linker_name):
self._linker_name = linker_name
@@ -325,13 +326,13 @@ class MapFileParserLld(object):
# 00000000002010c0 0000000000000000 0 frame_dummy
# 00000000002010ed 0000000000000071 1 a.o:(.text)
# 00000000002010ed 0000000000000071 0 main
+ # Extract e.g., 'lld_v0' -> 0, or 'lld-lto_v1' -> 1.
+ map_file_version = int(self._linker_name.split('_v')[1])
+ pattern = MapFileParserLld._LINE_RE[map_file_version]
+
sym_maker = _SymbolMaker()
cur_section = None
cur_section_is_useful = None
- if self._linker_name.endswith('v1'):
- pattern = self._LINE_RE_V1
- else:
- pattern = self._LINE_RE_V0
for line in lines:
m = pattern.match(line)
@@ -391,19 +392,58 @@ class MapFileParserLld(object):
return self._section_sizes, sym_maker.syms
-def DetectLinkerNameFromMapFileHeader(first_line):
+def _DetectLto(lines):
+ """Scans LLD linker map file and returns whether LTO was used."""
+ # It's assumed that the first line in |lines| was consumed to determine that
+ # LLD was used. Seek 'thinlto-cache' prefix within an "indicator section" as
+ # indicator for LTO.
+ found_indicator_section = False
+ # Potential names of "main section". Only one gets used.
+ indicator_section_set = set(['.rodata', '.ARM.exidx'])
+ start_pos = -1
+ for line in lines:
+ # Shortcut to avoid regex: The first line seen (second line in file) should
+ # start a section, and start with '.', e.g.:
+ # 194 194 13 1 .interp
+ # Assign |start_pos| as position of '.', and trim everything before!
+ if start_pos < 0:
+ start_pos = line.index('.')
+ if len(line) < start_pos:
+ continue
+ line = line[start_pos:]
+ tok = line.lstrip() # Allow whitespace at right.
+ indent_size = len(line) - len(tok)
+ if indent_size == 0: # Section change.
+ if found_indicator_section: # Exit if just visited "main section".
+ break
+ if tok.strip() in indicator_section_set:
+ found_indicator_section = True
+ elif indent_size == 8:
+ if found_indicator_section:
+ if tok.startswith('thinlto-cache'):
+ return True
+ return False
+
+
+def DetectLinkerNameFromMapFile(lines):
+ """Scans linker map file, and returns a coded linker name."""
+ first_line = next(lines)
+
if first_line.startswith('Address'):
- return 'lld_v0'
- elif first_line.lstrip().startswith('VMA'):
- return 'lld_v1'
+ return 'lld-lto_v0' if _DetectLto(lines) else 'lld_v0'
+
+ if first_line.lstrip().startswith('VMA'):
+ return 'lld-lto_v1' if _DetectLto(lines) else 'lld_v1'
+
if first_line.startswith('Archive member'):
return 'gold'
+
raise Exception('Invalid map file: ' + first_line)
class MapFileParser(object):
"""Parses a linker map file, with heuristic linker detection."""
- def Parse(self, lines):
+ def Parse(self, linker_name, lines):
"""Parses a linker map file.
Args:
@@ -412,15 +452,18 @@ class MapFileParser(object):
Returns:
A tuple of (section_sizes, symbols).
"""
- linker_name = DetectLinkerNameFromMapFileHeader(next(lines))
+ next(lines) # Consume the first line of headers.
if linker_name.startswith('lld'):
inner_parser = MapFileParserLld(linker_name)
elif linker_name == 'gold':
inner_parser = MapFileParserGold()
else:
raise Exception('.map file is from a unsupported linker.')
+
section_sizes, syms = inner_parser.Parse(lines)
for sym in syms:
- if sym.object_path: # Don't want '' to become '.'.
+ if sym.object_path and not sym.object_path.endswith(')'):
+ # Don't want '' to become '.'.
+ # Thin archives' paths will get fixed in |ar.CreateThinObjectPath|.
sym.object_path = os.path.normpath(sym.object_path)
return (section_sizes, syms)
diff --git a/chromium/tools/binary_size/libsupersize/main.py b/chromium/tools/binary_size/libsupersize/main.py
index a289ec28ebc..fd972ac6cb0 100755
--- a/chromium/tools/binary_size/libsupersize/main.py
+++ b/chromium/tools/binary_size/libsupersize/main.py
@@ -18,6 +18,7 @@ import sys
import archive
import console
import html_report
+import start_server
def _LogPeakRamUsage():
@@ -69,7 +70,9 @@ def main():
actions = collections.OrderedDict()
actions['archive'] = (archive, 'Create a .size file')
actions['html_report'] = (
- html_report, 'Create a stand-alone html report from a .size file.')
+ html_report, 'Create a stand-alone report from a .size file.')
+ actions['start_server'] = (
+ start_server, 'Start a web server to view data generated by html_report')
actions['console'] = (
console,
'Starts an interactive Python console for analyzing .size files.')
@@ -84,6 +87,7 @@ def main():
tup[0].AddArguments(sub_parser)
sub_parser.set_defaults(func=tup[0].Run)
+ # Show help if the command or a subcommand is called with no arguments
if len(sys.argv) == 1:
parser.print_help()
sys.exit(1)
diff --git a/chromium/tools/binary_size/libsupersize/models.py b/chromium/tools/binary_size/libsupersize/models.py
index 3488bc4178a..9f27e2ad377 100644
--- a/chromium/tools/binary_size/libsupersize/models.py
+++ b/chromium/tools/binary_size/libsupersize/models.py
@@ -24,6 +24,8 @@ Description of common properties:
are removed from both full_name and name during normalization).
* section_name: E.g. ".text", ".rodata", ".data.rel.local"
* section: The second character of |section_name|. E.g. "t", "r", "d".
+ * component: The team that owns this feature.
+ Never None, but will be '' when no component exists.
"""
import collections
@@ -43,6 +45,7 @@ METADATA_ELF_FILENAME = 'elf_file_name' # Path relative to output_directory.
METADATA_ELF_MTIME = 'elf_mtime' # int timestamp in utc.
METADATA_ELF_BUILD_ID = 'elf_build_id'
METADATA_GN_ARGS = 'gn_args'
+METADATA_LINKER_NAME = 'linker_name'
METADATA_TOOL_PREFIX = 'tool_prefix' # Path relative to SRC_ROOT.
SECTION_BSS = '.bss'
@@ -338,6 +341,7 @@ class Symbol(BaseSymbol):
'section_name',
'source_path',
'size',
+ 'component',
)
def __init__(self, section_name, size_without_padding, address=None,
@@ -354,14 +358,16 @@ class Symbol(BaseSymbol):
self.flags = flags
self.aliases = aliases
self.padding = 0
+ self.component = ''
def __repr__(self):
template = ('{}@{:x}(size_without_padding={},padding={},full_name={},'
- 'object_path={},source_path={},flags={},num_aliases={})')
+ 'object_path={},source_path={},flags={},num_aliases={},'
+ 'component={})')
return template.format(
self.section_name, self.address, self.size_without_padding,
self.padding, self.full_name, self.object_path, self.source_path,
- self.FlagsString(), self.num_aliases)
+ self.FlagsString(), self.num_aliases, self.component)
@property
def pss(self):
@@ -411,9 +417,16 @@ class DeltaSymbol(BaseSymbol):
return DIFF_STATUS_ADDED
if self.after_symbol is None:
return DIFF_STATUS_REMOVED
- if self.size == 0:
- return DIFF_STATUS_UNCHANGED
- return DIFF_STATUS_CHANGED
+ # Use delta size and delta PSS as indicators of change. Delta size = 0 with
+ # delta PSS != 0 can be caused by:
+ # (1) Alias addition / removal without actual binary change.
+ # (2) Alias merging / splitting along with binary changes, where matched
+ # symbols all happen the same size (hence delta size = 0).
+ # The purpose of checking PSS is to account for (2). However, this means (1)
+ # would produce much more diffs than before!
+ if self.size != 0 or self.pss != 0:
+ return DIFF_STATUS_CHANGED
+ return DIFF_STATUS_UNCHANGED
@property
def address(self):
@@ -454,6 +467,10 @@ class DeltaSymbol(BaseSymbol):
return (self.after_symbol or self.before_symbol).section_name
@property
+ def component(self):
+ return (self.after_symbol or self.before_symbol).component
+
+ @property
def padding_pss(self):
if self.after_symbol is None:
return -self.before_symbol.padding_pss
@@ -620,6 +637,11 @@ class SymbolGroup(BaseSymbol):
return self._size
@property
+ def component(self):
+ first = self._symbols[0].component if self else ''
+ return first if all(s.component == first for s in self._symbols) else ''
+
+ @property
def pss(self):
if self._pss is None:
if self.IsBss():
@@ -679,8 +701,12 @@ class SymbolGroup(BaseSymbol):
def Sorted(self, cmp_func=None, key=None, reverse=False):
if cmp_func is None and key is None:
- cmp_func = lambda a, b: cmp((a.IsBss(), abs(b.pss), a.name),
- (b.IsBss(), abs(a.pss), b.name))
+ if self.IsDelta():
+ key = lambda s: (s.diff_status == DIFF_STATUS_UNCHANGED, s.IsBss(),
+ s.size_without_padding == 0, -abs(s.pss), s.name)
+ else:
+ key = lambda s: (
+ s.IsBss(), s.size_without_padding == 0, -abs(s.pss), s.name)
after_symbols = sorted(self._symbols, cmp_func, key, reverse)
return self._CreateTransformed(
@@ -746,6 +772,9 @@ class SymbolGroup(BaseSymbol):
def WhereIsTemplate(self):
return self.Filter(lambda s: s.template_name is not s.name)
+ def WhereHasComponent(self):
+ return self.Filter(lambda s: s.component)
+
def WhereSourceIsGenerated(self):
return self.Filter(lambda s: s.generated_source)
@@ -777,6 +806,10 @@ class SymbolGroup(BaseSymbol):
return self.Filter(lambda s: (regex.search(s.source_path) or
regex.search(s.object_path)))
+ def WhereComponentMatches(self, pattern):
+ regex = re.compile(match_util.ExpandRegexIdentifierPlaceholder(pattern))
+ return self.Filter(lambda s: regex.search(s.component))
+
def WhereMatches(self, pattern):
"""Looks for |pattern| within all paths & names."""
regex = re.compile(match_util.ExpandRegexIdentifierPlaceholder(pattern))
@@ -833,6 +866,9 @@ class SymbolGroup(BaseSymbol):
Use a negative value to omit symbols entirely rather than
include them outside of a group.
group_factory: Function to create SymbolGroup from a list of Symbols.
+
+ Returns:
+ SymbolGroup of SymbolGroups
"""
if group_factory is None:
group_factory = lambda token, symbols: self._CreateTransformed(
@@ -954,6 +990,9 @@ class SymbolGroup(BaseSymbol):
def GroupedBySectionName(self):
return self.GroupedBy(lambda s: s.section_name)
+ def GroupedByComponent(self):
+ return self.GroupedBy(lambda s: s.component)
+
def GroupedByFullName(self, min_count=2):
"""Groups by symbol.full_name.
diff --git a/chromium/tools/binary_size/libsupersize/nm.py b/chromium/tools/binary_size/libsupersize/nm.py
index 6ee1320e69e..e5afe97c995 100755..100644
--- a/chromium/tools/binary_size/libsupersize/nm.py
+++ b/chromium/tools/binary_size/libsupersize/nm.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -7,85 +6,27 @@
The design of this file is entirely to work around Python's lack of concurrency.
-CollectAliasesByAddress:
+CollectAliasesByAddress():
Runs "nm" on the elf to collect all symbol names. This reveals symbol names of
identical-code-folded functions.
-CollectAliasesByAddressAsync:
+CollectAliasesByAddressAsync():
Runs CollectAliasesByAddress in a subprocess and returns a promise.
-_BulkObjectFileAnalyzerMaster:
- Creates a subprocess and sends IPCs to it asking it to do work.
-
-_BulkObjectFileAnalyzerSlave:
- Receives IPCs and delegates logic to _BulkObjectFileAnalyzerWorker.
- Runs _BulkObjectFileAnalyzerWorker on a background thread in order to stay
- responsive to IPCs.
-
-_BulkObjectFileAnalyzerWorker:
- Performs the actual work. Uses Process Pools to shard out per-object-file
- work and then aggregates results.
-
-BulkObjectFileAnalyzer:
- Alias for _BulkObjectFileAnalyzerMaster, but when SUPERSIZE_DISABLE_ASYNC=1,
- alias for _BulkObjectFileAnalyzerWorker.
- * AnalyzePaths: Run "nm" on all .o files to collect symbol names that exist
- within each. Does not work with thin archives (expand them first).
- * SortPaths: Sort results of AnalyzePaths().
- * AnalyzeStringLiterals: Must be run after AnalyzePaths() has completed.
- Extracts string literals from .o files, and then locates them within the
- "** merge strings" sections within an ELF's .rodata section.
-
-This file can also be run stand-alone in order to test out the logic on smaller
-sample sizes.
+RunNmOnIntermediates():
+ BulkForkAndCall() target: Runs nm on a .a file or a list of .o files, parses
+ the output, extracts symbol information, and (if available) extracts string
+ offset information.
"""
-from __future__ import print_function
-
-import argparse
-import atexit
import collections
-import errno
-import itertools
-import logging
import os
-import multiprocessing
-import Queue
-import signal
import subprocess
-import sys
-import threading
-import traceback
-import ar
import concurrent
import demangle
-import models
import path_util
-_MSG_ANALYZE_PATHS = 1
-_MSG_SORT_PATHS = 2
-_MSG_ANALYZE_STRINGS = 3
-_MSG_GET_SYMBOL_NAMES = 4
-_MSG_GET_STRINGS = 5
-
-_active_pids = None
-
-
-def _DecodePosition(x):
- # Encoded as "123:123"
- sep_idx = x.index(':')
- return (int(x[:sep_idx]), int(x[sep_idx + 1:]))
-
-
-def _MakeToolPrefixAbsolute(tool_prefix):
- # Ensure tool_prefix is absolute so that CWD does not affect it
- if os.path.sep in tool_prefix:
- # Use abspath() on the dirname to avoid it stripping a trailing /.
- dirname = os.path.dirname(tool_prefix)
- tool_prefix = os.path.abspath(dirname) + tool_prefix[len(dirname):]
- return tool_prefix
-
def _IsRelevantNmName(name):
# Skip lines like:
@@ -184,86 +125,6 @@ def CollectAliasesByAddressAsync(elf_path, tool_prefix):
decode_func=decode)
-def _LookupStringSectionPositions(target, tool_prefix, output_directory):
- """Returns a dict of object_path -> [(offset, size)...] of .rodata sections.
-
- Args:
- target: An archive path string (e.g., "foo.a") or a list of object paths.
- """
- is_archive = isinstance(target, basestring)
- args = [path_util.GetReadElfPath(tool_prefix), '-S', '--wide']
- if is_archive:
- args.append(target)
- else:
- # Assign path for when len(target) == 1, (no File: line exists).
- path = target[0]
- args.extend(target)
-
- output = subprocess.check_output(args, cwd=output_directory)
- lines = output.splitlines()
- section_positions_by_path = {}
- cur_offsets = []
- for line in lines:
- # File: base/third_party/libevent/libevent.a(buffer.o)
- # [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
- # [11] .rodata.str1.1 PROGBITS 00000000 0000b4 000004 01 AMS 0 0 1
- # [11] .rodata.str4.4 PROGBITS 00000000 0000b4 000004 01 AMS 0 0 4
- # [11] .rodata.str8.8 PROGBITS 00000000 0000b4 000004 01 AMS 0 0 8
- # [80] .rodata..L.str PROGBITS 00000000 000530 000002 00 A 0 0 1
- # The various string sections differ by alignment.
- # The presence of a wchar_t literal (L"asdf") seems to make a str4 section.
- # When multiple sections exist, nm gives us no indication as to which
- # section each string corresponds to.
- if line.startswith('File: '):
- if cur_offsets:
- section_positions_by_path[path] = cur_offsets
- cur_offsets = []
- path = line[6:]
- elif '.rodata.' in line:
- progbits_idx = line.find('PROGBITS ')
- if progbits_idx != -1:
- fields = line[progbits_idx:].split()
- position = (int(fields[2], 16), int(fields[3], 16))
- # The heuristics in _IterStringLiterals rely on str1 coming first.
- if fields[-1] == '1':
- cur_offsets.insert(0, position)
- else:
- cur_offsets.append(position)
- if cur_offsets:
- section_positions_by_path[path] = cur_offsets
- return section_positions_by_path
-
-
-def LookupElfRodataInfo(elf_path, tool_prefix):
- """Returns (address, offset, size) for the .rodata section."""
- args = [path_util.GetReadElfPath(tool_prefix), '-S', '--wide', elf_path]
- output = subprocess.check_output(args)
- lines = output.splitlines()
- for line in lines:
- # [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
- # [07] .rodata PROGBITS 025e7000 237c000 5ec4f6 00 A 0 0 256
- if '.rodata ' in line:
- fields = line[line.index(models.SECTION_RODATA):].split()
- return int(fields[2], 16), int(fields[3], 16), int(fields[4], 16)
- raise AssertionError('No .rodata for command: ' + repr(args))
-
-
-def _ReadFileChunks(path, positions):
- """Returns a list of strings corresponding to |positions|.
-
- Args:
- positions: List of (offset, size).
- """
- ret = []
- if not positions:
- return ret
- with open(path, 'rb') as f:
- for offset, size in positions:
- f.seek(offset)
- ret.append(f.read(size))
- return ret
-
-
def _ParseOneObjectFileNmOutput(lines):
# Constructors are often repeated because they have the same unmangled
# name, but multiple mangled names. See:
@@ -288,145 +149,8 @@ def _ParseOneObjectFileNmOutput(lines):
return string_addresses, symbol_names
-def _ReadStringSections(target, output_directory, positions_by_path):
- """Returns a dict of object_path -> [string...] of .rodata chunks.
-
- Args:
- target: An archive path string (e.g., "foo.a") or a list of object paths.
- positions_by_path: A dict of object_path -> [(offset, size)...]
- """
- is_archive = isinstance(target, basestring)
- string_sections_by_path = {}
- if is_archive:
- for subpath, chunk in ar.IterArchiveChunks(
- os.path.join(output_directory, target)):
- path = '{}({})'.format(target, subpath)
- positions = positions_by_path.get(path)
- # No positions if file has no string literals.
- if positions:
- string_sections_by_path[path] = (
- [chunk[offset:offset + size] for offset, size in positions])
- else:
- for path in target:
- positions = positions_by_path.get(path)
- # We already log a warning about this in _IterStringLiterals().
- if positions:
- string_sections_by_path[path] = _ReadFileChunks(
- os.path.join(output_directory, path), positions)
- return string_sections_by_path
-
-
-def _ExtractArchivePath(path):
- # E.g. foo/bar.a(baz.o)
- if path.endswith(')'):
- start_idx = path.index('(')
- return path[:start_idx]
- return None
-
-
-def _IterStringLiterals(path, addresses, obj_sections):
- """Yields all string literals (including \0) for the given object path.
-
- Args:
- path: Object file path.
- addresses: List of string offsets encoded as hex strings.
- obj_sections: List of contents of .rodata.str sections read from the given
- object file.
- """
-
- next_offsets = sorted(int(a, 16) for a in addresses)
- if not obj_sections:
- # Happens when there is an address for a symbol which is not actually a
- # string literal, or when string_sections_by_path is missing an entry.
- logging.warning('Object has %d strings but no string sections: %s',
- len(addresses), path)
- return
- for section_data in obj_sections:
- cur_offsets = next_offsets
- # Always assume first element is 0. I'm not entirely sure why this is
- # necessary, but strings get missed without it.
- next_offsets = [0]
- prev_offset = 0
- # TODO(agrieve): Switch to using nm --print-size in order to capture the
- # address+size of each string rather than just the address.
- for offset in cur_offsets[1:]:
- if offset >= len(section_data):
- # Remaining offsets are for next section.
- next_offsets.append(offset)
- continue
- # Figure out which offsets apply to this section via heuristic of them
- # all ending with a null character.
- if offset == prev_offset or section_data[offset - 1] != '\0':
- next_offsets.append(offset)
- continue
- yield section_data[prev_offset:offset]
- prev_offset = offset
-
- if prev_offset < len(section_data):
- yield section_data[prev_offset:]
-
-
# This is a target for BulkForkAndCall().
-def _ResolveStringPieces(encoded_string_addresses_by_path, string_data,
- tool_prefix, output_directory):
- string_addresses_by_path = concurrent.DecodeDictOfLists(
- encoded_string_addresses_by_path)
- # Assign |target| as archive path, or a list of object paths.
- any_path = next(string_addresses_by_path.iterkeys())
- target = _ExtractArchivePath(any_path)
- if not target:
- target = string_addresses_by_path.keys()
-
- # Run readelf to find location of .rodata within the .o files.
- section_positions_by_path = _LookupStringSectionPositions(
- target, tool_prefix, output_directory)
- # Load the .rodata sections (from object files) as strings.
- string_sections_by_path = _ReadStringSections(
- target, output_directory, section_positions_by_path)
-
- # list of elf_positions_by_path.
- ret = [collections.defaultdict(list) for _ in string_data]
- # Brute-force search of strings within ** merge strings sections.
- # This is by far the slowest part of AnalyzeStringLiterals().
- # TODO(agrieve): Pre-process string_data into a dict of literal->address (at
- # least for ascii strings).
- for path, object_addresses in string_addresses_by_path.iteritems():
- for value in _IterStringLiterals(
- path, object_addresses, string_sections_by_path.get(path)):
- first_match = -1
- first_match_dict = None
- for target_dict, data in itertools.izip(ret, string_data):
- # Set offset so that it will be 0 when len(value) is added to it below.
- offset = -len(value)
- while True:
- offset = data.find(value, offset + len(value))
- if offset == -1:
- break
- # Preferring exact matches (those following \0) over substring matches
- # significantly increases accuracy (although shows that linker isn't
- # being optimal).
- if offset == 0 or data[offset - 1] == '\0':
- break
- if first_match == -1:
- first_match = offset
- first_match_dict = target_dict
- if offset != -1:
- break
- if offset == -1:
- # Exact match not found, so take suffix match if it exists.
- offset = first_match
- target_dict = first_match_dict
- # Missing strings happen when optimization make them unused.
- if offset != -1:
- # Encode tuple as a string for easier mashalling.
- target_dict[path].append(
- str(offset) + ':' + str(len(value)))
-
- return [concurrent.EncodeDictOfLists(x) for x in ret]
-
-
-# This is a target for BulkForkAndCall().
-def _RunNmOnIntermediates(target, tool_prefix, output_directory):
+def RunNmOnIntermediates(target, tool_prefix, output_directory):
"""Returns encoded_symbol_names_by_path, encoded_string_addresses_by_path.
Args:
@@ -471,287 +195,3 @@ def _RunNmOnIntermediates(target, tool_prefix, output_directory):
# down on marshalling overhead.
return (concurrent.EncodeDictOfLists(symbol_names_by_path),
concurrent.EncodeDictOfLists(string_addresses_by_path))
-
-
-class _BulkObjectFileAnalyzerWorker(object):
- def __init__(self, tool_prefix, output_directory):
- self._tool_prefix = _MakeToolPrefixAbsolute(tool_prefix)
- self._output_directory = output_directory
- self._paths_by_name = collections.defaultdict(list)
- self._encoded_string_addresses_by_path_chunks = []
- self._list_of_encoded_elf_string_positions_by_path = None
-
- def AnalyzePaths(self, paths):
- def iter_job_params():
- object_paths = []
- for path in paths:
- # Note: _ResolveStringPieces relies upon .a not being grouped.
- if path.endswith('.a'):
- yield path, self._tool_prefix, self._output_directory
- else:
- object_paths.append(path)
-
- BATCH_SIZE = 50 # Chosen arbitrarily.
- for i in xrange(0, len(object_paths), BATCH_SIZE):
- batch = object_paths[i:i + BATCH_SIZE]
- yield batch, self._tool_prefix, self._output_directory
-
- params = list(iter_job_params())
- # Order of the jobs doesn't matter since each job owns independent paths,
- # and our output is a dict where paths are the key.
- results = concurrent.BulkForkAndCall(_RunNmOnIntermediates, params)
-
- # Names are still mangled.
- all_paths_by_name = self._paths_by_name
- for encoded_syms, encoded_strs in results:
- symbol_names_by_path = concurrent.DecodeDictOfLists(encoded_syms)
- for path, names in symbol_names_by_path.iteritems():
- for name in names:
- all_paths_by_name[name].append(path)
-
- if encoded_strs != concurrent.EMPTY_ENCODED_DICT:
- self._encoded_string_addresses_by_path_chunks.append(encoded_strs)
- logging.debug('worker: AnalyzePaths() completed.')
-
- def SortPaths(self):
- # Finally, demangle all names, which can result in some merging of lists.
- self._paths_by_name = demangle.DemangleKeysAndMergeLists(
- self._paths_by_name, self._tool_prefix)
- # Sort and uniquefy.
- for key in self._paths_by_name.iterkeys():
- self._paths_by_name[key] = sorted(set(self._paths_by_name[key]))
-
- def AnalyzeStringLiterals(self, elf_path, elf_string_positions):
- logging.debug('worker: AnalyzeStringLiterals() started.')
- # Read string_data from elf_path, to be shared by forked processes.
- address, offset, _ = LookupElfRodataInfo(elf_path, self._tool_prefix)
- adjust = address - offset
- abs_string_positions = (
- (addr - adjust, s) for addr, s in elf_string_positions)
- string_data = _ReadFileChunks(elf_path, abs_string_positions)
-
- params = (
- (chunk, string_data, self._tool_prefix, self._output_directory)
- for chunk in self._encoded_string_addresses_by_path_chunks)
- # Order of the jobs doesn't matter since each job owns independent paths,
- # and our output is a dict where paths are the key.
- results = concurrent.BulkForkAndCall(_ResolveStringPieces, params)
- results = list(results)
-
- final_result = []
- for i in xrange(len(elf_string_positions)):
- final_result.append(
- concurrent.JoinEncodedDictOfLists([r[i] for r in results]))
- self._list_of_encoded_elf_string_positions_by_path = final_result
- logging.debug('worker: AnalyzeStringLiterals() completed.')
-
- def GetSymbolNames(self):
- return self._paths_by_name
-
- def GetStringPositions(self):
- return [concurrent.DecodeDictOfLists(x, value_transform=_DecodePosition)
- for x in self._list_of_encoded_elf_string_positions_by_path]
-
- def GetEncodedStringPositions(self):
- return self._list_of_encoded_elf_string_positions_by_path
-
- def Close(self):
- pass
-
-
-def _TerminateSubprocesses():
- global _active_pids
- if _active_pids:
- for pid in _active_pids:
- os.kill(pid, signal.SIGKILL)
- _active_pids = []
-
-
-class _BulkObjectFileAnalyzerMaster(object):
- """Runs BulkObjectFileAnalyzer in a subprocess."""
- def __init__(self, tool_prefix, output_directory):
- self._child_pid = None
- self._pipe = None
- self._tool_prefix = tool_prefix
- self._output_directory = output_directory
-
- def _Spawn(self):
- global _active_pids
- parent_conn, child_conn = multiprocessing.Pipe()
- self._child_pid = os.fork()
- if self._child_pid:
- # We are the parent process.
- if _active_pids is None:
- _active_pids = []
- atexit.register(_TerminateSubprocesses)
- _active_pids.append(self._child_pid)
- self._pipe = parent_conn
- else:
- # We are the child process.
- logging.root.handlers[0].setFormatter(logging.Formatter(
- 'nm: %(levelname).1s %(relativeCreated)6d %(message)s'))
- worker_analyzer = _BulkObjectFileAnalyzerWorker(
- self._tool_prefix, self._output_directory)
- slave = _BulkObjectFileAnalyzerSlave(worker_analyzer, child_conn)
- slave.Run()
-
- def AnalyzePaths(self, paths):
- if self._child_pid is None:
- self._Spawn()
-
- logging.debug('Sending batch of %d paths to subprocess', len(paths))
- payload = '\x01'.join(paths)
- self._pipe.send((_MSG_ANALYZE_PATHS, payload))
-
- def SortPaths(self):
- self._pipe.send((_MSG_SORT_PATHS,))
-
- def AnalyzeStringLiterals(self, elf_path, string_positions):
- self._pipe.send((_MSG_ANALYZE_STRINGS, elf_path, string_positions))
-
- def GetSymbolNames(self):
- self._pipe.send((_MSG_GET_SYMBOL_NAMES,))
- self._pipe.recv() # None
- logging.debug('Decoding nm results from forked process')
- encoded_paths_by_name = self._pipe.recv()
- return concurrent.DecodeDictOfLists(encoded_paths_by_name)
-
- def GetStringPositions(self):
- self._pipe.send((_MSG_GET_STRINGS,))
- self._pipe.recv() # None
- logging.debug('Decoding string symbol results from forked process')
- result = self._pipe.recv()
- return [concurrent.DecodeDictOfLists(x, value_transform=_DecodePosition)
- for x in result]
-
- def Close(self):
- self._pipe.close()
- # Child process should terminate gracefully at this point, but leave it in
- # _active_pids to be killed just in case.
-
-
-class _BulkObjectFileAnalyzerSlave(object):
- """The subprocess entry point."""
- def __init__(self, worker_analyzer, pipe):
- self._worker_analyzer = worker_analyzer
- self._pipe = pipe
- # Use a worker thread so that AnalyzeStringLiterals() is non-blocking. The
- # thread allows the main thread to process a call to GetSymbolNames() while
- # AnalyzeStringLiterals() is in progress.
- self._job_queue = Queue.Queue()
- self._worker_thread = threading.Thread(target=self._WorkerThreadMain)
- self._allow_analyze_paths = True
-
- def _WorkerThreadMain(self):
- while True:
- # Handle exceptions so test failure will be explicit and not block.
- try:
- func = self._job_queue.get()
- func()
- except Exception:
- traceback.print_exc()
- self._job_queue.task_done()
-
- def _WaitForAnalyzePathJobs(self):
- if self._allow_analyze_paths:
- self._job_queue.join()
- self._allow_analyze_paths = False
-
- def Run(self):
- try:
- self._worker_thread.start()
- while True:
- message = self._pipe.recv()
- if message[0] == _MSG_ANALYZE_PATHS:
- assert self._allow_analyze_paths, (
- 'Cannot call AnalyzePaths() after AnalyzeStringLiterals()s.')
- paths = message[1].split('\x01')
- self._job_queue.put(lambda: self._worker_analyzer.AnalyzePaths(paths))
- elif message[0] == _MSG_SORT_PATHS:
- assert self._allow_analyze_paths, (
- 'Cannot call SortPaths() after AnalyzeStringLiterals()s.')
- self._job_queue.put(self._worker_analyzer.SortPaths)
- elif message[0] == _MSG_ANALYZE_STRINGS:
- self._WaitForAnalyzePathJobs()
- elf_path, string_positions = message[1:]
- self._job_queue.put(
- lambda: self._worker_analyzer.AnalyzeStringLiterals(
- elf_path, string_positions))
- elif message[0] == _MSG_GET_SYMBOL_NAMES:
- self._WaitForAnalyzePathJobs()
- self._pipe.send(None)
- paths_by_name = self._worker_analyzer.GetSymbolNames()
- self._pipe.send(concurrent.EncodeDictOfLists(paths_by_name))
- elif message[0] == _MSG_GET_STRINGS:
- self._job_queue.join()
- # Send a None packet so that other side can measure IPC transfer time.
- self._pipe.send(None)
- self._pipe.send(self._worker_analyzer.GetEncodedStringPositions())
- except EOFError:
- pass
- except EnvironmentError, e:
- # Parent process exited so don't log.
- if e.errno in (errno.EPIPE, errno.ECONNRESET):
- sys.exit(1)
-
- logging.debug('nm bulk subprocess finished.')
- sys.exit(0)
-
-
-BulkObjectFileAnalyzer = _BulkObjectFileAnalyzerMaster
-if concurrent.DISABLE_ASYNC:
- BulkObjectFileAnalyzer = _BulkObjectFileAnalyzerWorker
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument('--multiprocess', action='store_true')
- parser.add_argument('--tool-prefix', required=True)
- parser.add_argument('--output-directory', required=True)
- parser.add_argument('--elf-file', type=os.path.realpath)
- parser.add_argument('--show-names', action='store_true')
- parser.add_argument('--show-strings', action='store_true')
- parser.add_argument('objects', type=os.path.realpath, nargs='+')
-
- args = parser.parse_args()
- logging.basicConfig(level=logging.DEBUG,
- format='%(levelname).1s %(relativeCreated)6d %(message)s')
-
- if args.multiprocess:
- bulk_analyzer = _BulkObjectFileAnalyzerMaster(
- args.tool_prefix, args.output_directory)
- else:
- concurrent.DISABLE_ASYNC = True
- bulk_analyzer = _BulkObjectFileAnalyzerWorker(
- args.tool_prefix, args.output_directory)
-
- # Pass individually to test multiple calls.
- for path in args.objects:
- bulk_analyzer.AnalyzePaths([path])
- bulk_analyzer.SortPaths()
-
- names_to_paths = bulk_analyzer.GetSymbolNames()
- print('Found {} names'.format(len(names_to_paths)))
- if args.show_names:
- for name, paths in names_to_paths.iteritems():
- print('{}: {!r}'.format(name, paths))
-
- if args.elf_file:
- address, offset, size = LookupElfRodataInfo(
- args.elf_file, args.tool_prefix)
- bulk_analyzer.AnalyzeStringLiterals(args.elf_file, ((address, size),))
-
- positions_by_path = bulk_analyzer.GetStringPositions()[0]
- print('Found {} string literals'.format(sum(
- len(v) for v in positions_by_path.itervalues())))
- if args.show_strings:
- logging.debug('.rodata adjust=%d', address - offset)
- for path, positions in positions_by_path.iteritems():
- strs = _ReadFileChunks(
- args.elf_file, ((offset + addr, size) for addr, size in positions))
- print('{}: {!r}'.format(
- path, [s if len(s) < 20 else s[:20] + '...' for s in strs]))
-
-
-if __name__ == '__main__':
- main()
diff --git a/chromium/tools/binary_size/libsupersize/obj_analyzer.py b/chromium/tools/binary_size/libsupersize/obj_analyzer.py
new file mode 100755
index 00000000000..eee679babce
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/obj_analyzer.py
@@ -0,0 +1,371 @@
+#!/usr/bin/env python
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Analyzer for Object Files.
+
+This file works around Python's lack of concurrency.
+
+_BulkObjectFileAnalyzerMaster:
+ Creates a subprocess and sends IPCs to it asking it to do work.
+
+_BulkObjectFileAnalyzerSlave:
+ Receives IPCs and delegates logic to _BulkObjectFileAnalyzerWorker.
+ Runs _BulkObjectFileAnalyzerWorker on a background thread in order to stay
+ responsive to IPCs.
+
+_BulkObjectFileAnalyzerWorker:
+ Performs the actual work. Uses Process Pools to shard out per-object-file
+ work and then aggregates results.
+
+BulkObjectFileAnalyzer:
+ Alias for _BulkObjectFileAnalyzerMaster, but when SUPERSIZE_DISABLE_ASYNC=1,
+ alias for _BulkObjectFileAnalyzerWorker.
+ * AnalyzePaths: Run "nm" on all .o files to collect symbol names that exist
+ within each. Does not work with thin archives (expand them first).
+ * SortPaths: Sort results of AnalyzePaths().
+ * AnalyzeStringLiterals: Must be run after AnalyzePaths() has completed.
+ Extracts string literals from .o files, and then locates them within the
+ "** merge strings" sections within an ELF's .rodata section.
+
+This file can also be run stand-alone in order to test out the logic on smaller
+sample sizes.
+"""
+
+from __future__ import print_function
+
+import argparse
+import atexit
+import collections
+import errno
+import logging
+import os
+import multiprocessing
+import Queue
+import signal
+import sys
+import threading
+import traceback
+
+import concurrent
+import demangle
+import nm
+import string_extract
+
+
+_MSG_ANALYZE_PATHS = 1
+_MSG_SORT_PATHS = 2
+_MSG_ANALYZE_STRINGS = 3
+_MSG_GET_SYMBOL_NAMES = 4
+_MSG_GET_STRINGS = 5
+
+_active_pids = None
+
+
+def _DecodePosition(x):
+ # Encoded as "123:123"
+ sep_idx = x.index(':')
+ return (int(x[:sep_idx]), int(x[sep_idx + 1:]))
+
+
+def _MakeToolPrefixAbsolute(tool_prefix):
+ # Ensure tool_prefix is absolute so that CWD does not affect it
+ if os.path.sep in tool_prefix:
+ # Use abspath() on the dirname to avoid it stripping a trailing /.
+ dirname = os.path.dirname(tool_prefix)
+ tool_prefix = os.path.abspath(dirname) + tool_prefix[len(dirname):]
+ return tool_prefix
+
+
+class _BulkObjectFileAnalyzerWorker(object):
+ def __init__(self, tool_prefix, output_directory):
+ self._tool_prefix = _MakeToolPrefixAbsolute(tool_prefix)
+ self._output_directory = output_directory
+ self._paths_by_name = collections.defaultdict(list)
+ self._encoded_string_addresses_by_path_chunks = []
+ self._list_of_encoded_elf_string_positions_by_path = None
+
+ def AnalyzePaths(self, paths):
+ def iter_job_params():
+ object_paths = []
+ for path in paths:
+ # Note: ResolveStringPieces() relies upon .a not being grouped.
+ if path.endswith('.a'):
+ yield (path,)
+ else:
+ object_paths.append(path)
+
+ BATCH_SIZE = 50 # Chosen arbitrarily.
+ for i in xrange(0, len(object_paths), BATCH_SIZE):
+ batch = object_paths[i:i + BATCH_SIZE]
+ yield (batch,)
+
+ params = list(iter_job_params())
+ # Order of the jobs doesn't matter since each job owns independent paths,
+ # and our output is a dict where paths are the key.
+ results = concurrent.BulkForkAndCall(
+ nm.RunNmOnIntermediates, params, tool_prefix=self._tool_prefix,
+ output_directory=self._output_directory)
+
+ # Names are still mangled.
+ all_paths_by_name = self._paths_by_name
+ for encoded_syms, encoded_strs in results:
+ symbol_names_by_path = concurrent.DecodeDictOfLists(encoded_syms)
+ for path, names in symbol_names_by_path.iteritems():
+ for name in names:
+ all_paths_by_name[name].append(path)
+
+ if encoded_strs != concurrent.EMPTY_ENCODED_DICT:
+ self._encoded_string_addresses_by_path_chunks.append(encoded_strs)
+ logging.debug('worker: AnalyzePaths() completed.')
+
+ def SortPaths(self):
+ # Finally, demangle all names, which can result in some merging of lists.
+ self._paths_by_name = demangle.DemangleKeysAndMergeLists(
+ self._paths_by_name, self._tool_prefix)
+ # Sort and uniquefy.
+ for key in self._paths_by_name.iterkeys():
+ self._paths_by_name[key] = sorted(set(self._paths_by_name[key]))
+
+ def AnalyzeStringLiterals(self, elf_path, elf_string_positions):
+ logging.debug('worker: AnalyzeStringLiterals() started.')
+ # Read string_data from elf_path, to be shared by forked processes.
+ address, offset, _ = string_extract.LookupElfRodataInfo(
+ elf_path, self._tool_prefix)
+ adjust = address - offset
+ abs_string_positions = (
+ (addr - adjust, s) for addr, s in elf_string_positions)
+ string_data = string_extract.ReadFileChunks(elf_path, abs_string_positions)
+
+ params = ((chunk,)
+ for chunk in self._encoded_string_addresses_by_path_chunks)
+ # Order of the jobs doesn't matter since each job owns independent paths,
+ # and our output is a dict where paths are the key.
+ results = concurrent.BulkForkAndCall(
+ string_extract.ResolveStringPieces, params, string_data=string_data,
+ tool_prefix=self._tool_prefix, output_directory=self._output_directory)
+ results = list(results)
+
+ final_result = []
+ for i in xrange(len(elf_string_positions)):
+ final_result.append(
+ concurrent.JoinEncodedDictOfLists([r[i] for r in results]))
+ self._list_of_encoded_elf_string_positions_by_path = final_result
+ logging.debug('worker: AnalyzeStringLiterals() completed.')
+
+ def GetSymbolNames(self):
+ return self._paths_by_name
+
+ def GetStringPositions(self):
+ return [concurrent.DecodeDictOfLists(x, value_transform=_DecodePosition)
+ for x in self._list_of_encoded_elf_string_positions_by_path]
+
+ def GetEncodedStringPositions(self):
+ return self._list_of_encoded_elf_string_positions_by_path
+
+ def Close(self):
+ pass
+
+
+def _TerminateSubprocesses():
+ global _active_pids
+ if _active_pids:
+ for pid in _active_pids:
+ os.kill(pid, signal.SIGKILL)
+ _active_pids = []
+
+
+class _BulkObjectFileAnalyzerMaster(object):
+ """Runs BulkObjectFileAnalyzer in a subprocess."""
+ def __init__(self, tool_prefix, output_directory):
+ self._child_pid = None
+ self._pipe = None
+ self._tool_prefix = tool_prefix
+ self._output_directory = output_directory
+
+ def _Spawn(self):
+ global _active_pids
+ parent_conn, child_conn = multiprocessing.Pipe()
+ self._child_pid = os.fork()
+ if self._child_pid:
+ # We are the parent process.
+ if _active_pids is None:
+ _active_pids = []
+ atexit.register(_TerminateSubprocesses)
+ _active_pids.append(self._child_pid)
+ self._pipe = parent_conn
+ else:
+ # We are the child process.
+ logging.root.handlers[0].setFormatter(logging.Formatter(
+ 'nm: %(levelname).1s %(relativeCreated)6d %(message)s'))
+ worker_analyzer = _BulkObjectFileAnalyzerWorker(
+ self._tool_prefix, self._output_directory)
+ slave = _BulkObjectFileAnalyzerSlave(worker_analyzer, child_conn)
+ slave.Run()
+
+ def AnalyzePaths(self, paths):
+ if self._child_pid is None:
+ self._Spawn()
+
+ logging.debug('Sending batch of %d paths to subprocess', len(paths))
+ payload = '\x01'.join(paths)
+ self._pipe.send((_MSG_ANALYZE_PATHS, payload))
+
+ def SortPaths(self):
+ self._pipe.send((_MSG_SORT_PATHS,))
+
+ def AnalyzeStringLiterals(self, elf_path, string_positions):
+ self._pipe.send((_MSG_ANALYZE_STRINGS, elf_path, string_positions))
+
+ def GetSymbolNames(self):
+ self._pipe.send((_MSG_GET_SYMBOL_NAMES,))
+ self._pipe.recv() # None
+ logging.debug('Decoding nm results from forked process')
+ encoded_paths_by_name = self._pipe.recv()
+ return concurrent.DecodeDictOfLists(encoded_paths_by_name)
+
+ def GetStringPositions(self):
+ self._pipe.send((_MSG_GET_STRINGS,))
+ self._pipe.recv() # None
+ logging.debug('Decoding string symbol results from forked process')
+ result = self._pipe.recv()
+ return [concurrent.DecodeDictOfLists(x, value_transform=_DecodePosition)
+ for x in result]
+
+ def Close(self):
+ self._pipe.close()
+ # Child process should terminate gracefully at this point, but leave it in
+ # _active_pids to be killed just in case.
+
+
+class _BulkObjectFileAnalyzerSlave(object):
+ """The subprocess entry point."""
+ def __init__(self, worker_analyzer, pipe):
+ self._worker_analyzer = worker_analyzer
+ self._pipe = pipe
+ # Use a worker thread so that AnalyzeStringLiterals() is non-blocking. The
+ # thread allows the main thread to process a call to GetSymbolNames() while
+ # AnalyzeStringLiterals() is in progress.
+ self._job_queue = Queue.Queue()
+ self._worker_thread = threading.Thread(target=self._WorkerThreadMain)
+ self._allow_analyze_paths = True
+
+ def _WorkerThreadMain(self):
+ while True:
+ # Handle exceptions so test failure will be explicit and not block.
+ try:
+ func = self._job_queue.get()
+ func()
+ except Exception:
+ traceback.print_exc()
+ self._job_queue.task_done()
+
+ def _WaitForAnalyzePathJobs(self):
+ if self._allow_analyze_paths:
+ self._job_queue.join()
+ self._allow_analyze_paths = False
+
+ # Handle messages in a function outside the event loop, so local variables are
+ # independent across messages, and can be bound to jobs by lambdas using
+ # closures instead of functools.partial().
+ def _HandleMessage(self, message):
+ if message[0] == _MSG_ANALYZE_PATHS:
+ assert self._allow_analyze_paths, (
+ 'Cannot call AnalyzePaths() after AnalyzeStringLiterals()s.')
+ paths = message[1].split('\x01')
+ self._job_queue.put(lambda: self._worker_analyzer.AnalyzePaths(paths))
+ elif message[0] == _MSG_SORT_PATHS:
+ assert self._allow_analyze_paths, (
+ 'Cannot call SortPaths() after AnalyzeStringLiterals()s.')
+ self._job_queue.put(self._worker_analyzer.SortPaths)
+ elif message[0] == _MSG_ANALYZE_STRINGS:
+ self._WaitForAnalyzePathJobs()
+ elf_path, string_positions = message[1:]
+ self._job_queue.put(
+ lambda: self._worker_analyzer.AnalyzeStringLiterals(
+ elf_path, string_positions))
+ elif message[0] == _MSG_GET_SYMBOL_NAMES:
+ self._WaitForAnalyzePathJobs()
+ self._pipe.send(None)
+ paths_by_name = self._worker_analyzer.GetSymbolNames()
+ self._pipe.send(concurrent.EncodeDictOfLists(paths_by_name))
+ elif message[0] == _MSG_GET_STRINGS:
+ self._job_queue.join()
+ # Send a None packet so that other side can measure IPC transfer time.
+ self._pipe.send(None)
+ self._pipe.send(self._worker_analyzer.GetEncodedStringPositions())
+
+ def Run(self):
+ try:
+ self._worker_thread.start()
+ while True:
+ self._HandleMessage(self._pipe.recv())
+ except EOFError:
+ pass
+ except EnvironmentError, e:
+ # Parent process exited so don't log.
+ if e.errno in (errno.EPIPE, errno.ECONNRESET):
+ sys.exit(1)
+
+ logging.debug('nm bulk subprocess finished.')
+ sys.exit(0)
+
+
+BulkObjectFileAnalyzer = _BulkObjectFileAnalyzerMaster
+if concurrent.DISABLE_ASYNC:
+ BulkObjectFileAnalyzer = _BulkObjectFileAnalyzerWorker
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--multiprocess', action='store_true')
+ parser.add_argument('--tool-prefix', required=True)
+ parser.add_argument('--output-directory', required=True)
+ parser.add_argument('--elf-file', type=os.path.realpath)
+ parser.add_argument('--show-names', action='store_true')
+ parser.add_argument('--show-strings', action='store_true')
+ parser.add_argument('objects', type=os.path.realpath, nargs='+')
+
+ args = parser.parse_args()
+ logging.basicConfig(level=logging.DEBUG,
+ format='%(levelname).1s %(relativeCreated)6d %(message)s')
+
+ if args.multiprocess:
+ bulk_analyzer = _BulkObjectFileAnalyzerMaster(
+ args.tool_prefix, args.output_directory)
+ else:
+ concurrent.DISABLE_ASYNC = True
+ bulk_analyzer = _BulkObjectFileAnalyzerWorker(
+ args.tool_prefix, args.output_directory)
+
+ # Pass individually to test multiple calls.
+ for path in args.objects:
+ bulk_analyzer.AnalyzePaths([path])
+ bulk_analyzer.SortPaths()
+
+ names_to_paths = bulk_analyzer.GetSymbolNames()
+ print('Found {} names'.format(len(names_to_paths)))
+ if args.show_names:
+ for name, paths in names_to_paths.iteritems():
+ print('{}: {!r}'.format(name, paths))
+
+ if args.elf_file:
+ address, offset, size = string_extract.LookupElfRodataInfo(
+ args.elf_file, args.tool_prefix)
+ bulk_analyzer.AnalyzeStringLiterals(args.elf_file, ((address, size),))
+
+ positions_by_path = bulk_analyzer.GetStringPositions()[0]
+ print('Found {} string literals'.format(sum(
+ len(v) for v in positions_by_path.itervalues())))
+ if args.show_strings:
+ logging.debug('.rodata adjust=%d', address - offset)
+ for path, positions in positions_by_path.iteritems():
+ strs = string_extract.ReadFileChunks(
+ args.elf_file, ((offset + addr, size) for addr, size in positions))
+ print('{}: {!r}'.format(
+ path, [s if len(s) < 20 else s[:20] + '...' for s in strs]))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/binary_size/libsupersize/path_util.py b/chromium/tools/binary_size/libsupersize/path_util.py
index 1432fd3a69a..9ef38105a8f 100644
--- a/chromium/tools/binary_size/libsupersize/path_util.py
+++ b/chromium/tools/binary_size/libsupersize/path_util.py
@@ -85,11 +85,14 @@ class ToolPrefixFinder(_PathFinder):
self._output_directory_finder = output_directory_finder
self._linker_name = linker_name;
+ def IsLld(self):
+ return self._linker_name.startswith('lld') if self._linker_name else True
+
def Detect(self):
output_directory = self._output_directory_finder.Tentative()
if output_directory:
ret = None
- if self._linker_name.startswith('lld'):
+ if self.IsLld():
ret = os.path.join(SRC_ROOT, 'third_party', 'llvm-build',
'Release+Asserts', 'bin', 'llvm-')
else:
@@ -182,3 +185,9 @@ def GetReadElfPath(tool_prefix):
if tool_prefix[-5:] == 'llvm-':
return 'readelf'
return tool_prefix + 'readelf'
+
+
+def GetBcAnalyzerPath(tool_prefix):
+ if tool_prefix[-5:] != 'llvm-':
+ raise ValueError('BC analyzer is only supported in LLVM.')
+ return tool_prefix + 'bcanalyzer'
diff --git a/chromium/tools/binary_size/libsupersize/start_server.py b/chromium/tools/binary_size/libsupersize/start_server.py
new file mode 100644
index 00000000000..23ef088f38f
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/start_server.py
@@ -0,0 +1,51 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Runs a server to let the user interact with supersize using a web UI."""
+
+import BaseHTTPServer
+import logging
+import os
+import SimpleHTTPServer
+
+
+class SupersizeHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler,
+ object):
+ # Directory to serve files from
+ serve_from = None
+ # Path to data file
+ data_file_path = None
+
+ #override
+ def translate_path(self, path):
+ f = super(SupersizeHTTPRequestHandler, self).translate_path(path)
+ relative_path = os.path.relpath(f, os.getcwd())
+ if relative_path == 'data.ndjson':
+ return SupersizeHTTPRequestHandler.data_file_path
+ else:
+ return os.path.join(SupersizeHTTPRequestHandler.serve_from, relative_path)
+
+
+def AddArguments(parser):
+ parser.add_argument('report_file',
+ help='Path to a custom html_report data file to load.')
+ parser.add_argument('-p', '--port', type=int, default=8000,
+ help='Port for the HTTP server')
+ parser.add_argument('-a', '--address', default='localhost',
+ help='Address for the HTTP server')
+
+
+def Run(args, _parser):
+ logging.info('Starting server')
+ server_addr = ('', args.port)
+
+ static_files = os.path.join(os.path.dirname(__file__), 'static')
+
+ SupersizeHTTPRequestHandler.serve_from = static_files
+ SupersizeHTTPRequestHandler.data_file_path = args.report_file
+ httpd = BaseHTTPServer.HTTPServer(server_addr, SupersizeHTTPRequestHandler)
+
+ sa = httpd.socket.getsockname()
+ logging.warning('Server ready at http://%s:%d', sa[0], sa[1])
+ httpd.serve_forever()
diff --git a/chromium/tools/binary_size/libsupersize/static/favicon.ico b/chromium/tools/binary_size/libsupersize/static/favicon.ico
new file mode 100644
index 00000000000..ff2c6a9af95
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/static/favicon.ico
Binary files differ
diff --git a/chromium/tools/binary_size/libsupersize/static/index.html b/chromium/tools/binary_size/libsupersize/static/index.html
new file mode 100644
index 00000000000..3a29bf074d6
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/static/index.html
@@ -0,0 +1,603 @@
+<!DOCTYPE html>
+<html lang="en">
+<!--
+ Copyright 2018 The Chromium Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+-->
+
+<head>
+ <title>Binary Size Analysis</title>
+ <script src="start-worker.js"></script>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <link href="https://fonts.googleapis.com/css?family=Google+Sans:400,500|Roboto:400,500" rel="stylesheet">
+ <style>
+ body {
+ margin: 0;
+ min-height: 100vh;
+ display: grid;
+ grid-template-columns: auto 0;
+ grid-template-rows: 64px 1fr;
+ grid-template-areas: "appbar options" "symbols options";
+ color: #3c4043;
+ font-family: "Roboto", sans-serif;
+ }
+
+ .appbar {
+ grid-area: appbar;
+ }
+ .appbar-inner {
+ height: 100%;
+ padding: 0 48px;
+ display: flex;
+ align-items: center;
+ }
+ .appbar-progress {
+ display: block;
+ width: 100%;
+ height: 4px;
+ -webkit-appearance: none;
+ appearance: none;
+ contain: strict;
+ background: #4285f499;
+ transition: opacity 0.5s ease;
+ }
+ .appbar-progress::-webkit-progress-bar {
+ background: transparent;
+ }
+ .appbar-progress::-webkit-progress-value {
+ background: #1a73e8;
+ transition: width 1s ease-in;
+ }
+ .appbar-progress[value="0"]::-webkit-progress-value {
+ transition: none;
+ }
+ .appbar-progress[value="1"] {
+ opacity: 0;
+ }
+ .appbar-progress[value="1"]::-webkit-progress-value {
+ transition-duration: 0.2s;
+ }
+ .error .appbar-progress {
+ background: #ea433599;
+ }
+ .error .appbar-progress::-webkit-progress-value {
+ background: #d93025;
+ }
+
+ .options {
+ visibility: hidden;
+ grid-area: options;
+ }
+
+ .symbols {
+ grid-area: symbols;
+ padding: 0 48px;
+ }
+ .tree-container {
+ margin: 0 auto;
+ max-width: 1200px;
+ }
+
+ .headline {
+ margin: 0;
+ font-family: "Google Sans", Arial, sans-serif;
+ font-weight: normal;
+ color: #202124;
+ font-size: 22px;
+ flex: 1;
+ }
+ .subtitle {
+ font-weight: 500;
+ color: #5f6368;
+ font-size: 13px;
+ }
+ .subhead,
+ .subhead-2 {
+ font-family: "Google Sans", Arial, sans-serif;
+ font-weight: 500;
+ font-size: 16px;
+ color: #3c4043;
+ }
+ .subhead-2 {
+ font-size: 14px;
+ }
+ .body-2 {
+ font-weight: 400;
+ font-size: 14px;
+ }
+ .caption {
+ font-size: 12px;
+ color: #5f6368;
+ }
+
+ ul {
+ list-style-type: none;
+ padding-left: 0;
+ }
+
+ .tree {
+ font-size: 13px;
+ }
+
+ .tree-header {
+ display: flex;
+ justify-content: space-between;
+ padding: 8px 0;
+ margin-left: 48px;
+ line-height: 24px;
+ border-bottom: 1px solid #dadce0;
+ }
+
+ [role="group"] {
+ padding-left: 13px;
+ border-left: 1px solid #dadce0;
+ margin-left: 10px;
+ }
+
+ .icon {
+ display: block;
+ margin-right: 6px;
+ }
+
+ /** Tree nodes */
+ .node {
+ display: flex;
+ padding-right: 8px;
+ margin-right: -8px;
+ align-items: center;
+ text-decoration: none;
+ color: inherit;
+ border-radius: 4px;
+ }
+ .node:hover {
+ background: #f1f3f4;
+ }
+ .node::before {
+ content: "";
+ display: inline-block;
+ margin: 10px;
+ width: 0;
+ height: 0;
+ }
+
+ [aria-expanded]>.node::before {
+ /** Draw a 5x10 triangle */
+ margin: 5px 7px 5px 8px;
+ border-style: solid;
+ border-width: 5px 0 5px 5px;
+ border-color: transparent transparent transparent currentColor;
+ transition: transform .1s ease-out;
+ }
+ [aria-expanded="true"]>.node::before {
+ transform: rotate(90deg);
+ }
+
+ /** Tree node sub items */
+ .symbol-name {
+ font-weight: 500;
+ word-break: break-word;
+ flex: 1;
+ }
+
+ .count,
+ .size,
+ .percent {
+ margin-left: 16px;
+ text-align: right;
+ color: #5f6368;
+ white-space: nowrap;
+ }
+ .shrunk {
+ color: #34a853;
+ }
+ .grew {
+ color: #ea4335;
+ }
+ .removed {
+ text-decoration: line-through;
+ }
+
+ .diff .size-header::after {
+ content: ' diff';
+ }
+ </style>
+ <link rel="stylesheet" href="options.css">
+ <link rel="icon" href="favicon.ico" sizes="16x16 32x32 256x256" type="image/x-icon">
+ <script defer src="shared.js"></script>
+ <script defer src="state.js"></script>
+ <script defer src="infocard-ui.js"></script>
+ <script defer src="tree-ui.js"></script>
+</head>
+
+<body>
+ <div class="scrim toggle-options" hidden></div>
+ <header class="appbar">
+ <div class="appbar-inner">
+ <h1 class="headline">Binary Size Analysis</h1>
+ <input type="file" name="upload" id="upload" accept=".ndjson" >
+ <label for="upload" class="text-button filled-button with-icon">
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="#fff">
+ <!--
+ Icons from https://material.io/tools/icons/?style=outline
+ with some custom icons designed in the same style
+ -->
+ <path d="M6 2a2 2 0 0 0-2 2v16c0 1.1.9 2 2 2h12a2 2 0 0 0 2-2V8l-6-6H6zm0 2h7v5h5v11H6V4zm6 7l-4 4h3v4h2v-4h3l-4-4z" />
+ </svg>
+ Upload data
+ </label>
+ <a href="https://chromium.googlesource.com/chromium/src/+/master/tools/binary_size/html_report_faq.md" class="icon-button" title="FAQ">
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#5f6368">
+ <path d="M11,18h2v-2h-2V18z M12,2C6.48,2,2,6.48,2,12s4.48,10,10,10s10-4.48,10-10S17.52,2,12,2z M12,20c-4.41,0-8-3.59-8-8
+ s3.59-8,8-8s8,3.59,8,8S16.41,20,12,20z M12,6c-2.21,0-4,1.79-4,4h2c0-1.1,0.9-2,2-2s2,0.9,2,2c0,2-3,1.75-3,5h2c0-2.25,3-2.5,3-5
+ C16,7.79,14.21,6,12,6z" />
+ </svg>
+ </a>
+ <button type="button" class="icon-button toggle-options" title="Settings">
+ <svg class="settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#5f6368">
+ <path d="M19.43,12.98c0.04-0.32,0.07-0.64,0.07-0.98c0-0.34-0.03-0.66-0.07-0.98l2.11-1.65c0.19-0.15,0.24-0.42,0.12-0.64l-2-3.46
+ c-0.09-0.16-0.26-0.25-0.44-0.25c-0.06,0-0.12,0.01-0.17,0.03l-2.49,1c-0.52-0.4-1.08-0.73-1.69-0.98l-0.38-2.65
+ C14.46,2.18,14.25,2,14,2h-4C9.75,2,9.54,2.18,9.51,2.42L9.13,5.07C8.52,5.32,7.96,5.66,7.44,6.05l-2.49-1
+ C4.89,5.03,4.83,5.02,4.77,5.02c-0.17,0-0.34,0.09-0.43,0.25l-2,3.46C2.21,8.95,2.27,9.22,2.46,9.37l2.11,1.65
+ C4.53,11.34,4.5,11.67,4.5,12c0,0.33,0.03,0.66,0.07,0.98l-2.11,1.65c-0.19,0.15-0.24,0.42-0.12,0.64l2,3.46
+ c0.09,0.16,0.26,0.25,0.44,0.25c0.06,0,0.12-0.01,0.17-0.03l2.49-1c0.52,0.4,1.08,0.73,1.69,0.98l0.38,2.65
+ C9.54,21.82,9.75,22,10,22h4c0.25,0,0.46-0.18,0.49-0.42l0.38-2.65c0.61-0.25,1.17-0.59,1.69-0.98l2.49,1
+ c0.06,0.02,0.12,0.03,0.18,0.03c0.17,0,0.34-0.09,0.43-0.25l2-3.46c0.12-0.22,0.07-0.49-0.12-0.64L19.43,12.98z M17.45,11.27
+ c0.04,0.31,0.05,0.52,0.05,0.73c0,0.21-0.02,0.43-0.05,0.73l-0.14,1.13l0.89,0.7l1.08,0.84l-0.7,1.21l-1.27-0.51l-1.04-0.42
+ l-0.9,0.68c-0.43,0.32-0.84,0.56-1.25,0.73l-1.06,0.43l-0.16,1.13L12.7,20H11.3l-0.19-1.35l-0.16-1.13l-1.06-0.43
+ c-0.43-0.18-0.83-0.41-1.23-0.71l-0.91-0.7l-1.06,0.43l-1.27,0.51l-0.7-1.21l1.08-0.84l0.89-0.7l-0.14-1.13
+ C6.52,12.43,6.5,12.2,6.5,12s0.02-0.43,0.05-0.73l0.14-1.13L5.8,9.44L4.72,8.6l0.7-1.21l1.27,0.51l1.04,0.42l0.9-0.68
+ c0.43-0.32,0.84-0.56,1.25-0.73l1.06-0.43l0.16-1.13L11.3,4h1.39l0.19,1.35l0.16,1.13l1.06,0.43c0.43,0.18,0.83,0.41,1.23,0.71
+ l0.91,0.7l1.06-0.43l1.27-0.51l0.7,1.21L18.2,9.44l-0.89,0.7L17.45,11.27z" />
+ <path d="M12,8c-2.21,0-4,1.79-4,4s1.79,4,4,4s4-1.79,4-4S14.21,8,12,8z M12,14c-1.1,0-2-0.9-2-2s0.9-2,2-2s2,0.9,2,2
+ S13.1,14,12,14z" />
+ </svg>
+ </button>
+ </div>
+ <progress value="0" id="progress" class="appbar-progress"></progress>
+ </header>
+ <link href="options.css" rel="stylesheet">
+ <form id="options" class="options" method="GET">
+ <header class="form-bar">
+ <button type="button" class="icon-button toggle-options" title="Close">
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#5f6368">
+ <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
+ </svg>
+ </button>
+ </header>
+
+ <h2 class="subhead">Size options</h2>
+ <p class="select-wrapper">
+ <select id="byteunit" name="byteunit">
+ <option value="B">B - bytes</option>
+ <option value="KiB">KiB - kilibytes</option>
+ <option value="MiB" selected>MiB - megabytes</option>
+ <option value="GiB">GiB - gigabytes</option>
+ </select>
+ <label class="select-label" for="byteunit">Byte unit</label>
+ </p>
+ <p class="checkbox-wrapper">
+ <input type="checkbox" id="methodcount" name="method_count" value="on">
+ <label class="checkbox-label" for="methodcount">Show dex method count rather than size</label>
+ </p>
+
+ <fieldset>
+ <legend class="subhead">Group symbols by</legend>
+ <div class="radio-wrapper">
+ <input type="radio" id="sourcepath" name="group_by" value="source_path" checked>
+ <label class="radio-label" for="sourcepath">Source path</label>
+ </div>
+ <div class="radio-wrapper">
+ <input type="radio" id="component" name="group_by" value="component">
+ <label class="radio-label" for="component">Component</label>
+ </div>
+ </fieldset>
+
+ <fieldset id="types-filter">
+ <legend class="subhead">Symbol types to show</legend>
+ <div class="checkbox-wrapper">
+ <input type="checkbox" id="filterbss" name="type" value="b">
+ <label class="checkbox-label" for="filterbss">
+ Uninitialized data (.bss)
+ </label>
+ </div>
+ <div class="checkbox-wrapper">
+ <input type="checkbox" id="filterdata" name="type" value="d" checked>
+ <label class="checkbox-label" for="filterdata">
+ Initialized data (.data)
+ </label>
+ </div>
+ <div class="checkbox-wrapper">
+ <input type="checkbox" id="filterrodata" name="type" value="r" checked>
+ <label class="checkbox-label" for="filterrodata">
+ Read-only data (.rodata)
+ </label>
+ </div>
+ <div class="checkbox-wrapper">
+ <input type="checkbox" id="filtertext" name="type" value="t" checked>
+ <label class="checkbox-label" for="filtertext">
+ Code (.text)
+ </label>
+ </div>
+ <div class="checkbox-wrapper">
+ <input type="checkbox" id="filtervtable" name="type" value="v" checked>
+ <label class="checkbox-label" for="filtervtable">
+ Vtable entries
+ </label>
+ </div>
+ <div class="checkbox-wrapper">
+ <input type="checkbox" id="filtergen" name="type" value="*" checked>
+ <label class="checkbox-label" for="filtergen">
+ Generated Symbols (typeinfo, thunks, etc)
+ </label>
+ </div>
+ <div class="checkbox-wrapper">
+ <input type="checkbox" id="filterdexnon" name="type" value="x" checked>
+ <label class="checkbox-label" for="filterdexnon">
+ Dex non-method entries
+ </label>
+ </div>
+ <div class="checkbox-wrapper">
+ <input type="checkbox" id="filterdex" name="type" value="m" checked>
+ <label class="checkbox-label" for="filterdex">
+ Dex methods
+ </label>
+ </div>
+ <div class="checkbox-wrapper">
+ <input type="checkbox" id="filterpak" name="type" value="p" checked>
+ <label class="checkbox-label" for="filterpak">
+ Locale Pak Entries
+ </label>
+ </div>
+ <div class="checkbox-wrapper">
+ <input type="checkbox" id="filterpaknon" name="type" value="P" checked>
+ <label class="checkbox-label" for="filterpaknon">
+ Non-Locale Pak Entries
+ </label>
+ </div>
+ <div class="checkbox-wrapper">
+ <input type="checkbox" id="filterother" name="type" value="o" checked>
+ <label class="checkbox-label" for="filterother">
+ Other Entries
+ </label>
+ </div>
+ <button type="button" class="text-button" id="type-all">Select all</button>
+ <button type="button" class="text-button" id="type-none">Select none</button>
+ </fieldset>
+
+ <fieldset>
+ <legend class="subhead">Advanced filters</legend>
+ <p class="input-wrapper">
+ <input type="number" id="minsize" name="min_size" value="0" min="0">
+ <label class="input-label" for="minsize">
+ Minimum size (bytes)
+ </label>
+ </p>
+ <fieldset>
+ <legend class="subhead-2">Regular expressions</legend>
+ <div class="input-wrapper">
+ <input class="input-regex" type="text" id="includeregex" name="include" placeholder=".+@.+">
+ <label class="input-label" for="includeregex">
+ Symbols must contain
+ </label>
+ </div>
+ <div class="input-wrapper">
+ <input class="input-regex" type="text" id="excluderegex" name="exclude" placeholder="\(.+\)">
+ <label class="input-label" for="excluderegex">
+ Symbols must exclude
+ </label>
+ </div>
+ </fieldset>
+ </fieldset>
+ </form>
+ <div class="symbols">
+ <div hidden id="icons">
+ <svg class="icon foldericon" height="24" width="24" fill="#5f6368">
+ <title>Directory</title>
+ <path d="M9.17,6l2,2H20v10L4,18V6H9.17 M10,4H4C2.9,4,2.01,4.9,2.01,6L2,18c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V8c0-1.1-0.9-2-2-2
+ h-8L10,4L10,4z" />
+ </svg>
+ <svg class='icon componenticon' height='24' width='24' fill='#5f6368'>
+ <title>Component</title>
+ <path d="M9,13.75c-2.34,0-7,1.17-7,3.5V19h14v-1.75C16,14.92,11.34,13.75,9,13.75z M4.34,17c0.84-0.58,2.87-1.25,4.66-1.25
+ s3.82,0.67,4.66,1.25H4.34z" />
+ <path d="M9,12c1.93,0,3.5-1.57,3.5-3.5C12.5,6.57,10.93,5,9,5S5.5,6.57,5.5,8.5C5.5,10.43,7.07,12,9,12z M9,7
+ c0.83,0,1.5,0.67,1.5,1.5S9.83,10,9,10S7.5,9.33,7.5,8.5S8.17,7,9,7z" />
+ <path d="M16.04,13.81C17.2,14.65,18,15.77,18,17.25V19h4v-1.75C22,15.23,18.5,14.08,16.04,13.81z" />
+ <path d="M15,12c1.93,0,3.5-1.57,3.5-3.5C18.5,6.57,16.93,5,15,5c-0.54,0-1.04,0.13-1.5,0.35c0.63,0.89,1,1.98,1,3.15
+ s-0.37,2.26-1,3.15C13.96,11.87,14.46,12,15,12z" />
+ </svg>
+ <svg class="icon javaclassicon" height="24" width="24" fill="#5f6368">
+ <title>Java class</title>
+ <path d="M6.6 1.44l-.82.83 2.1 2.1A6.96 6.96 0 0 0 5 10v1h14v-1a6.96 6.96 0 0 0-2.88-5.63l2.1-2.1-.82-.83-2.3 2.31a6.81 6.81 0 0 0-6.19 0L6.6 1.44zM9 7a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zM5 12v4.27C5 20 8.17 23 12 23s7-3 7-6.73V12H5zm2 2h10v2.27c0 2.6-2.2 4.73-5 4.73s-5-2.13-5-4.73V14z"
+ />
+ </svg>
+ <svg class="icon fileicon" height="24" width="24" fill="#5f6368">
+ <title>File</title>
+ <path d="M14,2H6C4.9,2,4.01,2.9,4.01,4L4,20c0,1.1,0.89,2,1.99,2H18c1.1,0,2-0.9,2-2V8L14,2z M6,20V4h7v5h5v11
+ L6,20z" />
+ </svg>
+ <svg class="icon bssicon" height="24" width="24" fill="#a142f4">
+ <title>Uninitialized data</title>
+ <path d="M6 2a2 2 0 0 0-2 2v16c0 1.1.9 2 2 2h12a2 2 0 0 0 2-2V8l-6-6H6zm0 2h7v5h5v11H6V4zm4 6v4h2v-4h-2zm0 6v2h2v-2h-2z"
+ />
+ </svg>
+ <svg class="icon dataicon" height="24" width="24" fill="#fa7b17">
+ <title>Initialized data</title>
+ <path d="M6 2a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6H6m0 2h7v5h5v11H6V4m2 8v2h8v-2H8m0 4v2h5v-2z" />
+ </svg>
+ <svg class="icon readonlyicon" height="24" width="24" fill="#24c1e0">
+ <title>Read-only data</title>
+ <path d="M6 2a2 2 0 0 0-2 2v16c0 1.1.9 2 2 2h12a2 2 0 0 0 2-2V8l-6-6H6zm0 2h7v5h5v11H6V4zm5.9 8c-2 0-3.7 1.2-4.4 3a4.7 4.7 0 0 0 8.8 0c-.7-1.8-2.4-3-4.4-3zm0 1a2 2 0 0 1 2 2 2 2 0 0 1-2 2 2 2 0 0 1-2-2 2 2 0 0 1 2-2zm0 .8a1.2 1.2 0 0 0-1.2 1.2 1.2 1.2 0 0 0 1.2 1.2 1.2 1.2 0 0 0 1.2-1.2 1.2 1.2 0 0 0-1.2-1.2z"
+ />
+ </svg>
+ <svg class="icon codeicon" height="24" width="24" fill="#1a73e8">
+ <title>Code</title>
+ <path d="M9.4,16.6L4.8,12l4.6-4.6L8,6l-6,6l6,6L9.4,16.6z M14.6,16.6l4.6-4.6l-4.6-4.6L16,6l6,6l-6,6L14.6,16.6z" />
+ </svg>
+ <svg class="icon vtableicon" height="24" width="24" fill="#fbbc04">
+ <title>Vtable entry</title>
+ <path d="M20,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h15c1.1,0,2-0.9,2-2V5C22,3.9,21.1,3,20,3z M20,5v3H5V5H20z M15,19h-5v-9h5V19z
+ M5,10h3v9H5V10z M17,19v-9h3v9H17z" />
+ </svg>
+ <svg class="icon generatedicon" height="24" width="24" fill="#f439a0">
+ <title>Generated symbol</title>
+ <path d="M6 2a2 2 0 0 0-2 2v16c0 1.1.9 2 2 2h12a2 2 0 0 0 2-2V8l-6-6H6zm0 2h7v5h5v11H6V4zm9.5 8l-.6 1.4-1.4.6 1.4.6.6 1.4.6-1.4 1.4-.6-1.4-.6-.6-1.4zm-6 1l-1 2-2 1 2 1 1 2 1-2 2-1-2-1-1-2z"
+ />
+ </svg>
+ <svg class="icon dexicon" height="24" width="24" fill="#ea4335">
+ <title>Dex non-method entry</title>
+ <path d="M6.6 1.44l-.82.83 2.1 2.1A6.96 6.96 0 0 0 5 10v1h14v-1a6.96 6.96 0 0 0-2.88-5.63l2.1-2.1-.82-.83-2.3 2.31a6.81 6.81 0 0 0-6.19 0L6.6 1.44zM9 7a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zM5 12v4.27C5 20 8.17 23 12 23s7-3 7-6.73V12H5zm2 2h10v2.27c0 2.6-2.2 4.73-5 4.73s-5-2.13-5-4.73V14z"
+ />
+ </svg>
+ <svg class="icon dexmethodicon" height="24" width="24" fill="#a50e0e">
+ <title>Dex method</title>
+ <path d="M6.6 1.44l-.82.83 2.1 2.1A6.96 6.96 0 0 0 5 10v1h14v-1a6.96 6.96 0 0 0-2.88-5.63l2.1-2.1-.82-.83-2.3 2.31a6.81 6.81 0 0 0-6.19 0L6.6 1.44zM9 7a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1zM5 12v4.27C5 20 8.17 23 12 23s7-3 7-6.73V12H5zm2 2h10v2.27c0 2.6-2.2 4.73-5 4.73s-5-2.13-5-4.73V14z"
+ />
+ </svg>
+ <svg class="icon localpakicon" height="24" width="24" fill="#34a853">
+ <title>Locale pak entry</title>
+ <path d="M5 3a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5zm0 2h5v2h2V5h7v14H5V5zm7 2v2h2V7h-2zm0 2h-2v2h2V9zm0 2v2h2v-2h-2zm0 2h-2v2h2v-2zm0 2v2h2v-2h-2z"
+ />
+ </svg>
+ <svg class="icon nonlocalpakicon" height="24" width="24" fill="#0d652d">
+ <title>Non-locale pak entry</title>
+ <path d="M5 3a2 2 0 0 0-2 2v14c0 1.1.9 2 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5zm0 2h5v2h2V5h7v14H5V5zm7 2v2h2V7h-2zm0 2h-2v2h2V9zm0 2v2h2v-2h-2zm0 2h-2v2h2v-2zm0 2v2h2v-2h-2z"
+ />
+ </svg>
+ <svg class="icon othericon" height="24" width="24" fill="#5f6368">
+ <title>Other entry</title>
+ <path d="M10.88 2l-.85 1.36L4 13h6v-2H7.6l3.28-5.23L12.28 8h2.35l-3.75-6zM12 10v10h10V10H12zm2 2h6v6h-6v-6zM2.21 15A5.52 5.52 0 0 0 10 21.4v-2.45A3.48 3.48 0 0 1 7.5 20a3.48 3.48 0 0 1-3.15-5H2.2z"
+ />
+ </svg>
+ </div>
+ <template id="treenode-container">
+ <li role="treeitem" aria-expanded="false" aria-describedby="infocard-container">
+ <a class="node" href="#" tabindex="-1" role="presentation">
+ <span class="symbol-name"></span>
+ <span class="size"></span>
+ </a>
+ <ul role="group"></ul>
+ </li>
+ </template>
+ <template id="treenode-symbol">
+ <li role="treeitem" aria-describedby="infocard-symbol">
+ <span class="node" tabindex="-1">
+ <span class="symbol-name"></span>
+ <span class="size"></span>
+ </span>
+ </li>
+ </template>
+ <main class="tree-container">
+ <header class="tree-header">
+ <span class="subtitle">Name</span>
+ <span class="subtitle size-header" id="size-header">Size</span>
+ </header>
+ <ul id="symboltree" class="tree" role="tree" aria-labelledby="headline"></ul>
+ </main>
+ <link href="infocard.css" rel="stylesheet">
+ <footer class="infocards">
+ <div class="infocard infocard-container open" id="infocard-container" hidden>
+ <div class="icon-info container-icon-info">
+ <canvas class="type-pie-info" height="80" width="80"></canvas>
+ <div></div>
+ </div>
+ <header class="header-info">
+ <h4 class="subhead size-info"></h4>
+ <p class="body-2 path-info"></p>
+ <p class="caption type-info"></p>
+ </header>
+ <table class="type-breakdown-info">
+ <thead>
+ <tr>
+ <th class="subhead-2">Type</th>
+ <th class="subhead-2 count">Count</th>
+ <th class="subhead-2 size">Total size</th>
+ <th class="subhead-2 percent">Percent</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr class="bss-info">
+ <th scope="row">.bss</th>
+ <td class="count"></td>
+ <td class="size"></td>
+ <td class="percent"></td>
+ </tr>
+ <tr class="data-info">
+ <th scope="row">.data and .data.*</th>
+ <td class="count"></td>
+ <td class="size"></td>
+ <td class="percent"></td>
+ </tr>
+ <tr class="rodata-info">
+ <th scope="row">.rodata</th>
+ <td class="count"></td>
+ <td class="size"></td>
+ <td class="percent"></td>
+ </tr>
+ <tr class="text-info">
+ <th scope="row">.text</th>
+ <td class="count"></td>
+ <td class="size"></td>
+ <td class="percent"></td>
+ </tr>
+ <tr class="vtable-info">
+ <th scope="row">Vtable entry</th>
+ <td class="count"></td>
+ <td class="size"></td>
+ <td class="percent"></td>
+ </tr>
+ <tr class="gen-info">
+ <th scope="row">Generated symbols</th>
+ <td class="count"></td>
+ <td class="size"></td>
+ <td class="percent"></td>
+ </tr>
+ <tr class="dexnon-info">
+ <th scope="row">Dex non-method entries</th>
+ <td class="count"></td>
+ <td class="size"></td>
+ <td class="percent"></td>
+ </tr>
+ <tr class="dex-info">
+ <th scope="row">Dex methods</th>
+ <td class="count"></td>
+ <td class="size"></td>
+ <td class="percent"></td>
+ </tr>
+ <tr class="pak-info">
+ <th scope="row">Locale pak entries</th>
+ <td class="count"></td>
+ <td class="size"></td>
+ <td class="percent"></td>
+ </tr>
+ <tr class="paknon-info">
+ <th scope="row">Non-locale pak entries</th>
+ <td class="count"></td>
+ <td class="size"></td>
+ <td class="percent"></td>
+ </tr>
+ <tr class="other-info">
+ <th scope="row">Other entries</th>
+ <td class="count"></td>
+ <td class="size"></td>
+ <td class="percent"></td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <div class="infocard infocard-symbol" id="infocard-symbol" hidden>
+ <div class="icon-info">
+ <div></div>
+ </div>
+ <header class="header-info">
+ <h4 class="subhead size-info"></h4>
+ <p class="body-2 path-info"></p>
+ </header>
+ <p class="caption type-info"></p>
+ </div>
+ </footer>
+ </div>
+</body>
+
+</html> \ No newline at end of file
diff --git a/chromium/tools/binary_size/libsupersize/static/infocard-ui.js b/chromium/tools/binary_size/libsupersize/static/infocard-ui.js
new file mode 100644
index 00000000000..7d04641f871
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/static/infocard-ui.js
@@ -0,0 +1,328 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// @ts-check
+'use strict';
+
+/**
+ * @fileoverview
+ * UI classes and methods for the info cards that display informations about
+ * symbols as the user hovers or focuses on them.
+ */
+
+const displayInfocard = (() => {
+ const _CANVAS_RADIUS = 40;
+
+ class Infocard {
+ /**
+ * @param {string} id
+ */
+ constructor(id) {
+ this._infocard = document.getElementById(id);
+ /** @type {HTMLHeadingElement} */
+ this._sizeInfo = this._infocard.querySelector('.size-info');
+ /** @type {HTMLParagraphElement} */
+ this._pathInfo = this._infocard.querySelector('.path-info');
+ /** @type {HTMLDivElement} */
+ this._iconInfo = this._infocard.querySelector('.icon-info');
+ /** @type {HTMLParagraphElement} */
+ this._typeInfo = this._infocard.querySelector('.type-info');
+
+ /**
+ * Last symbol type displayed.
+ * Tracked to avoid re-cloning the same icon.
+ * @type {string}
+ */
+ this._lastType = '';
+ }
+
+ /**
+ * Updates the size header, which normally displayed the byte size of the
+ * node followed by an abbreviated version.
+ *
+ * Example: "1,234 bytes (1.23 KiB)"
+ * @param {TreeNode} node
+ */
+ _updateSize(node) {
+ const {description, element, value} = getSizeContents(node);
+ const sizeFragment = dom.createFragment([
+ document.createTextNode(`${description} (`),
+ element,
+ document.createTextNode(')'),
+ ]);
+
+ // Update DOM
+ setSizeClasses(this._sizeInfo, value);
+
+ dom.replace(this._sizeInfo, sizeFragment);
+ }
+
+ /**
+ * Updates the path text, which shows the idPath of the node but highlights
+ * the symbol name portion using bold text.
+ * @param {TreeNode} node
+ */
+ _updatePath(node) {
+ const path = node.idPath.slice(0, node.shortNameIndex);
+ const boldShortName = dom.textElement(
+ 'span',
+ shortName(node),
+ 'symbol-name-info'
+ );
+ const pathFragment = dom.createFragment([
+ document.createTextNode(path),
+ boldShortName,
+ ]);
+
+ // Update DOM
+ dom.replace(this._pathInfo, pathFragment);
+ }
+
+ /**
+ * Updates the icon and type text. The type label is pulled from the
+ * title of the icon supplied.
+ * @param {SVGSVGElement} icon Icon to display
+ */
+ _setTypeContent(icon) {
+ const typeDescription = icon.querySelector('title').textContent;
+ icon.setAttribute('fill', '#fff');
+
+ this._typeInfo.textContent = typeDescription;
+ this._iconInfo.removeChild(this._iconInfo.lastElementChild);
+ this._iconInfo.appendChild(icon);
+ }
+
+ /**
+ * Toggle wheter or not the card is visible.
+ * @param {boolean} isHidden
+ */
+ setHidden(isHidden) {
+ if (isHidden) {
+ this._infocard.setAttribute('hidden', '');
+ } else {
+ this._infocard.removeAttribute('hidden');
+ }
+ }
+
+ /**
+ * Updates the DOM for the info card.
+ * @param {TreeNode} node
+ */
+ _updateInfocard(node) {
+ const type = node.type[0];
+
+ // Update DOM
+ this._updateSize(node);
+ this._updatePath(node);
+ if (type !== this._lastType) {
+ // No need to create a new icon if it is identical.
+ const icon = getIconTemplate(type);
+ this._setTypeContent(icon);
+ this._lastType = type;
+ }
+ }
+
+ /**
+ * Updates the card on the next animation frame.
+ * @param {TreeNode} node
+ */
+ updateInfocard(node) {
+ cancelAnimationFrame(Infocard._pendingFrame);
+ Infocard._pendingFrame = requestAnimationFrame(() =>
+ this._updateInfocard(node)
+ );
+ }
+ }
+
+ class SymbolInfocard extends Infocard {
+ /**
+ * @param {SVGSVGElement} icon Icon to display
+ */
+ _setTypeContent(icon) {
+ const color = icon.getAttribute('fill');
+ super._setTypeContent(icon);
+ this._iconInfo.style.backgroundColor = color;
+ }
+ }
+
+ class ContainerInfocard extends Infocard {
+ constructor(id) {
+ super(id);
+ this._tableBody = this._infocard.querySelector('tbody');
+ this._ctx = this._infocard.querySelector('canvas').getContext('2d');
+
+ /**
+ * @type {{[type:string]: HTMLTableRowElement}} Rows in the container
+ * infocard that represent a particular symbol type.
+ */
+ this._infoRows = {
+ b: this._tableBody.querySelector('.bss-info'),
+ d: this._tableBody.querySelector('.data-info'),
+ r: this._tableBody.querySelector('.rodata-info'),
+ t: this._tableBody.querySelector('.text-info'),
+ v: this._tableBody.querySelector('.vtable-info'),
+ '*': this._tableBody.querySelector('.gen-info'),
+ x: this._tableBody.querySelector('.dexnon-info'),
+ m: this._tableBody.querySelector('.dex-info'),
+ p: this._tableBody.querySelector('.pak-info'),
+ P: this._tableBody.querySelector('.paknon-info'),
+ o: this._tableBody.querySelector('.other-info'),
+ };
+
+ /**
+ * Update the DPI of the canvas for zoomed in and high density screens.
+ */
+ const _updateCanvasDpi = () => {
+ this._ctx.canvas.height = _CANVAS_RADIUS * 2 * devicePixelRatio;
+ this._ctx.canvas.width = _CANVAS_RADIUS * 2 * devicePixelRatio;
+ this._ctx.scale(devicePixelRatio, devicePixelRatio);
+ };
+
+ _updateCanvasDpi();
+ window.addEventListener('resize', _updateCanvasDpi);
+ }
+
+ /**
+ * @param {SVGSVGElement} icon Icon to display
+ */
+ _setTypeContent(icon) {
+ super._setTypeContent(icon);
+ icon.classList.add('canvas-overlay');
+ }
+
+ /**
+ * Draw a slice of a pie chart.
+ * @param {number} angleStart Starting angle, in radians.
+ * @param {number} percentage Percentage of circle to draw.
+ * @param {string} fillColor Color of the pie slice.
+ * @param {string} strokeColor Color of the pie slice border.
+ * @returns {number} Ending angle, in radians.
+ */
+ _drawSlice(angleStart, percentage, fillColor, strokeColor) {
+ const arcLength = Math.abs(percentage) * 2 * Math.PI;
+ const angleEnd = angleStart + arcLength;
+ if (arcLength === 0) return angleEnd;
+
+ // Update DOM
+ this._ctx.fillStyle = fillColor;
+ // Move cursor to center, where line will start
+ this._ctx.beginPath();
+ this._ctx.moveTo(40, 40);
+ // Move cursor to start of arc then draw arc
+ this._ctx.arc(40, 40, _CANVAS_RADIUS, angleStart, angleEnd);
+ // Move cursor back to center
+ this._ctx.closePath();
+ this._ctx.fill();
+
+ if (strokeColor) {
+ this._ctx.strokeStyle = strokeColor;
+ this._ctx.lineWidth = 16;
+ this._ctx.beginPath();
+ this._ctx.arc(40, 40, _CANVAS_RADIUS, angleStart, angleEnd);
+ this._ctx.stroke();
+ }
+
+ return angleEnd;
+ }
+
+ /**
+ * Update a row in the breakdown table with the given values.
+ * @param {HTMLTableRowElement} row
+ * @param {{size:number,count:number} | null} stats Total size of the
+ * symbols of a given type in a container.
+ * @param {number} percentage How much the size represents in relation to
+ * the total size of the symbols in the container.
+ */
+ _updateBreakdownRow(row, stats, percentage) {
+ if (stats == null || stats.size === 0) {
+ if (row.parentElement != null) {
+ this._tableBody.removeChild(row);
+ }
+ return;
+ }
+
+ const countColumn = row.querySelector('.count');
+ const sizeColumn = row.querySelector('.size');
+ const percentColumn = row.querySelector('.percent');
+
+ const countString = stats.count.toLocaleString(_LOCALE, {
+ useGrouping: true,
+ });
+ const sizeString = stats.size.toLocaleString(_LOCALE, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ useGrouping: true,
+ });
+ const percentString = percentage.toLocaleString(_LOCALE, {
+ style: 'percent',
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ });
+
+ // Update DOM
+ countColumn.textContent = countString;
+ sizeColumn.textContent = sizeString;
+ percentColumn.textContent = percentString;
+ this._tableBody.appendChild(row);
+ }
+
+ /**
+ * Update DOM for the container infocard
+ * @param {TreeNode} containerNode
+ */
+ _updateInfocard(containerNode) {
+ const extraRows = {...this._infoRows};
+ const statsEntries = Object.entries(containerNode.childStats).sort(
+ (a, b) => b[1].size - a[1].size
+ );
+ const diffMode = state.has('diff_mode');
+ let totalSize = 0;
+ for (const [, stats] of statsEntries) {
+ totalSize += Math.abs(stats.size);
+ }
+
+ // Update DOM
+ super._updateInfocard(containerNode);
+ let angleStart = 0;
+ for (const [type, stats] of statsEntries) {
+ delete extraRows[type];
+ const {color} = getIconStyle(type);
+ const percentage = stats.size / totalSize;
+ let stroke = '';
+ if (diffMode) {
+ stroke = stats.size > 0 ? '#ea4335' : '#34a853';
+ }
+
+ angleStart = this._drawSlice(angleStart, percentage, color, stroke);
+ this._updateBreakdownRow(this._infoRows[type], stats, percentage);
+ }
+
+ // Hide unused types
+ for (const row of Object.values(extraRows)) {
+ this._updateBreakdownRow(row, null, 0);
+ }
+ }
+ }
+
+ const _containerInfo = new ContainerInfocard('infocard-container');
+ const _symbolInfo = new SymbolInfocard('infocard-symbol');
+
+ /**
+ * Displays an infocard for the given symbol on the next frame.
+ * @param {TreeNode} node
+ */
+ function displayInfocard(node) {
+ if (_CONTAINER_TYPE_SET.has(node.type[0])) {
+ _containerInfo.updateInfocard(node);
+ _containerInfo.setHidden(false);
+ _symbolInfo.setHidden(true);
+ } else {
+ _symbolInfo.updateInfocard(node);
+ _symbolInfo.setHidden(false);
+ _containerInfo.setHidden(true);
+ }
+ }
+
+ return displayInfocard;
+})();
diff --git a/chromium/tools/binary_size/libsupersize/static/infocard.css b/chromium/tools/binary_size/libsupersize/static/infocard.css
new file mode 100644
index 00000000000..b8105844067
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/static/infocard.css
@@ -0,0 +1,113 @@
+/* Copyright 2018 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+.infocards {
+ visibility: hidden;
+ position: fixed;
+ bottom: 8px;
+ left: 8px;
+ right: 8px;
+ margin: 0 auto;
+ max-width: 512px;
+ max-height: 50vh;
+ overflow-y: auto;
+ background: white;
+ border-radius: 8px;
+ box-shadow: 0 1px 2px #3c40434d, 0 1px 3px 1px #3c404326;
+ transform: translateY(16px);
+ opacity: 0;
+ transition: 0.3s ease transform, 0.3s ease opacity, 0.3s ease visibility;
+}
+.tree-container:hover ~ .infocards,
+.tree-container.focused ~ .infocards {
+ visibility: visible;
+ opacity: 1;
+ transform: none;
+}
+
+.infocard {
+ display: grid;
+ padding: 16px;
+}
+.infocard-container {
+ grid-template-areas: 'header icon' 'type type';
+ grid-template-columns: auto 80px;
+ grid-column-gap: 16px;
+ grid-row-gap: 8px;
+}
+.infocard-symbol {
+ grid-template-areas: 'icon header' 'type type';
+ grid-template-columns: 40px auto;
+ grid-column-gap: 16px;
+}
+
+.infocard[hidden] {
+ display: none;
+}
+@media (min-width: 700px) {
+ .show-options .infocards {
+ right: 256px;
+ }
+}
+
+.icon-info {
+ grid-area: icon;
+ align-self: center;
+ padding: 8px 2px 8px 8px;
+ border-radius: 50%;
+}
+.container-icon-info {
+ position: relative;
+ padding: 0;
+ height: 80px;
+}
+.header-info {
+ grid-area: header;
+ color: #202124;
+}
+.size-info {
+ margin: 0 0 2px;
+}
+.path-info {
+ margin: 0 0 8px;
+ word-break: break-word;
+ color: #3c4043;
+}
+.symbol-name-info {
+ font-weight: 500;
+}
+.type-info {
+ grid-area: type;
+ margin-bottom: 0;
+}
+
+.type-pie-info {
+ height: 80px;
+ width: 80px;
+ border-radius: 50%;
+}
+.type-breakdown-info {
+ grid-area: type;
+ border-top: 1px solid #dadce0;
+ padding-top: 8px;
+ clear: right;
+ height: 0; /* Fixes bug with table height in Firefox */
+}
+.canvas-overlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ margin: auto;
+}
+
+th {
+ text-align: left;
+}
+th[scope='row'],
+td {
+ font-weight: normal;
+ font-size: 14px;
+}
diff --git a/chromium/tools/binary_size/libsupersize/static/options.css b/chromium/tools/binary_size/libsupersize/static/options.css
new file mode 100644
index 00000000000..20b15235cab
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/static/options.css
@@ -0,0 +1,291 @@
+/* Copyright 2018 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+/** Body modifier class, indicates when options should be visible. */
+.show-options {
+ grid-template-columns: auto 256px;
+}
+
+.show-options .options {
+ visibility: visible;
+}
+.show-options .settings {
+ fill: #1a73e8;
+}
+
+/** Black overlay shown on smaller screens when options is visible. */
+.scrim {
+ z-index: 5; /* Side panel layer */
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 256px;
+ background: #00000050;
+}
+
+/** Options side panel */
+.options {
+ z-index: 5; /* Side panel layer */
+ grid-area: options;
+ padding: 0 16px;
+ overflow-y: auto;
+ position: fixed;
+ right: 0;
+ top: 0;
+ height: 100vh;
+ width: 224px;
+ background: #fffffff5;
+ box-shadow: 0 1px 2px #3c40434d, 0 2px 6px 2px #3c404326;
+}
+
+fieldset {
+ border: 0;
+ padding: 0;
+ margin: 2em 0 1em;
+}
+.options fieldset:first-of-type {
+ margin-top: 1em;
+}
+legend {
+ margin: 1em 0;
+ padding: 0;
+}
+
+/** Toolbar */
+.form-bar {
+ display: flex;
+ justify-content: flex-end;
+ height: 64px;
+ align-items: center;
+}
+
+/** Buttons */
+.icon-button,
+.text-button {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ background: transparent;
+ border: 0;
+}
+
+.icon-button {
+ height: 40px;
+ width: 40px;
+ border-radius: 50%;
+}
+.icon-button:hover {
+ background: #0000001f;
+}
+
+.text-button {
+ padding: 0 8px;
+ line-height: 36px;
+ border-radius: 4px;
+ color: #1a73e8;
+ font-family: 'Google Sans', Arial, sans-serif;
+ font-weight: 500;
+ font-size: 14px;
+}
+.text-button:hover {
+ background: #d2e3fc80;
+}
+.text-button:hover:focus {
+ background: #d2e3fc;
+}
+.text-button:focus,
+.text-button:active {
+ background: #d2e3fce6;
+}
+
+.text-button.with-icon {
+ display: flex;
+ align-items: center;
+ padding: 0 16px 0 12px;
+ margin: 0 8px;
+}
+
+.filled-button {
+ background: #1a73e8;
+ color: white;
+}
+.filled-button:hover {
+ background: #287ae6;
+ box-shadow: 0 1px 2px #3c40434d, 0 1px 3px 1px #3c404326;
+}
+input:focus + label.filled-button:hover {
+ background: #5d9cee;
+}
+input:focus + label.filled-button {
+ background: #5094ed;
+ outline: #2e3436 dotted 1px;
+ outline: -webkit-focus-ring-color auto 5px;
+}
+.filled-button:active,
+input:focus + label.filled-button:active {
+ background: #1a73e8;
+ box-shadow: 0 1px 2px #3c40434d, 0 2px 6px 2px #3c404326;
+}
+
+/** <input type='text'> or <select> elements */
+.input-wrapper,
+.select-wrapper {
+ position: relative;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ background: rgba(0, 0, 0, 0.04);
+ margin-bottom: 1em;
+}
+input[type='text'],
+input[type='number'],
+select {
+ box-sizing: border-box;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ font: inherit;
+ background: transparent;
+ border: 0;
+ padding: 20px 12px 13px;
+ width: 100%;
+ caret-color: #1a73e8;
+}
+.input-label,
+.select-label {
+ position: absolute;
+ z-index: -1;
+ top: 0;
+ bottom: -1px;
+ left: 0;
+ right: 0;
+ font-size: 12px;
+ line-height: 20px;
+ padding: 0 12px;
+ color: #5f6368;
+ border-bottom: 1px solid currentColor;
+}
+.select-label::after {
+ content: '';
+ position: absolute;
+ top: calc(50% - 5px);
+ right: 4px;
+ margin: 5px 7px 5px 8px;
+ border-style: solid;
+ border-width: 5px 5px 0 5px;
+ border-color: currentColor transparent transparent transparent;
+ transition: transform 0.2s ease-out;
+}
+input[type='text']:focus + .input-label,
+input[type='number']:focus + .input-label,
+select:focus + .select-label {
+ color: #1a73e8;
+ bottom: -2px;
+ border-width: 2px;
+}
+select:focus + .select-label::after {
+ transform: rotate(180deg);
+}
+
+/** <input type='checkbox' or 'radio'> elements */
+input[type='checkbox'],
+input[type='radio'] {
+ position: absolute;
+ margin: 0;
+ height: 18px;
+ width: 18px;
+ opacity: 0;
+}
+.checkbox-wrapper,
+.radio-wrapper {
+ position: relative;
+}
+.checkbox-label,
+.radio-label {
+ display: block;
+ position: relative;
+ padding-left: 34px;
+ margin: 4px 0;
+ cursor: pointer;
+ font-size: 14px;
+}
+.checkbox-label::before,
+.checkbox-label::after,
+.radio-label::before,
+.radio-label::after {
+ position: absolute;
+ content: '';
+ border: 2px solid currentColor;
+}
+.checkbox-label::before,
+.radio-label::before {
+ width: 14px;
+ height: 14px;
+ border-radius: 2px;
+ left: 0;
+}
+.checkbox-label::after,
+.radio-label::after {
+ width: 4px;
+ opacity: 0;
+ transition: opacity 0.2s ease;
+}
+.checkbox-label::after {
+ height: 9px;
+ left: 6px;
+ top: 2px;
+ border-top-width: 0;
+ border-left-width: 0;
+ transform: rotate(45deg);
+}
+.radio-label::before {
+ border-radius: 50%;
+}
+.radio-label::after {
+ height: 4px;
+ left: 5px;
+ top: 5px;
+ background: currentColor;
+ border-radius: 50%;
+}
+input[type='checkbox']:checked + .checkbox-label,
+input[type='radio']:checked + .radio-label {
+ color: #1a73e8;
+}
+input[type='checkbox']:checked + .checkbox-label::after,
+input[type='radio']:checked + .radio-label::after {
+ opacity: 1;
+}
+input[type='checkbox']:disabled + .checkbox-label,
+input[type='radio']:disabled + .radio-label {
+ color: #80868b;
+}
+input[type='checkbox']:focus + .checkbox-label,
+input[type='radio']:focus + .radio-label {
+ outline: #2e3436 dotted 1px;
+ outline: -webkit-focus-ring-color auto 5px;
+}
+
+input[type='file'] {
+ opacity: 0;
+}
+
+/** Tweaks for smaller screen sizes */
+@media (max-width: 700px) {
+ .show-options {
+ grid-template-columns: auto 0;
+ }
+ .show-options .scrim {
+ display: block;
+ }
+ .appbar,
+ .symbols {
+ padding: 0 16px;
+ }
+ .appbar-progress {
+ margin: 0 -16px;
+ width: calc(100% + 32px);
+ }
+}
diff --git a/chromium/tools/binary_size/libsupersize/static/shared.js b/chromium/tools/binary_size/libsupersize/static/shared.js
new file mode 100644
index 00000000000..6892a57138a
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/static/shared.js
@@ -0,0 +1,141 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// @ts-check
+'use strict';
+
+/**
+ * @fileoverview
+ * Constants used by both the UI and Web Worker scripts.
+ */
+
+/**
+ * @typedef {object} TreeNode Node object used to represent the file tree. Can
+ * represent either a container or a symbol.
+ * @prop {TreeNode[] | null} children Child tree nodes. Null values indicate
+ * that there are children, but that they haven't been loaded in yet. Empty
+ * arrays indicate this is a leaf node.
+ * @prop {TreeNode | null} parent Parent tree node. null if this is a root node.
+ * @prop {string} idPath Full path to this node.
+ * @prop {number} shortNameIndex The name of the node is include in the idPath.
+ * This index indicates where to start to slice the idPath to read the name.
+ * @prop {number} size Byte size of this node and its children.
+ * @prop {string} type Type of this node. If this node has children, the string
+ * may have a second character to denote the most common child.
+ * @prop {{[type: string]: {size:number,count:number}}} childStats Stats about
+ * this node's descendants, organized by symbol type.
+ */
+
+/**
+ * @typedef {object} TreeProgress
+ * @prop {TreeNode} root Root node and its direct children.
+ * @prop {number} percent Number from (0-1] to represent percentage.
+ * @prop {boolean} diffMode True if we are currently showing the diff of two
+ * different size files.
+ * @prop {string} [error] Error message, if an error occured in the worker.
+ * If unset, then there was no error.
+ */
+
+/**
+ * @typedef {object} GetSizeResult
+ * @prop {string} description Description of the size, shown as hover text
+ * @prop {Node} element Abbreviated representation of the size, which can
+ * include DOM elements for styling.
+ * @prop {number} value The size number used to create the other strings.
+ */
+/**
+ * @typedef {(node: TreeNode, unit: string) => GetSizeResult} GetSize
+ */
+
+/** Abberivated keys used by FileEntrys in the JSON data file. */
+const _KEYS = Object.freeze({
+ SOURCE_PATH: /** @type {'p'} */ ('p'),
+ COMPONENT_INDEX: /** @type {'c'} */ ('c'),
+ FILE_SYMBOLS: /** @type {'s'} */ ('s'),
+ SYMBOL_NAME: /** @type {'n'} */ ('n'),
+ SIZE: /** @type {'b'} */ ('b'),
+ TYPE: /** @type {'t'} */ ('t'),
+ COUNT: /** @type {'u'} */ ('u'),
+});
+
+/**
+ * @enum {number} Various byte units and the corresponding amount of bytes
+ * that one unit represents.
+ */
+const _BYTE_UNITS = Object.freeze({
+ GiB: 1024 ** 3,
+ MiB: 1024 ** 2,
+ KiB: 1024 ** 1,
+ B: 1024 ** 0,
+});
+/** Set of all byte units */
+const _BYTE_UNITS_SET = new Set(Object.keys(_BYTE_UNITS));
+
+/**
+ * Special types used by containers, such as folders and files.
+ */
+const _CONTAINER_TYPES = {
+ DIRECTORY: 'D',
+ COMPONENT: 'C',
+ FILE: 'F',
+ JAVA_CLASS: 'J',
+};
+const _CONTAINER_TYPE_SET = new Set(Object.values(_CONTAINER_TYPES));
+
+/** Type for a dex method symbol */
+const _DEX_METHOD_SYMBOL_TYPE = 'm';
+/** Type for an 'other' symbol */
+const _OTHER_SYMBOL_TYPE = 'o';
+
+/** Set of all known symbol types. Container types are not included. */
+const _SYMBOL_TYPE_SET = new Set('bdrtv*xmpP' + _OTHER_SYMBOL_TYPE);
+
+/** Name used by a directory created to hold symbols with no name. */
+const _NO_NAME = '(No path)';
+
+/** Key where type is stored in the query string state. */
+const _TYPE_STATE_KEY = 'type';
+
+/** @type {string | string[]} */
+const _LOCALE = navigator.languages || navigator.language;
+
+/**
+ * Returns shortName for a tree node.
+ * @param {TreeNode} node
+ */
+function shortName(node) {
+ return node.idPath.slice(node.shortNameIndex);
+}
+
+/**
+ * Iterate through each type in the query string. Types can be expressed as
+ * repeats of the same key in the query string ("type=b&type=p") or as a long
+ * string with multiple characters ("type=bp").
+ * @param {string[]} typesList All values associated with the "type" key in the
+ * query string.
+ */
+function* types(typesList) {
+ for (const typeOrTypes of typesList) {
+ for (const typeChar of typeOrTypes) {
+ yield typeChar;
+ }
+ }
+}
+
+/**
+ * Limit how frequently `func` is called.
+ * @template {T}
+ * @param {T & Function} func
+ * @param {number} wait Time to wait before func can be called again (ms).
+ * @returns {T}
+ */
+function debounce(func, wait) {
+ /** @type {number} */
+ let timeoutId;
+ function debounced (...args) {
+ clearTimeout(timeoutId);
+ timeoutId = setTimeout(() => func(...args), wait);
+ };
+ return /** @type {any} */ (debounced);
+}
diff --git a/chromium/tools/binary_size/libsupersize/static/start-worker.js b/chromium/tools/binary_size/libsupersize/static/start-worker.js
new file mode 100644
index 00000000000..fb983b29cb1
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/static/start-worker.js
@@ -0,0 +1,95 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// @ts-check
+'use strict';
+
+const _innerWorker = new Worker('tree-worker.js');
+
+/**
+ * We use a worker to keep large tree creation logic off the UI thread.
+ * This class is used to interact with the worker.
+ */
+class TreeWorker {
+ /**
+ * @param {Worker} worker Web worker to wrap
+ */
+ constructor(worker) {
+ this._worker = worker;
+ /** ID counter used by `waitForResponse` */
+ this._requestId = 1;
+
+ /** @type {(data: TreeProgress) => void | null} callback for `loadTree` */
+ this._loadTreeCallback = null;
+
+ this._worker.addEventListener('message', event => {
+ if (this._loadTreeCallback && event.data.id === 0) {
+ this._loadTreeCallback(event.data);
+ }
+ });
+ }
+
+ /**
+ *
+ * @param {string} action
+ * @param {any} data
+ */
+ _waitForResponse(action, data) {
+ const id = ++this._requestId;
+ return new Promise((resolve, reject) => {
+ const handleResponse = event => {
+ if (event.data.id === id) {
+ this._worker.removeEventListener('message', handleResponse);
+ if (event.data.error) {
+ reject(event.data.error);
+ } else {
+ resolve(event.data.result);
+ }
+ }
+ };
+
+ this._worker.addEventListener('message', handleResponse);
+ this._worker.postMessage({id, action, data});
+ });
+ }
+
+ /**
+ * Get data for a node with `idPath`. Loads information about the node and its
+ * direct children. Deeper children can be loaded by calling this function
+ * again.
+ * @param {string} idPath Path of the node to find
+ * @returns {Promise<TreeNode | null>}
+ */
+ openNode(idPath) {
+ return this._waitForResponse('open', idPath);
+ }
+
+ /**
+ * Set callback used after `loadTree` is first called.
+ * @param {(data: TreeProgress) => void} callback Called when the worker
+ * has some data to display. Complete when `progress` is 1.
+ */
+ setOnProgressHandler(callback) {
+ this._loadTreeCallback = callback;
+ }
+
+ /**
+ * Loads the tree data given on a worker thread and replaces the tree view in
+ * the UI once complete. Uses query string as state for the options.
+ * Use `onProgress` before calling `loadTree`.
+ * @param {string} input
+ * @returns {Promise<TreeProgress>}
+ */
+ loadTree(input = null) {
+ return this._waitForResponse('load', {
+ input,
+ options: location.search.slice(1),
+ });
+ }
+}
+
+const worker = new TreeWorker(_innerWorker);
+// Kick off the worker ASAP so it can start parsing data faster.
+// Subsequent calls will just use a worker locally.
+const treeReady = worker.loadTree('data.ndjson');
diff --git a/chromium/tools/binary_size/libsupersize/static/state.js b/chromium/tools/binary_size/libsupersize/static/state.js
new file mode 100644
index 00000000000..0b34bdce6c8
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/static/state.js
@@ -0,0 +1,402 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// @ts-check
+'use strict';
+
+/**
+ * @fileoverview
+ * Methods for manipulating the state and the DOM of the page
+ */
+
+/** @type {HTMLFormElement} Form containing options and filters */
+const form = document.getElementById('options');
+
+/** Utilities for working with the DOM */
+const dom = {
+ /**
+ * Create a document fragment from the given nodes
+ * @param {Iterable<Node>} nodes
+ * @returns {DocumentFragment}
+ */
+ createFragment(nodes) {
+ const fragment = document.createDocumentFragment();
+ for (const node of nodes) fragment.appendChild(node);
+ return fragment;
+ },
+ /**
+ * Removes all the existing children of `parent` and inserts
+ * `newChild` in their place
+ * @param {Node} parent
+ * @param {Node | null} newChild
+ */
+ replace(parent, newChild) {
+ while (parent.firstChild) parent.removeChild(parent.firstChild);
+ if (newChild != null) parent.appendChild(newChild);
+ },
+ /**
+ * Builds a text element in a single statement.
+ * @param {string} tagName Type of the element, such as "span".
+ * @param {string} text Text content for the element.
+ * @param {string} [className] Class to apply to the element.
+ */
+ textElement(tagName, text, className) {
+ const element = document.createElement(tagName);
+ element.textContent = text;
+ if (className) element.className = className;
+ return element;
+ },
+};
+
+/** Build utilities for working with the state. */
+function _initState() {
+ const _DEFAULT_FORM = new FormData(form);
+
+ /**
+ * State is represented in the query string and
+ * can be manipulated by this object. Keys in the query match with
+ * input names.
+ */
+ let _filterParams = new URLSearchParams(location.search.slice(1));
+ const typeList = _filterParams.getAll(_TYPE_STATE_KEY);
+ _filterParams.delete(_TYPE_STATE_KEY);
+ for (const type of types(typeList)) {
+ _filterParams.append(_TYPE_STATE_KEY, type);
+ }
+
+ const state = Object.freeze({
+ /**
+ * Returns a string from the current query string state.
+ * Can optionally restrict valid values for the query.
+ * Values not present in the query will return null, or the default
+ * value if supplied.
+ * @param {string} key
+ * @param {object} [options]
+ * @param {string} [options.default] Default to use if key is not present
+ * in the state
+ * @param {Set<string>} [options.valid] If provided, values must be in this
+ * set to be returned. Invalid values will return null or `defaultValue`.
+ * @returns {string | null}
+ */
+ get(key, options = {}) {
+ const [val = null] = state.getAll(key, {
+ default: options.default ? [options.default] : null,
+ valid: options.valid,
+ });
+ return val;
+ },
+ /**
+ * Returns all string values for a key from the current query string state.
+ * Can optionally provide default values used if there are no values.
+ * @param {string} key
+ * @param {object} [options]
+ * @param {string[]} [options.default] Default to use if key is not present
+ * in the state.
+ * @param {Set<string>} [options.valid] If provided, values must be in this
+ * set to be returned. Invalid values will be omitted.
+ * @returns {string[]}
+ */
+ getAll(key, options = {}) {
+ let vals = _filterParams.getAll(key);
+ if (options.valid != null) {
+ vals = vals.filter(val => options.valid.has(val));
+ }
+ if (options.default != null && vals.length === 0) {
+ vals = options.default;
+ }
+ return vals;
+ },
+ /**
+ * Checks if a key is present in the query string state.
+ * @param {string} key
+ * @returns {boolean}
+ */
+ has(key) {
+ return _filterParams.has(key);
+ },
+ /**
+ * Formats the filter state as a string.
+ */
+ toString() {
+ const copy = new URLSearchParams(_filterParams);
+ const types = [...new Set(copy.getAll(_TYPE_STATE_KEY))];
+ if (types.length > 0) copy.set(_TYPE_STATE_KEY, types.join(''));
+ return `?${copy.toString()}`;
+ },
+ /**
+ * Saves a key and value into a temporary state not displayed in the URL.
+ * @param {string} key
+ * @param {string | null} value
+ */
+ set(key, value) {
+ if (value == null) {
+ _filterParams.delete(key);
+ } else {
+ _filterParams.set(key, value);
+ }
+ history.replaceState(null, null, state.toString());
+ },
+ });
+
+ // Update form inputs to reflect the state from URL.
+ for (const element of form.elements) {
+ if (element.name) {
+ const input = /** @type {HTMLInputElement} */ (element);
+ const values = _filterParams.getAll(input.name);
+ const [value] = values;
+ if (value) {
+ switch (input.type) {
+ case 'checkbox':
+ input.checked = values.includes(input.value);
+ break;
+ case 'radio':
+ input.checked = value === input.value;
+ break;
+ default:
+ input.value = value;
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Yields only entries that have been modified in
+ * comparison to `_DEFAULT_FORM`.
+ * @param {FormData} modifiedForm
+ */
+ function* onlyChangedEntries(modifiedForm) {
+ // Remove default values
+ for (const key of modifiedForm.keys()) {
+ const modifiedValues = modifiedForm.getAll(key);
+ const defaultValues = _DEFAULT_FORM.getAll(key);
+
+ const valuesChanged =
+ modifiedValues.length !== defaultValues.length ||
+ modifiedValues.some((v, i) => v !== defaultValues[i]);
+ if (valuesChanged) {
+ for (const value of modifiedValues) {
+ yield [key, value];
+ }
+ }
+ }
+ }
+
+ // Update the state when the form changes.
+ function _updateStateFromForm() {
+ const modifiedForm = new FormData(form);
+ _filterParams = new URLSearchParams(onlyChangedEntries(modifiedForm));
+ history.replaceState(null, null, state.toString());
+ }
+
+ form.addEventListener('change', _updateStateFromForm);
+
+ return state;
+}
+
+function _startListeners() {
+ const _SHOW_OPTIONS_STORAGE_KEY = 'show-options';
+
+ /** @type {HTMLFieldSetElement} */
+ const typesFilterContainer = document.getElementById('types-filter');
+ /** @type {HTMLInputElement} */
+ const methodCountInput = form.elements.namedItem('method_count');
+ /** @type {HTMLFieldSetElement} */
+ const byteunit = form.elements.namedItem('byteunit');
+ /** @type {HTMLCollectionOf<HTMLInputElement>} */
+ const typeCheckboxes = form.elements.namedItem(_TYPE_STATE_KEY);
+ /** @type {HTMLSpanElement} */
+ const sizeHeader = document.getElementById('size-header');
+
+ /**
+ * The settings dialog on the side can be toggled on and off by elements with
+ * a 'toggle-options' class.
+ */
+ function _toggleOptions() {
+ const openedOptions = document.body.classList.toggle('show-options');
+ localStorage.setItem(_SHOW_OPTIONS_STORAGE_KEY, openedOptions.toString());
+ }
+ for (const button of document.getElementsByClassName('toggle-options')) {
+ button.addEventListener('click', _toggleOptions);
+ }
+ // Default to open if getItem returns null
+ if (localStorage.getItem(_SHOW_OPTIONS_STORAGE_KEY) !== 'false') {
+ document.body.classList.add('show-options');
+ }
+
+ /**
+ * Disable some fields when method_count is set
+ */
+ function setMethodCountModeUI() {
+ if (methodCountInput.checked) {
+ byteunit.setAttribute('disabled', '');
+ typesFilterContainer.setAttribute('disabled', '');
+ sizeHeader.textContent = 'Methods';
+ } else {
+ byteunit.removeAttribute('disabled');
+ typesFilterContainer.removeAttribute('disabled');
+ sizeHeader.textContent = 'Size';
+ }
+ }
+ setMethodCountModeUI();
+ methodCountInput.addEventListener('change', setMethodCountModeUI);
+
+ document.getElementById('type-all').addEventListener('click', () => {
+ for (const checkbox of typeCheckboxes) {
+ checkbox.checked = true;
+ }
+ form.dispatchEvent(new Event('change'));
+ });
+ document.getElementById('type-none').addEventListener('click', () => {
+ for (const checkbox of typeCheckboxes) {
+ checkbox.checked = false;
+ }
+ form.dispatchEvent(new Event('change'));
+ });
+}
+
+function _makeIconTemplateGetter() {
+ const _icons = document.getElementById('icons');
+
+ /**
+ * @type {{[type:string]: SVGSVGElement}} Icon elements
+ * that correspond to each symbol type.
+ */
+ const symbolIcons = {
+ D: _icons.querySelector('.foldericon'),
+ C: _icons.querySelector('.componenticon'),
+ J: _icons.querySelector('.javaclassicon'),
+ F: _icons.querySelector('.fileicon'),
+ b: _icons.querySelector('.bssicon'),
+ d: _icons.querySelector('.dataicon'),
+ r: _icons.querySelector('.readonlyicon'),
+ t: _icons.querySelector('.codeicon'),
+ v: _icons.querySelector('.vtableicon'),
+ '*': _icons.querySelector('.generatedicon'),
+ x: _icons.querySelector('.dexicon'),
+ m: _icons.querySelector('.dexmethodicon'),
+ p: _icons.querySelector('.localpakicon'),
+ P: _icons.querySelector('.nonlocalpakicon'),
+ o: _icons.querySelector('.othericon'), // used as default icon
+ };
+
+ /** @type {Map<string, {color:string,description:string}>} */
+ const iconInfoCache = new Map();
+
+ /**
+ * Returns the SVG icon template element corresponding to the given type.
+ * @param {string} type Symbol type character.
+ * @param {boolean} readonly If true, the original template is returned.
+ * If false, a copy is returned that can be modified.
+ * @returns {SVGSVGElement}
+ */
+ function getIconTemplate(type, readonly = false) {
+ const iconTemplate = symbolIcons[type] || symbolIcons[_OTHER_SYMBOL_TYPE];
+ return readonly ? iconTemplate : iconTemplate.cloneNode(true);
+ }
+
+ /**
+ * Returns style info about SVG icon template element corresponding to the
+ * given type.
+ * @param {string} type Symbol type character.
+ */
+ function getIconStyle(type) {
+ let info = iconInfoCache.get(type);
+ if (info == null) {
+ const icon = getIconTemplate(type, true);
+ info = {
+ color: icon.getAttribute('fill'),
+ description: icon.querySelector('title').textContent,
+ };
+ iconInfoCache.set(type, info);
+ }
+ return info;
+ }
+
+ return {getIconTemplate, getIconStyle};
+}
+
+function _makeSizeTextGetter() {
+ const _SIZE_CHANGE_CUTOFF = 50000;
+
+ /**
+ * Create the contents for the size element of a tree node.
+ * The unit to use is selected from the current state.
+ *
+ * If in method count mode, size instead represents the amount of methods in
+ * the node. Otherwise, the original number of bytes will be displayed.
+ *
+ * @param {TreeNode} node Node whose size is the number of bytes to use for
+ * the size text
+ * @returns {GetSizeResult} Object with hover text title and
+ * size element body. Can be consumed by `_applySizeFunc()`
+ */
+ function getSizeContents(node) {
+ if (state.has('method_count')) {
+ const {count: methodCount = 0} =
+ node.childStats[_DEX_METHOD_SYMBOL_TYPE] || {};
+ const methodStr = methodCount.toLocaleString(_LOCALE, {
+ useGrouping: true,
+ });
+
+ return {
+ element: document.createTextNode(methodStr),
+ description: `${methodStr} method${methodCount === 1 ? '' : 's'}`,
+ value: methodCount,
+ };
+ } else {
+ const bytes = node.size;
+ const unit = state.get('byteunit', {
+ default: 'MiB',
+ valid: _BYTE_UNITS_SET,
+ });
+ // Format the bytes as a number with 2 digits after the decimal point
+ const text = (bytes / _BYTE_UNITS[unit]).toLocaleString(_LOCALE, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ });
+ const textNode = document.createTextNode(`${text} `);
+
+ // Display the suffix with a smaller font
+ const suffixElement = dom.textElement('small', unit);
+
+ const bytesGrouped = bytes.toLocaleString(_LOCALE, {useGrouping: true});
+
+ return {
+ element: dom.createFragment([textNode, suffixElement]),
+ description: `${bytesGrouped} bytes`,
+ value: bytes,
+ };
+ }
+ }
+
+ /**
+ * Set classes on an element based on the size it represents.
+ * @param {HTMLElement} sizeElement
+ * @param {number} value
+ */
+ function setSizeClasses(sizeElement, value) {
+ const shouldHaveStyle =
+ state.has('diff_mode') && Math.abs(value) > _SIZE_CHANGE_CUTOFF;
+ if (shouldHaveStyle) {
+ if (value < 0) {
+ sizeElement.classList.add('shrunk');
+ sizeElement.classList.remove('grew');
+ } else {
+ sizeElement.classList.remove('shrunk');
+ sizeElement.classList.add('grew');
+ }
+ } else {
+ sizeElement.classList.remove('shrunk', 'grew');
+ }
+ }
+
+ return {getSizeContents, setSizeClasses};
+}
+
+/** Utilities for working with the state */
+const state = _initState();
+const {getIconTemplate, getIconStyle} = _makeIconTemplateGetter();
+const {getSizeContents, setSizeClasses} = _makeSizeTextGetter();
+_startListeners();
diff --git a/chromium/tools/binary_size/libsupersize/static/tree-ui.js b/chromium/tools/binary_size/libsupersize/static/tree-ui.js
new file mode 100644
index 00000000000..5e8d6143b7f
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/static/tree-ui.js
@@ -0,0 +1,411 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// @ts-check
+'use strict';
+
+/**
+ * @fileoverview
+ * UI classes and methods for the Tree View in the
+ * Binary Size Analysis HTML report.
+ */
+
+{
+ /** Capture one of: "::", "../", "./", "/", "#" */
+ const _SPECIAL_CHAR_REGEX = /(::|(?:\.*\/)+|#)/g;
+ /** Insert zero-width space after capture group */
+ const _ZERO_WIDTH_SPACE = '$&\u200b';
+
+ // Templates for tree nodes in the UI.
+ /** @type {HTMLTemplateElement} Template for leaves in the tree */
+ const _leafTemplate = document.getElementById('treenode-symbol');
+ /** @type {HTMLTemplateElement} Template for trees */
+ const _treeTemplate = document.getElementById('treenode-container');
+
+ const _symbolTree = document.getElementById('symboltree');
+
+ /**
+ * @type {HTMLCollectionOf<HTMLAnchorElement | HTMLSpanElement>}
+ * HTMLCollection of all nodes. Updates itself automatically.
+ */
+ const _liveNodeList = document.getElementsByClassName('node');
+ /**
+ * @type {HTMLCollectionOf<HTMLSpanElement>}
+ * HTMLCollection of all size elements. Updates itself automatically.
+ */
+ const _liveSizeSpanList = document.getElementsByClassName('size');
+
+ /**
+ * @type {WeakMap<HTMLElement, Readonly<TreeNode>>}
+ * Associates UI nodes with the corresponding tree data object
+ * so that event listeners and other methods can
+ * query the original data.
+ */
+ const _uiNodeData = new WeakMap();
+
+ /**
+ * Sets focus to a new tree element while updating the element that last had
+ * focus. The tabindex property is used to avoid needing to tab through every
+ * single tree item in the page to reach other areas.
+ * @param {number | HTMLElement} el Index of tree node in `_liveNodeList`
+ */
+ function _focusTreeElement(el) {
+ const lastFocused = document.activeElement;
+ if (_uiNodeData.has(lastFocused)) {
+ // Update DOM
+ lastFocused.tabIndex = -1;
+ }
+ const element = typeof el === 'number' ? _liveNodeList[el] : el;
+ if (element != null) {
+ // Update DOM
+ element.tabIndex = 0;
+ element.focus();
+ }
+ }
+
+ /**
+ * Click event handler to expand or close the child group of a tree.
+ * @param {Event} event
+ */
+ async function _toggleTreeElement(event) {
+ event.preventDefault();
+
+ /** @type {HTMLAnchorElement | HTMLSpanElement} */
+ const link = event.currentTarget;
+ const element = link.parentElement;
+ const group = link.nextElementSibling;
+
+ const isExpanded = element.getAttribute('aria-expanded') === 'true';
+ if (isExpanded) {
+ // Update DOM
+ element.setAttribute('aria-expanded', 'false');
+ dom.replace(group, null);
+ } else {
+ element.setAttribute('aria-expanded', 'true');
+
+ let data = _uiNodeData.get(link);
+ if (data == null || data.children == null) {
+ const idPath = link.querySelector('.symbol-name').title;
+ data = await worker.openNode(idPath);
+ _uiNodeData.set(link, data);
+ }
+
+ const newElements = data.children.map(child => newTreeElement(child));
+ if (newElements.length === 1) {
+ // Open the inner element if it only has a single child.
+ // Ensures nodes like "java"->"com"->"google" are opened all at once.
+ newElements[0].querySelector('.node').click();
+ }
+ const newElementsFragment = dom.createFragment(newElements);
+
+ // Update DOM
+ requestAnimationFrame(() => {
+ group.appendChild(newElementsFragment);
+ });
+ }
+ }
+
+ /**
+ * Keydown event handler to move focus for the given element
+ * @param {KeyboardEvent} event
+ */
+ function _handleKeyNavigation(event) {
+ /** @type {HTMLAnchorElement | HTMLSpanElement} */
+ const link = event.target;
+ const focusIndex = Array.prototype.indexOf.call(_liveNodeList, link);
+
+ /** Focus the tree element immediately following this one */
+ function _focusNext() {
+ if (focusIndex > -1 && focusIndex < _liveNodeList.length - 1) {
+ event.preventDefault();
+ _focusTreeElement(focusIndex + 1);
+ }
+ }
+
+ /** Open or close the tree element */
+ function _toggle() {
+ event.preventDefault();
+ link.click();
+ }
+
+ /**
+ * Focus the tree element at `index` if it starts with `char`
+ * @param {string} char
+ * @param {number} index
+ */
+ function _focusIfStartsWith(char, index) {
+ const data = _uiNodeData.get(_liveNodeList[index]);
+ if (shortName(data).startsWith(char)) {
+ event.preventDefault();
+ _focusTreeElement(index);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ switch (event.key) {
+ // Space should act like clicking or pressing enter & toggle the tree.
+ case ' ':
+ _toggle();
+ break;
+ // Move to previous focusable node
+ case 'ArrowUp':
+ if (focusIndex > 0) {
+ event.preventDefault();
+ _focusTreeElement(focusIndex - 1);
+ }
+ break;
+ // Move to next focusable node
+ case 'ArrowDown':
+ _focusNext();
+ break;
+ // If closed tree, open tree. Otherwise, move to first child.
+ case 'ArrowRight': {
+ const data = _uiNodeData.get(link);
+ if (!data.children || data.children.length !== 0) {
+ const isExpanded =
+ link.parentElement.getAttribute('aria-expanded') === 'true';
+ if (isExpanded) {
+ _focusNext();
+ } else {
+ _toggle();
+ }
+ }
+ break;
+ }
+ // If opened tree, close tree. Otherwise, move to parent.
+ case 'ArrowLeft':
+ {
+ const isExpanded =
+ link.parentElement.getAttribute('aria-expanded') === 'true';
+ if (isExpanded) {
+ _toggle();
+ } else {
+ const groupList = link.parentElement.parentElement;
+ if (groupList.getAttribute('role') === 'group') {
+ event.preventDefault();
+ _focusTreeElement(groupList.previousElementSibling);
+ }
+ }
+ }
+ break;
+ // Focus first node
+ case 'Home':
+ event.preventDefault();
+ _focusTreeElement(0);
+ break;
+ // Focus last node on screen
+ case 'End':
+ event.preventDefault();
+ _focusTreeElement(_liveNodeList.length - 1);
+ break;
+ // Expand all sibling nodes
+ case '*':
+ const groupList = link.parentElement.parentElement;
+ if (groupList.getAttribute('role') === 'group') {
+ event.preventDefault();
+ for (const li of groupList.children) {
+ if (li.getAttribute('aria-expanded') !== 'true') {
+ li.querySelector('.node').click();
+ }
+ }
+ }
+ break;
+ // If a letter was pressed, find a node starting with that character.
+ default:
+ if (event.key.length === 1 && event.key.match(/\S/)) {
+ for (let i = focusIndex + 1; i < _liveNodeList.length; i++) {
+ if (_focusIfStartsWith(event.key, i)) return;
+ }
+ for (let i = 0; i < focusIndex; i++) {
+ if (_focusIfStartsWith(event.key, i)) return;
+ }
+ }
+ break;
+ }
+ }
+
+ /**
+ * Replace the contents of the size element for a tree node.
+ * @param {HTMLElement} sizeElement Element that should display the size
+ * @param {TreeNode} node
+ */
+ function _setSize(sizeElement, node) {
+ const {description, element, value} = getSizeContents(node);
+
+ // Replace the contents of '.size' and change its title
+ dom.replace(sizeElement, element);
+ sizeElement.title = description;
+ setSizeClasses(sizeElement, value);
+ }
+
+ /**
+ * Inflate a template to create an element that represents one tree node.
+ * The element will represent a tree or a leaf, depending on if the tree
+ * node object has any children. Trees use a slightly different template
+ * and have click event listeners attached.
+ * @param {TreeNode} data Data to use for the UI.
+ * @returns {DocumentFragment}
+ */
+ function newTreeElement(data) {
+ const isLeaf = data.children && data.children.length === 0;
+ const template = isLeaf ? _leafTemplate : _treeTemplate;
+ const element = document.importNode(template.content, true);
+
+ // Associate clickable node & tree data
+ /** @type {HTMLAnchorElement | HTMLSpanElement} */
+ const link = element.querySelector('.node');
+ _uiNodeData.set(link, Object.freeze(data));
+
+ // Icons are predefined in the HTML through hidden SVG elements
+ const type = data.type[0];
+ const icon = getIconTemplate(type);
+ if (!isLeaf) {
+ const symbolStyle = getIconStyle(data.type[1]);
+ icon.setAttribute('fill', symbolStyle.color);
+ }
+ // Insert an SVG icon at the start of the link to represent type
+ link.insertBefore(icon, link.firstElementChild);
+
+ // Set the symbol name and hover text
+ /** @type {HTMLSpanElement} */
+ const symbolName = element.querySelector('.symbol-name');
+ symbolName.textContent = shortName(data).replace(
+ _SPECIAL_CHAR_REGEX,
+ _ZERO_WIDTH_SPACE
+ );
+ symbolName.title = data.idPath;
+
+ if (state.has('method_count') && type === _DEX_METHOD_SYMBOL_TYPE) {
+ const {count = 0} = data.childStats[type] || {};
+ if (count < 0) {
+ symbolName.classList.add('removed');
+ }
+ }
+
+ // Set the byte size and hover text
+ _setSize(element.querySelector('.size'), data);
+
+ link.addEventListener('mouseover', event =>
+ displayInfocard(_uiNodeData.get(event.currentTarget))
+ );
+ if (!isLeaf) {
+ link.addEventListener('click', _toggleTreeElement);
+ }
+
+ return element;
+ }
+
+ // When the `byteunit` state changes, update all .size elements in the page
+ form.elements.namedItem('byteunit').addEventListener('change', event => {
+ event.stopPropagation();
+ state.set(event.currentTarget.name, event.currentTarget.value);
+ // Update existing size elements with the new unit
+ for (const sizeElement of _liveSizeSpanList) {
+ const data = _uiNodeData.get(sizeElement.parentElement);
+ if (data) _setSize(sizeElement, data);
+ }
+ });
+
+ _symbolTree.addEventListener('keydown', _handleKeyNavigation);
+ _symbolTree.addEventListener('focusin', event => {
+ displayInfocard(_uiNodeData.get(event.target));
+ event.currentTarget.parentElement.classList.add('focused');
+ });
+ _symbolTree.addEventListener('focusout', event =>
+ event.currentTarget.parentElement.classList.remove('focused')
+ );
+
+ self.newTreeElement = newTreeElement;
+}
+
+{
+ class ProgressBar {
+ /** @param {string} id */
+ constructor(id) {
+ /** @type {HTMLProgressElement} */
+ this._element = document.getElementById(id);
+ this.lastValue = this._element.value;
+ }
+
+ setValue(val) {
+ if (val === 0 || val >= this.lastValue) {
+ this._element.value = val;
+ this.lastValue = val;
+ } else {
+ // Reset to 0 so the progress bar doesn't animate backwards.
+ this.setValue(0);
+ requestAnimationFrame(() => this.setValue(val));
+ }
+ }
+ }
+
+ /** @type {HTMLUListElement} */
+ const _symbolTree = document.getElementById('symboltree');
+ /** @type {HTMLInputElement} */
+ const _fileUpload = document.getElementById('upload');
+ const _progress = new ProgressBar('progress');
+
+ /**
+ * Displays the given data as a tree view
+ * @param {TreeProgress} message
+ */
+ function displayTree(message) {
+ const {root, percent, diffMode, error} = message;
+ /** @type {DocumentFragment | null} */
+ let rootElement = null;
+ if (root) {
+ rootElement = newTreeElement(root);
+ /** @type {HTMLAnchorElement} */
+ const link = rootElement.querySelector('.node');
+ // Expand the root UI node
+ link.click();
+ link.tabIndex = 0;
+ }
+ state.set('diff_mode', diffMode ? 'on' : null);
+
+ // Double requestAnimationFrame ensures that the code inside executes in a
+ // different frame than the above tree element creation.
+ requestAnimationFrame(() =>
+ requestAnimationFrame(() => {
+ _progress.setValue(percent);
+ if (error) {
+ document.body.classList.add('error');
+ } else {
+ document.body.classList.remove('error');
+ }
+ if (diffMode) {
+ document.body.classList.add('diff');
+ } else {
+ document.body.classList.remove('diff');
+ }
+
+ dom.replace(_symbolTree, rootElement);
+ })
+ );
+ }
+
+ treeReady.then(displayTree);
+ worker.setOnProgressHandler(displayTree);
+
+ _fileUpload.addEventListener('change', event => {
+ const input = /** @type {HTMLInputElement} */ (event.currentTarget);
+ const file = input.files.item(0);
+ const fileUrl = URL.createObjectURL(file);
+ worker.loadTree(fileUrl).then(displayTree);
+ // Clean up afterwards so new files trigger event
+ input.value = '';
+ });
+
+ form.addEventListener('change', () => {
+ _progress.setValue(0);
+ worker.loadTree().then(displayTree);
+ });
+ form.addEventListener('submit', event => {
+ event.preventDefault();
+ _progress.setValue(0);
+ worker.loadTree().then(displayTree);
+ });
+}
diff --git a/chromium/tools/binary_size/libsupersize/static/tree-worker.js b/chromium/tools/binary_size/libsupersize/static/tree-worker.js
new file mode 100644
index 00000000000..46aa5323d80
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/static/tree-worker.js
@@ -0,0 +1,759 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// @ts-check
+'use strict';
+
+/**
+ * @fileoverview
+ * Web worker code to parse JSON data from binary_size into data for the UI to
+ * display.
+ */
+
+/**
+ * @typedef {object} Meta
+ * @prop {string[]} components
+ * @prop {number} total
+ * @prop {boolean} diff_mode
+ */
+/**
+ * @typedef {object} SymbolEntry JSON object representing a single symbol.
+ * @prop {string} n Name of the symbol.
+ * @prop {number} b Byte size of the symbol, divided by num_aliases.
+ * @prop {string} t Single character string to indicate the symbol type.
+ * @prop {number} [u] Count value indicating how many symbols this entry
+ * represents. Negative value when removed in a diff.
+ */
+/**
+ * @typedef {object} FileEntry JSON object representing a single file and its
+ * symbols.
+ * @prop {string} p Path to the file (source_path).
+ * @prop {number} c Index of the file's component in meta (component_index).
+ * @prop {SymbolEntry[]} s - Symbols belonging to this node. Array of objects.
+ */
+
+importScripts('./shared.js');
+
+const _PATH_SEP = '/';
+
+/** @param {FileEntry} fileEntry */
+function getSourcePath(fileEntry) {
+ return fileEntry[_KEYS.SOURCE_PATH];
+}
+
+/**
+ * Find the last index of either '/' or `sep` in the given path.
+ * @param {string} path
+ * @param {string} sep
+ */
+function lastIndexOf(path, sep) {
+ if (sep === _PATH_SEP) {
+ return path.lastIndexOf(_PATH_SEP);
+ } else {
+ return Math.max(path.lastIndexOf(sep), path.lastIndexOf(_PATH_SEP));
+ }
+}
+
+/**
+ * Return the dirname of the pathname 'path'. In a file path, this is the
+ * full path of its folder.
+ * @param {string} path Path to find dirname of.
+ * @param {string} sep Path seperator, such as '/'.
+ */
+function dirname(path, sep) {
+ return path.substring(0, lastIndexOf(path, sep));
+}
+
+/**
+ * Compare two nodes for sorting. Used in sortTree.
+ * @param {TreeNode} a
+ * @param {TreeNode} b
+ */
+function _compareFunc(a, b) {
+ return Math.abs(b.size) - Math.abs(a.size);
+}
+
+/**
+ * Make a node with some default arguments
+ * @param {Partial<TreeNode>} options
+ * Values to use for the node. If a value is
+ * omitted, a default will be used instead.
+ * @returns {TreeNode}
+ */
+function createNode(options) {
+ const {idPath, type, shortNameIndex, size = 0, childStats = {}} = options;
+ return {
+ children: [],
+ parent: null,
+ childStats,
+ idPath,
+ shortNameIndex,
+ size,
+ type,
+ };
+}
+
+/**
+ * Class used to build a tree from a list of symbol objects.
+ * Add each file node using `addFileEntry()`, then call `build()` to finalize
+ * the tree and return the root node. The in-progress tree can be obtained from
+ * the `rootNode` property.
+ */
+class TreeBuilder {
+ /**
+ * @param {object} options
+ * @param {(fileEntry: FileEntry) => string} options.getPath Called to get the
+ * id path of a symbol's file entry.
+ * @param {(symbolNode: TreeNode) => boolean} options.filterTest Called to see
+ * if a symbol should be included. If a symbol fails the test, it will not be
+ * attached to the tree.
+ * @param {string} options.sep Path seperator used to find parent names.
+ */
+ constructor(options) {
+ this._getPath = options.getPath;
+ this._filterTest = options.filterTest;
+ this._sep = options.sep || _PATH_SEP;
+
+ this.rootNode = createNode({
+ idPath: this._sep,
+ shortNameIndex: 0,
+ type: this._containerType(this._sep),
+ });
+ /** @type {Map<string, TreeNode>} Cache for directory nodes */
+ this._parents = new Map();
+
+ /**
+ * Regex used to split the `idPath` when finding nodes. Equivalent to
+ * one of: "/" or |sep|
+ */
+ this._splitter = new RegExp(`[/${this._sep}]`);
+ }
+
+ /**
+ * Link a node to a new parent. Will go up the tree to update parent sizes to
+ * include the new child.
+ * @param {TreeNode} node Child node.
+ * @param {TreeNode} directParent New parent node.
+ */
+ static _attachToParent(node, directParent) {
+ // Link the nodes together
+ directParent.children.push(node);
+ node.parent = directParent;
+
+ const additionalSize = node.size;
+ const additionalStats = Object.entries(node.childStats);
+
+ // Update the size and childStats of all ancestors
+ while (node.parent != null) {
+ const {parent} = node;
+ const [containerType, lastBiggestType] = parent.type;
+ let {size: lastBiggestSize = 0} =
+ parent.childStats[lastBiggestType] || {};
+ for (const [type, stat] of additionalStats) {
+ const parentStat = parent.childStats[type] || {size: 0, count: 0};
+
+ parentStat.size += stat.size;
+ parentStat.count += stat.count;
+ parent.childStats[type] = parentStat;
+
+ const absSize = Math.abs(parentStat.size);
+ if (absSize > lastBiggestSize) {
+ parent.type = `${containerType}${type}`;
+ lastBiggestSize = absSize;
+ }
+ }
+
+ parent.size += additionalSize;
+ node = parent;
+ }
+ }
+
+ /**
+ * Merges dex method symbols such as "Controller#get" and "Controller#set"
+ * into containers, based on the class of the dex methods.
+ * @param {TreeNode} node
+ */
+ static _joinDexMethodClasses(node) {
+ const hasDexMethods = node.childStats[_DEX_METHOD_SYMBOL_TYPE] != null;
+ if (!hasDexMethods || node.children == null) return node;
+
+ if (node.type[0] === _CONTAINER_TYPES.FILE) {
+ /** @type {Map<string, TreeNode>} */
+ const javaClassContainers = new Map();
+ /** @type {TreeNode[]} */
+ const otherSymbols = [];
+
+ // Place all dex methods into buckets
+ for (const childNode of node.children) {
+ // Java classes are denoted with a "#", such as "LogoView#onDraw"
+ const splitIndex = childNode.idPath.lastIndexOf('#');
+
+ const isDexMethodWithClass =
+ childNode.type === _DEX_METHOD_SYMBOL_TYPE &&
+ splitIndex > childNode.shortNameIndex;
+
+ if (isDexMethodWithClass) {
+ // Get the idPath of the class
+ const classIdPath = childNode.idPath.slice(0, splitIndex);
+
+ let classNode = javaClassContainers.get(classIdPath);
+ if (classNode == null) {
+ classNode = createNode({
+ idPath: classIdPath,
+ shortNameIndex: childNode.shortNameIndex,
+ type: _CONTAINER_TYPES.JAVA_CLASS,
+ });
+ javaClassContainers.set(classIdPath, classNode);
+ }
+
+ // Adjust the dex method's short name so it starts after the "#"
+ childNode.shortNameIndex = splitIndex + 1;
+ TreeBuilder._attachToParent(childNode, classNode);
+ } else {
+ otherSymbols.push(childNode);
+ }
+ }
+
+ node.children = otherSymbols;
+ for (const containerNode of javaClassContainers.values()) {
+ // Delay setting the parent until here so that `_attachToParent`
+ // doesn't add method stats twice
+ containerNode.parent = node;
+ node.children.push(containerNode);
+ }
+ } else {
+ node.children.forEach(TreeBuilder._joinDexMethodClasses);
+ }
+ return node;
+ }
+
+ /**
+ * Formats a tree node by removing references to its desendants and ancestors.
+ * This reduces how much data is sent to the UI thread at once. For large
+ * trees, serialization and deserialization of the entire tree can take ~7s.
+ *
+ * Only children up to `depth` will be kept, and deeper children will be
+ * replaced with `null` to indicate that there were children by they were
+ * removed.
+ *
+ * Leaves with no children will always have an empty children array.
+ * If a tree has only 1 child, it is kept as the UI will expand chains of
+ * single children in the tree.
+ *
+ * Additionally sorts the formatted portion of the tree.
+ * @param {TreeNode} node Node to format
+ * @param {number} depth How many levels of children to keep.
+ * @returns {TreeNode}
+ */
+ static formatNode(node, depth = 1) {
+ const childDepth = depth - 1;
+ // `null` represents that the children have not been loaded yet
+ let children = null;
+ if (depth > 0 || node.children.length <= 1) {
+ // If depth is larger than 0, include the children.
+ // If there are 0 children, include the empty array to indicate the node
+ // is a leaf.
+ // If there is 1 child, include it so the UI doesn't need to make a
+ // roundtrip in order to expand the chain.
+ children = node.children
+ .map(n => TreeBuilder.formatNode(n, childDepth))
+ .sort(_compareFunc);
+ }
+
+ return TreeBuilder._joinDexMethodClasses({
+ ...node,
+ children,
+ parent: null,
+ });
+ }
+
+ /**
+ * Returns the container type for a parent node.
+ * @param {string} childIdPath
+ * @private
+ */
+ _containerType(childIdPath) {
+ const useAlternateType =
+ childIdPath.lastIndexOf(this._sep) > childIdPath.lastIndexOf(_PATH_SEP);
+ if (useAlternateType) {
+ return _CONTAINER_TYPES.COMPONENT;
+ } else {
+ return _CONTAINER_TYPES.DIRECTORY;
+ }
+ }
+
+ /**
+ * Helper to return the parent of the given node. The parent is determined
+ * based in the idPath and the path seperator. If the parent doesn't yet
+ * exist, one is created and stored in the parents map.
+ * @param {TreeNode} childNode
+ * @private
+ */
+ _getOrMakeParentNode(childNode) {
+ // Get idPath of this node's parent.
+ let parentPath;
+ if (childNode.idPath === '') parentPath = _NO_NAME;
+ else parentPath = dirname(childNode.idPath, this._sep);
+
+ // check if parent exists
+ let parentNode;
+ if (parentPath === '') {
+ // parent is root node if dirname is ''
+ parentNode = this.rootNode;
+ } else {
+ // get parent from cache if it exists, otherwise create it
+ parentNode = this._parents.get(parentPath);
+ if (parentNode == null) {
+ parentNode = createNode({
+ idPath: parentPath,
+ shortNameIndex: lastIndexOf(parentPath, this._sep) + 1,
+ type: this._containerType(childNode.idPath),
+ });
+ this._parents.set(parentPath, parentNode);
+ }
+ }
+
+ // attach node to the newly found parent
+ TreeBuilder._attachToParent(childNode, parentNode);
+ return parentNode;
+ }
+
+ /**
+ * Iterate through every file node generated by supersize. Each node includes
+ * symbols that belong to that file. Create a tree node for each file with
+ * tree nodes for that file's symbols attached. Afterwards attach that node to
+ * its parent directory node, or create it if missing.
+ * @param {FileEntry} fileEntry File entry from data file
+ */
+ addFileEntry(fileEntry) {
+ const idPath = this._getPath(fileEntry);
+ // make node for this
+ const fileNode = createNode({
+ idPath,
+ shortNameIndex: lastIndexOf(idPath, this._sep) + 1,
+ type: _CONTAINER_TYPES.FILE,
+ });
+ // build child nodes for this file's symbols and attach to self
+ for (const symbol of fileEntry[_KEYS.FILE_SYMBOLS]) {
+ const size = symbol[_KEYS.SIZE];
+ const type = symbol[_KEYS.TYPE];
+ const count = symbol[_KEYS.COUNT] || 1;
+ const symbolNode = createNode({
+ // Join file path to symbol name with a ":"
+ idPath: `${idPath}:${symbol[_KEYS.SYMBOL_NAME]}`,
+ shortNameIndex: idPath.length + 1,
+ size,
+ type: symbol[_KEYS.TYPE],
+ childStats: {[type]: {size, count}},
+ });
+
+ if (this._filterTest(symbolNode)) {
+ TreeBuilder._attachToParent(symbolNode, fileNode);
+ }
+ }
+ // unless we filtered out every symbol belonging to this file,
+ if (fileNode.children.length > 0) {
+ // build all ancestor nodes for this file
+ let orphanNode = fileNode;
+ while (orphanNode.parent == null && orphanNode !== this.rootNode) {
+ orphanNode = this._getOrMakeParentNode(orphanNode);
+ }
+ }
+ }
+
+ /**
+ * Finalize the creation of the tree and return the root node.
+ */
+ build() {
+ this._getPath = () => '';
+ this._filterTest = () => false;
+ this._parents.clear();
+ return this.rootNode;
+ }
+
+ /**
+ * Internal handler for `find` to search for a node.
+ * @private
+ * @param {string[]} idPathList
+ * @param {TreeNode} node
+ * @returns {TreeNode | null}
+ */
+ _find(idPathList, node) {
+ if (node == null) {
+ return null;
+ } else if (idPathList.length === 0) {
+ // Found desired node
+ return node;
+ }
+
+ const [shortNameToFind] = idPathList;
+ const child = node.children.find(n => shortName(n) === shortNameToFind);
+
+ return this._find(idPathList.slice(1), child);
+ }
+
+ /**
+ * Find a node with a given `idPath` by traversing the tree.
+ * @param {string} idPath
+ */
+ find(idPath) {
+ // If `idPath` is the root's ID, return the root
+ if (idPath === this.rootNode.idPath) {
+ return this.rootNode;
+ }
+
+ const symbolIndex = idPath.indexOf(':');
+ let path;
+ if (symbolIndex > -1) {
+ const filePath = idPath.slice(0, symbolIndex);
+ const symbolName = idPath.slice(symbolIndex + 1);
+
+ path = filePath.split(this._splitter);
+ path.push(symbolName);
+ } else {
+ path = idPath.split(this._splitter);
+ }
+
+ // If the path is empty, it refers to the _NO_NAME container.
+ if (path[0] === '') {
+ path.unshift(_NO_NAME);
+ }
+
+ return this._find(path, this.rootNode);
+ }
+}
+
+/**
+ * Wrapper around fetch for requesting the same resource multiple times.
+ */
+class DataFetcher {
+ constructor(input) {
+ /** @type {AbortController | null} */
+ this._controller = null;
+ this.setInput(input);
+ }
+
+ /**
+ * Sets the input that describes what will be fetched. Also clears the cache.
+ * @param {string | Request} input URL to the resource you want to fetch.
+ */
+ setInput(input) {
+ if (typeof this._input === 'string' && this._input.startsWith('blob:')) {
+ // Revoke the previous Blob url to prevent memory leaks
+ URL.revokeObjectURL(this._input);
+ }
+
+ /** @type {Uint8Array | null} */
+ this._cache = null;
+ this._input = input;
+ }
+
+ /**
+ * Starts a new request and aborts the previous one.
+ * @param {string | Request} url
+ */
+ async fetch(url) {
+ if (this._controller) this._controller.abort();
+ this._controller = new AbortController();
+ return fetch(url, {
+ credentials: 'same-origin',
+ signal: this._controller.signal,
+ });
+ }
+
+ /**
+ * Yields binary chunks as Uint8Arrays. After a complete run, the bytes are
+ * cached and future calls will yield the cached Uint8Array instead.
+ */
+ async *arrayBufferStream() {
+ if (this._cache) {
+ yield this._cache;
+ return;
+ }
+
+ const response = await this.fetch(this._input);
+ let result;
+ // Use streams, if supported, so that we can show in-progress data instead
+ // of waiting for the entire data file to download. The file can be >100 MB,
+ // so streams ensure slow connections still see some data.
+ if (response.body) {
+ const reader = response.body.getReader();
+
+ /** @type {Uint8Array[]} Store received bytes to merge later */
+ let buffer = [];
+ /** Total size of received bytes */
+ let byteSize = 0;
+ while (true) {
+ // Read values from the stream
+ const {done, value} = await reader.read();
+ if (done) break;
+
+ const chunk = new Uint8Array(value, 0, value.length);
+ yield chunk;
+ buffer.push(chunk);
+ byteSize += chunk.length;
+ }
+
+ // We just cache a single typed array to save some memory and make future
+ // runs consistent with the no streams mode.
+ result = new Uint8Array(byteSize);
+ let i = 0;
+ for (const chunk of buffer) {
+ result.set(chunk, i);
+ i += chunk.length;
+ }
+ } else {
+ // In-memory version for browsers without stream support
+ result = new Uint8Array(await response.arrayBuffer());
+ yield result;
+ }
+
+ this._cache = result;
+ }
+
+ /**
+ * Transforms a binary stream into a newline delimited JSON (.ndjson) stream.
+ * Each yielded value corresponds to one line in the stream.
+ * @returns {AsyncIterable<Meta | FileEntry>}
+ */
+ async *newlineDelimtedJsonStream() {
+ const decoder = new TextDecoder();
+ const decoderArgs = {stream: true};
+ let textBuffer = '';
+
+ for await (const bytes of this.arrayBufferStream()) {
+ if (this._controller.signal.aborted) {
+ throw new DOMException('Request was aborted', 'AbortError');
+ }
+
+ textBuffer += decoder.decode(bytes, decoderArgs);
+ const lines = textBuffer.split('\n');
+ [textBuffer] = lines.splice(lines.length - 1, 1);
+
+ for (const line of lines) {
+ yield JSON.parse(line);
+ }
+ }
+ }
+}
+
+/**
+ * Parse the options represented as a query string, into an object.
+ * Includes checks for valid values.
+ * @param {string} options Query string
+ */
+function parseOptions(options) {
+ const params = new URLSearchParams(options);
+
+ const groupBy = params.get('group_by') || 'source_path';
+ const methodCountMode = params.has('method_count');
+
+ let minSymbolSize = Number(params.get('min_size'));
+ if (Number.isNaN(minSymbolSize)) {
+ minSymbolSize = 0;
+ }
+
+ const includeRegex = params.get('include');
+ const excludeRegex = params.get('exclude');
+
+ /** @type {Set<string>} */
+ let typeFilter;
+ if (methodCountMode) {
+ typeFilter = new Set(_DEX_METHOD_SYMBOL_TYPE);
+ } else {
+ typeFilter = new Set(types(params.getAll(_TYPE_STATE_KEY)));
+ if (typeFilter.size === 0) {
+ typeFilter = new Set(_SYMBOL_TYPE_SET);
+ typeFilter.delete('b');
+ }
+ }
+
+ /** @type {Array<(symbolNode: TreeNode) => boolean>} */
+ const filters = [];
+
+ /** Ensure symbol size is past the minimum */
+ if (minSymbolSize > 0) {
+ filters.push(s => Math.abs(s.size) >= minSymbolSize);
+ }
+
+ /** Ensure the symbol size wasn't filtered out */
+ if (typeFilter.size < _SYMBOL_TYPE_SET.size) {
+ filters.push(s => typeFilter.has(s.type));
+ }
+
+ if (includeRegex) {
+ const regex = new RegExp(includeRegex);
+ filters.push(s => regex.test(s.idPath));
+ }
+ if (excludeRegex) {
+ const regex = new RegExp(excludeRegex);
+ filters.push(s => !regex.test(s.idPath));
+ }
+
+ /**
+ * Check that a symbol node passes all the filters in the filters array.
+ * @param {TreeNode} symbolNode
+ */
+ function filterTest(symbolNode) {
+ return filters.every(fn => fn(symbolNode));
+ }
+
+ return {groupBy, filterTest};
+}
+
+/** @type {TreeBuilder | null} */
+let builder = null;
+const fetcher = new DataFetcher('data.ndjson');
+
+/**
+ * Assemble a tree when this worker receives a message.
+ * @param {string} options Query string containing options for the builder.
+ * @param {(msg: TreeProgress) => void} onProgress
+ * @returns {Promise<TreeProgress>}
+ */
+async function buildTree(options, onProgress) {
+ const {groupBy, filterTest} = parseOptions(options);
+
+ /** @type {Meta | null} Object from the first line of the data file */
+ let meta = null;
+
+ /** @type {{ [gropyBy: string]: (fileEntry: FileEntry) => string }} */
+ const getPathMap = {
+ component(fileEntry) {
+ const component = meta.components[fileEntry[_KEYS.COMPONENT_INDEX]];
+ const path = getSourcePath(fileEntry);
+ return `${component || '(No component)'}>${path}`;
+ },
+ source_path: getSourcePath,
+ };
+
+ builder = new TreeBuilder({
+ sep: groupBy === 'component' ? '>' : _PATH_SEP,
+ getPath: getPathMap[groupBy],
+ filterTest,
+ });
+
+ /**
+ * Creates data to post to the UI thread. Defaults will be used for the root
+ * and percent values if not specified.
+ * @param {{root?:TreeNode,percent?:number,error?:Error}} data Default data
+ * values to post.
+ */
+ function createProgressMessage(data = {}) {
+ let {percent} = data;
+ if (percent == null) {
+ if (meta == null) {
+ percent = 0;
+ } else {
+ percent = Math.max(builder.rootNode.size / meta.total, 0.1);
+ }
+ }
+
+ const message = {
+ root: TreeBuilder.formatNode(data.root || builder.rootNode),
+ percent,
+ diffMode: meta && meta.diff_mode,
+ };
+ if (data.error) {
+ message.error = data.error.message;
+ }
+ return message;
+ }
+
+ /**
+ * Post data to the UI thread. Defaults will be used for the root and percent
+ * values if not specified.
+ */
+ function postToUi() {
+ const message = createProgressMessage();
+ message.id = 0;
+ onProgress(message);
+ }
+
+ try {
+ // Post partial state every second
+ let lastBatchSent = Date.now();
+ for await (const dataObj of fetcher.newlineDelimtedJsonStream()) {
+ if (meta == null) {
+ // First line of data is used to store meta information.
+ meta = /** @type {Meta} */ (dataObj);
+ postToUi();
+ } else {
+ builder.addFileEntry(/** @type {FileEntry} */ (dataObj));
+ const currentTime = Date.now();
+ if (currentTime - lastBatchSent > 500) {
+ postToUi();
+ await Promise.resolve(); // Pause loop to check for worker messages
+ lastBatchSent = currentTime;
+ }
+ }
+ }
+
+ return createProgressMessage({
+ root: builder.build(),
+ percent: 1,
+ });
+ } catch (error) {
+ if (error.name === 'AbortError') {
+ console.info(error.message);
+ } else {
+ console.error(error);
+ }
+ return createProgressMessage({error});
+ }
+}
+
+const actions = {
+ /** @param {{input:string,options:string}} data */
+ load(data) {
+ if (data.input) fetcher.setInput(data.input);
+ return buildTree(data.options, progress => {
+ // @ts-ignore
+ self.postMessage(progress);
+ });
+ },
+ /** @param {string} path */
+ async open(path) {
+ if (!builder) throw new Error('Called open before load');
+ const node = builder.find(path);
+ return TreeBuilder.formatNode(node);
+ },
+};
+
+/**
+ * Call the requested action function with the given data. If an error is thrown
+ * or rejected, post the error message to the UI thread.
+ * @param {number} id Unique message ID.
+ * @param {string} action Action type, corresponding to a key in `actions.`
+ * @param {any} data Data to supply to the action function.
+ */
+async function runAction(id, action, data) {
+ try {
+ const result = await actions[action](data);
+ // @ts-ignore
+ self.postMessage({id, result});
+ } catch (err) {
+ // @ts-ignore
+ self.postMessage({id, error: err.message});
+ throw err;
+ }
+}
+
+const runActionDebounced = debounce(runAction, 0);
+
+/**
+ * @param {MessageEvent} event Event for when this worker receives a message.
+ */
+self.onmessage = async event => {
+ const {id, action, data} = event.data;
+ if (action === 'load') {
+ // Loading large files will block the worker thread until complete or when
+ // an await statement is reached. During this time, multiple load messages
+ // can pile up due to filters being adjusted. We debounce the load call
+ // so that only the last message is read (the current set of filters).
+ runActionDebounced(id, action, data);
+ } else {
+ runAction(id, action, data);
+ }
+};
diff --git a/chromium/tools/binary_size/libsupersize/string_extract.py b/chromium/tools/binary_size/libsupersize/string_extract.py
new file mode 100644
index 00000000000..216052f0eb4
--- /dev/null
+++ b/chromium/tools/binary_size/libsupersize/string_extract.py
@@ -0,0 +1,249 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utilities to extract string literals from object files.
+
+LookupElfRodataInfo():
+ Runs readelf to extract and return .rodata section spec of an ELF file.
+
+ReadFileChunks():
+ Reads raw data from a file, given a list of ranges in the file.
+
+ResolveStringPieces():
+ BulkForkAndCall() target: Given {path: [string addresses]} and
+ [raw_string_data for each string_section]:
+ - Reads {path: [src_strings]}.
+ - For each path, searches for src_strings in at most 1 raw_string_data over
+ each string_section. If found, translates to string_range and annotates it
+ to the string_section.
+ - Returns [{path: [string_ranges]} for each string_section].
+"""
+
+import collections
+import itertools
+import logging
+import os
+import subprocess
+
+import ar
+import concurrent
+import models
+import path_util
+
+
+def LookupElfRodataInfo(elf_path, tool_prefix):
+ """Returns (address, offset, size) for the .rodata section."""
+ args = [path_util.GetReadElfPath(tool_prefix), '-S', '--wide', elf_path]
+ output = subprocess.check_output(args)
+ lines = output.splitlines()
+ for line in lines:
+ # [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ # [07] .rodata PROGBITS 025e7000 237c000 5ec4f6 00 A 0 0 256
+ if '.rodata ' in line:
+ fields = line[line.index(models.SECTION_RODATA):].split()
+ return int(fields[2], 16), int(fields[3], 16), int(fields[4], 16)
+ raise AssertionError('No .rodata for command: ' + repr(args))
+
+
+def ReadFileChunks(path, positions):
+ """Returns a list of strings corresponding to |positions|.
+
+ Args:
+ positions: List of (offset, size).
+ """
+ ret = []
+ if not positions:
+ return ret
+ with open(path, 'rb') as f:
+ for offset, size in positions:
+ f.seek(offset)
+ ret.append(f.read(size))
+ return ret
+
+
+def _ExtractArchivePath(path):
+ # E.g. foo/bar.a(baz.o)
+ if path.endswith(')'):
+ start_idx = path.index('(')
+ return path[:start_idx]
+ return None
+
+
+def _LookupStringSectionPositions(target, tool_prefix, output_directory):
+ """Returns a dict of object_path -> [(offset, size)...] of .rodata sections.
+
+ Args:
+ target: An archive path string (e.g., "foo.a") or a list of object paths.
+ """
+ is_archive = isinstance(target, basestring)
+ args = [path_util.GetReadElfPath(tool_prefix), '-S', '--wide']
+ if is_archive:
+ args.append(target)
+ else:
+ # Assign path for when len(target) == 1, (no File: line exists).
+ path = target[0]
+ args.extend(target)
+
+ output = subprocess.check_output(args, cwd=output_directory)
+ lines = output.splitlines()
+ section_positions_by_path = {}
+ cur_offsets = []
+ for line in lines:
+ # File: base/third_party/libevent/libevent.a(buffer.o)
+ # [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
+ # [11] .rodata.str1.1 PROGBITS 00000000 0000b4 000004 01 AMS 0 0 1
+ # [11] .rodata.str4.4 PROGBITS 00000000 0000b4 000004 01 AMS 0 0 4
+ # [11] .rodata.str8.8 PROGBITS 00000000 0000b4 000004 01 AMS 0 0 8
+ # [80] .rodata..L.str PROGBITS 00000000 000530 000002 00 A 0 0 1
+ # The various string sections differ by alignment.
+ # The presence of a wchar_t literal (L"asdf") seems to make a str4 section.
+ # When multiple sections exist, nm gives us no indication as to which
+ # section each string corresponds to.
+ if line.startswith('File: '):
+ if cur_offsets:
+ section_positions_by_path[path] = cur_offsets
+ cur_offsets = []
+ path = line[6:]
+ elif '.rodata.' in line:
+ progbits_idx = line.find('PROGBITS ')
+ if progbits_idx != -1:
+ fields = line[progbits_idx:].split()
+ position = (int(fields[2], 16), int(fields[3], 16))
+ # The heuristics in _IterStringLiterals rely on str1 coming first.
+ if fields[-1] == '1':
+ cur_offsets.insert(0, position)
+ else:
+ cur_offsets.append(position)
+ if cur_offsets:
+ section_positions_by_path[path] = cur_offsets
+ return section_positions_by_path
+
+
+def _ReadStringSections(target, output_directory, positions_by_path):
+ """Returns a dict of object_path -> [string...] of .rodata chunks.
+
+ Args:
+ target: An archive path string (e.g., "foo.a") or a list of object paths.
+ positions_by_path: A dict of object_path -> [(offset, size)...]
+ """
+ is_archive = isinstance(target, basestring)
+ string_sections_by_path = {}
+ if is_archive:
+ for subpath, chunk in ar.IterArchiveChunks(
+ os.path.join(output_directory, target)):
+ path = '{}({})'.format(target, subpath)
+ positions = positions_by_path.get(path)
+ # No positions if file has no string literals.
+ if positions:
+ string_sections_by_path[path] = (
+ [chunk[offset:offset + size] for offset, size in positions])
+ else:
+ for path in target:
+ positions = positions_by_path.get(path)
+ # We already log a warning about this in _IterStringLiterals().
+ if positions:
+ string_sections_by_path[path] = ReadFileChunks(
+ os.path.join(output_directory, path), positions)
+ return string_sections_by_path
+
+
+def _IterStringLiterals(path, addresses, obj_sections):
+ """Yields all string literals (including \0) for the given object path.
+
+ Args:
+ path: Object file path.
+ addresses: List of string offsets encoded as hex strings.
+ obj_sections: List of contents of .rodata.str sections read from the given
+ object file.
+ """
+
+ next_offsets = sorted(int(a, 16) for a in addresses)
+ if not obj_sections:
+ # Happens when there is an address for a symbol which is not actually a
+ # string literal, or when string_sections_by_path is missing an entry.
+ logging.warning('Object has %d strings but no string sections: %s',
+ len(addresses), path)
+ return
+ for section_data in obj_sections:
+ cur_offsets = next_offsets
+ # Always assume first element is 0. I'm not entirely sure why this is
+ # necessary, but strings get missed without it.
+ next_offsets = [0]
+ prev_offset = 0
+ # TODO(agrieve): Switch to using nm --print-size in order to capture the
+ # address+size of each string rather than just the address.
+ for offset in cur_offsets[1:]:
+ if offset >= len(section_data):
+ # Remaining offsets are for next section.
+ next_offsets.append(offset)
+ continue
+ # Figure out which offsets apply to this section via heuristic of them
+ # all ending with a null character.
+ if offset == prev_offset or section_data[offset - 1] != '\0':
+ next_offsets.append(offset)
+ continue
+ yield section_data[prev_offset:offset]
+ prev_offset = offset
+
+ if prev_offset < len(section_data):
+ yield section_data[prev_offset:]
+
+
+# This is a target for BulkForkAndCall().
+def ResolveStringPieces(encoded_string_addresses_by_path, string_data,
+ tool_prefix, output_directory):
+ string_addresses_by_path = concurrent.DecodeDictOfLists(
+ encoded_string_addresses_by_path)
+ # Assign |target| as archive path, or a list of object paths.
+ any_path = next(string_addresses_by_path.iterkeys())
+ target = _ExtractArchivePath(any_path)
+ if not target:
+ target = string_addresses_by_path.keys()
+
+ # Run readelf to find location of .rodata within the .o files.
+ section_positions_by_path = _LookupStringSectionPositions(
+ target, tool_prefix, output_directory)
+ # Load the .rodata sections (from object files) as strings.
+ string_sections_by_path = _ReadStringSections(
+ target, output_directory, section_positions_by_path)
+
+ # list of elf_positions_by_path.
+ ret = [collections.defaultdict(list) for _ in string_data]
+ # Brute-force search of strings within ** merge strings sections.
+ # This is by far the slowest part of AnalyzeStringLiterals().
+ # TODO(agrieve): Pre-process string_data into a dict of literal->address (at
+ # least for ascii strings).
+ for path, object_addresses in string_addresses_by_path.iteritems():
+ for value in _IterStringLiterals(
+ path, object_addresses, string_sections_by_path.get(path)):
+ first_match = -1
+ first_match_dict = None
+ for target_dict, data in itertools.izip(ret, string_data):
+ # Set offset so that it will be 0 when len(value) is added to it below.
+ offset = -len(value)
+ while True:
+ offset = data.find(value, offset + len(value))
+ if offset == -1:
+ break
+ # Preferring exact matches (those following \0) over substring matches
+ # significantly increases accuracy (although shows that linker isn't
+ # being optimal).
+ if offset == 0 or data[offset - 1] == '\0':
+ break
+ if first_match == -1:
+ first_match = offset
+ first_match_dict = target_dict
+ if offset != -1:
+ break
+ if offset == -1:
+ # Exact match not found, so take suffix match if it exists.
+ offset = first_match
+ target_dict = first_match_dict
+ # Missing strings happen when optimization make them unused.
+ if offset != -1:
+ # Encode tuple as a string for easier mashalling.
+ target_dict[path].append(
+ str(offset) + ':' + str(len(value)))
+
+ return [concurrent.EncodeDictOfLists(x) for x in ret]
diff --git a/chromium/tools/binary_size/libsupersize/template/D3SymbolTreeMap.js b/chromium/tools/binary_size/libsupersize/template/D3SymbolTreeMap.js
deleted file mode 100644
index 3f001bb999d..00000000000
--- a/chromium/tools/binary_size/libsupersize/template/D3SymbolTreeMap.js
+++ /dev/null
@@ -1,930 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO:
-// 1. Visibility functions: base on boxPadding.t, not 15
-// 2. Track a maxDisplayDepth that is user-settable:
-// maxDepth == currentRoot.depth + maxDisplayDepth
-function D3SymbolTreeMap(mapWidth, mapHeight, levelsToShow) {
- this._mapContainer = undefined;
- this._mapWidth = mapWidth;
- this._mapHeight = mapHeight;
- this.boxPadding = {'l': 5, 'r': 5, 't': 20, 'b': 5};
- this.infobox = undefined;
- this.methodCountMode = false;
- this._maskContainer = undefined;
- this._highlightContainer = undefined;
- // Transition in this order:
- // 1. Exiting items go away.
- // 2. Updated items move.
- // 3. New items enter.
- this._exitDuration=500;
- this._updateDuration=500;
- this._enterDuration=500;
- this._firstTransition=true;
- this._layout = undefined;
- this._currentRoot = undefined;
- this._currentNodes = undefined;
- this._treeData = undefined;
- this._maxLevelsToShow = levelsToShow;
- this._currentMaxDepth = this._maxLevelsToShow;
-}
-
-/**
- * Make a number pretty, with comma separators.
- */
-D3SymbolTreeMap._pretty = function(num) {
- num = Math.round(num)
- var asString = String(num);
- var result = '';
- var counter = 0;
- for (var x = asString.length - 1; x >= 0; x--) {
- counter++;
- if (counter === 4) {
- result = ',' + result;
- counter = 1;
- }
- result = asString.charAt(x) + result;
- }
- return result;
-}
-
-/**
- * Express a number in terms of KiB, MiB, GiB, etc.
- * Note that these are powers of 2, not of 10.
- */
-D3SymbolTreeMap.prototype._byteify = function(num) {
- if (this.methodCountMode) {
- return num + ' methods';
- }
- var suffix;
- if (num >= 1024) {
- if (num >= 1024 * 1024 * 1024) {
- suffix = 'GiB';
- num = num / (1024 * 1024 * 1024);
- } else if (num >= 1024 * 1024) {
- suffix = 'MiB';
- num = num / (1024 * 1024);
- } else if (num >= 1024) {
- suffix = 'KiB'
- num = num / 1024;
- }
- return num.toFixed(2) + ' ' + suffix;
- }
- return num + ' B';
-}
-
-D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS = {
- 'b': '.bss',
- 'd': '.data and .data.*',
- 'r': '.rodata',
- 't': '.text',
- 'v': 'Vtable Entry',
- '!': 'Generated Symbols (typeinfo, thunks, etc)',
- 'x': 'Dex Non-Method Entries',
- 'm': 'Dex Methods',
- 'p': 'Locale Pak Entries',
- 'P': 'Non-Locale Pak Entries',
- 'o': 'Other Entries',
-};
-D3SymbolTreeMap._NM_SYMBOL_TYPES = '';
-for (var symbol_type in D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS) {
- D3SymbolTreeMap._NM_SYMBOL_TYPES += symbol_type;
-}
-
-/**
- * Given a symbol type code, look up and return a human-readable description
- * of that symbol type. If the symbol type does not match one of the known
- * types, the unrecognized description (corresponding to symbol type '?') is
- * returned instead of null or undefined.
- */
-D3SymbolTreeMap._getSymbolDescription = function(type) {
- var result = D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS[type];
- if (result === undefined) {
- result = D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS['?'];
- }
- return result;
-}
-
-D3SymbolTreeMap._colorArray = [
- 'rgb(190,186,218)',
- 'rgb(253,180,98)',
- 'rgb(141,211,199)',
- 'rgb(128,177,211)',
- 'rgb(255,237,111)',
- 'rgb(204,235,197)',
- 'rgb(255,151,151)',
- 'rgb(255,95,95)',
- 'rgb(93,156,110)',
- 'rgb(61,109,55)',
- 'rgb(150,100,111)',
-]
-
-D3SymbolTreeMap._initColorMap = function() {
- var map = {};
- var numColors = D3SymbolTreeMap._colorArray.length;
- var count = 0;
- for (var key in D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS) {
- var index = count++ % numColors;
- map[key] = d3.rgb(D3SymbolTreeMap._colorArray[index]);
- }
- D3SymbolTreeMap._colorMap = map;
-}
-D3SymbolTreeMap._initColorMap();
-
-D3SymbolTreeMap.getColorForType = function(type) {
- var result = D3SymbolTreeMap._colorMap[type];
- if (result === undefined) return d3.rgb('rgb(255,255,255)');
- return result;
-}
-
-D3SymbolTreeMap.prototype.init = function() {
- this.infobox = this._createInfoBox();
- this._mapContainer = d3.select('body').append('div')
- .style('position', 'relative')
- .style('width', this._mapWidth)
- .style('height', this._mapHeight)
- .style('padding', 0)
- .style('margin', 0)
- .style('box-shadow', '5px 5px 5px #888');
- this._layout = this._createTreeMapLayout();
- this.methodCountMode = tree_data['methodCountMode'];
- this._setData(tree_data); // TODO: Don't use global 'tree_data'
-}
-
-/**
- * Sets the data displayed by the treemap and layint out the map.
- */
-D3SymbolTreeMap.prototype._setData = function(data) {
- this._treeData = data;
- console.time('_crunchStats');
- this._crunchStats(data);
- console.timeEnd('_crunchStats');
- this._currentRoot = this._treeData;
- this._currentNodes = this._layout.nodes(this._currentRoot);
- this._currentMaxDepth = this._maxLevelsToShow;
- this._doLayout();
-}
-
-/**
- * Recursively traverses the entire tree starting from the specified node,
- * computing statistics and recording metadata as it goes. Call this method
- * only once per imported tree.
- */
-D3SymbolTreeMap.prototype._crunchStats = function(node) {
- var stack = [];
- stack.idCounter = 0;
- this._crunchStatsHelper(stack, node);
-}
-
-/**
- * Invoke the specified visitor function on all data elements currently shown
- * in the treemap including any and all of their children, starting at the
- * currently-displayed root and descening recursively. The function will be
- * passed the datum element representing each node. No traversal guarantees
- * are made.
- */
-D3SymbolTreeMap.prototype.visitFromDisplayedRoot = function(visitor) {
- this._visit(this._currentRoot, visitor);
-}
-
-/**
- * Helper function for visit functions.
- */
-D3SymbolTreeMap.prototype._visit = function(datum, visitor) {
- visitor.call(this, datum);
- if (datum.children) for (var i = 0; i < datum.children.length; i++) {
- this._visit(datum.children[i], visitor);
- }
-}
-
-D3SymbolTreeMap.prototype._crunchStatsHelper = function(stack, node) {
- // Only overwrite the node ID if it isn't already set.
- // This allows stats to be crunched multiple times on subsets of data
- // without breaking the data-to-ID bindings. New nodes get new IDs.
- if (node.id === undefined) node.id = stack.idCounter++;
- if (node.children === undefined) {
- // Leaf node (symbol); accumulate stats.
- for (var i = 0; i < stack.length; i++) {
- var ancestor = stack[i];
- if (!ancestor.symbol_stats) ancestor.symbol_stats = {};
- if (ancestor.symbol_stats[node.t] === undefined) {
- // New symbol type we haven't seen before, just record.
- ancestor.symbol_stats[node.t] = {'count': 1,
- 'size': node.value};
- } else {
- // Existing symbol type, increment.
- ancestor.symbol_stats[node.t].count++;
- ancestor.symbol_stats[node.t].size += node.value;
- }
- }
- } else for (var i = 0; i < node.children.length; i++) {
- stack.push(node);
- this._crunchStatsHelper(stack, node.children[i]);
- stack.pop();
- }
-}
-
-D3SymbolTreeMap.prototype._createTreeMapLayout = function() {
- var result = d3.layout.treemap()
- .padding([this.boxPadding.t, this.boxPadding.r,
- this.boxPadding.b, this.boxPadding.l])
- .size([this._mapWidth, this._mapHeight]);
- return result;
-}
-
-D3SymbolTreeMap.prototype.resize = function(width, height) {
- this._mapWidth = width;
- this._mapHeight = height;
- this._mapContainer.style('width', width).style('height', height);
- this._layout.size([this._mapWidth, this._mapHeight]);
- this._currentNodes = this._layout.nodes(this._currentRoot);
- this._doLayout();
-}
-
-D3SymbolTreeMap.prototype._zoomDatum = function(datum) {
- if (this._currentRoot === datum) return; // already here
- this._hideHighlight(datum);
- this._hideInfoBox(datum);
- this._currentRoot = datum;
- this._currentNodes = this._layout.nodes(this._currentRoot);
- this._currentMaxDepth = this._currentRoot.depth + this._maxLevelsToShow;
- console.log('zooming into datum ' + this._currentRoot.n);
- this._doLayout();
-}
-
-D3SymbolTreeMap.prototype.setMaxLevels = function(levelsToShow) {
- this._maxLevelsToShow = levelsToShow;
- this._currentNodes = this._layout.nodes(this._currentRoot);
- this._currentMaxDepth = this._currentRoot.depth + this._maxLevelsToShow;
- console.log('setting max levels to show: ' + this._maxLevelsToShow);
- this._doLayout();
-}
-
-/**
- * Clone the specified tree, returning an independent copy of the data.
- * Only the original attributes expected to exist prior to invoking
- * _crunchStatsHelper are retained, with the exception of the 'id' attribute
- * (which must be retained for proper transitions).
- * If the optional filter parameter is provided, it will be called with 'this'
- * set to this treemap instance and passed the 'datum' object as an argument.
- * When specified, the copy will retain only the data for which the filter
- * function returns true.
- */
-D3SymbolTreeMap.prototype._clone = function(datum, filter) {
- var trackingStats = false;
- if (this.__cloneState === undefined) {
- console.time('_clone');
- trackingStats = true;
- this.__cloneState = {'accepted': 0, 'rejected': 0,
- 'forced': 0, 'pruned': 0};
- }
-
- // Must go depth-first. All parents of children that are accepted by the
- // filter must be preserved!
- var copy = {'n': datum.n, 'k': datum.k};
- var childAccepted = false;
- if (datum.children !== undefined) {
- for (var i = 0; i < datum.children.length; i++) {
- var copiedChild = this._clone(datum.children[i], filter);
- if (copiedChild !== undefined) {
- childAccepted = true; // parent must also be accepted.
- if (copy.children === undefined) copy.children = [];
- copy.children.push(copiedChild);
- }
- }
- }
-
- // Ignore nodes that don't match the filter, when present.
- var accept = false;
- if (childAccepted) {
- // Parent of an accepted child must also be accepted.
- this.__cloneState.forced++;
- accept = true;
- } else if (filter !== undefined && filter.call(this, datum) !== true) {
- this.__cloneState.rejected++;
- } else if (datum.children === undefined) {
- // Accept leaf nodes that passed the filter
- this.__cloneState.accepted++;
- accept = true;
- } else {
- // Non-leaf node. If no children are accepted, prune it.
- this.__cloneState.pruned++;
- }
-
- if (accept) {
- if (datum.id !== undefined) copy.id = datum.id;
- if (datum.lastPathElement !== undefined) {
- copy.lastPathElement = datum.lastPathElement;
- }
- if (datum.t !== undefined) copy.t = datum.t;
- if (datum.value !== undefined && datum.children === undefined) {
- copy.value = datum.value;
- }
- } else {
- // Discard the copy we were going to return
- copy = undefined;
- }
-
- if (trackingStats === true) {
- // We are the fist call in the recursive chain.
- console.timeEnd('_clone');
- var totalAccepted = this.__cloneState.accepted +
- this.__cloneState.forced;
- console.log(
- totalAccepted + ' nodes retained (' +
- this.__cloneState.forced + ' forced by accepted children, ' +
- this.__cloneState.accepted + ' accepted on their own merits), ' +
- this.__cloneState.rejected + ' nodes (and their children) ' +
- 'filtered out,' +
- this.__cloneState.pruned + ' nodes pruned because because no ' +
- 'children remained.');
- delete this.__cloneState;
- }
- return copy;
-}
-
-D3SymbolTreeMap.prototype.filter = function(filter) {
- // Ensure we have a copy of the original root.
- if (this._backupTree === undefined) this._backupTree = this._treeData;
- this._mapContainer.selectAll('div').remove();
- this._setData(this._clone(this._backupTree, filter));
-}
-
-D3SymbolTreeMap.prototype._doLayout = function() {
- console.time('_doLayout');
- this._handleInodes();
- this._handleLeaves();
- this._firstTransition = false;
- console.timeEnd('_doLayout');
-}
-
-D3SymbolTreeMap.prototype._highlightElement = function(datum, selection) {
- this._showHighlight(datum, selection);
-}
-
-D3SymbolTreeMap.prototype._unhighlightElement = function(datum, selection) {
- this._hideHighlight(datum, selection);
-}
-
-D3SymbolTreeMap.prototype._handleInodes = function() {
- console.time('_handleInodes');
- var thisTreeMap = this;
- var inodes = this._currentNodes.filter(function(datum){
- return (datum.depth <= thisTreeMap._currentMaxDepth) &&
- datum.children !== undefined;
- });
- var cellsEnter = this._mapContainer.selectAll('div.inode')
- .data(inodes, function(datum) { return datum.id; })
- .enter()
- .append('div').attr('class', 'inode').attr('id', function(datum){
- return 'node-' + datum.id;});
-
-
- // Define enter/update/exit for inodes
- cellsEnter
- .append('div')
- .attr('class', 'rect inode_rect_entering')
- .style('z-index', function(datum) { return datum.id * 2; })
- .style('position', 'absolute')
- .style('left', function(datum) { return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum){ return datum.dx; })
- .style('height', function(datum){ return datum.dy; })
- .style('opacity', '0')
- .style('border', '1px solid black')
- .style('background-image', function(datum) {
- return thisTreeMap._makeSymbolBucketBackgroundImage.call(
- thisTreeMap, datum);
- })
- .style('background-color', function(datum) {
- if (datum.t === undefined) return 'rgb(220,220,220)';
- return D3SymbolTreeMap.getColorForType(datum.t).toString();
- })
- .on('mouseover', function(datum){
- thisTreeMap._highlightElement.call(
- thisTreeMap, datum, d3.select(this));
- thisTreeMap._showInfoBox.call(thisTreeMap, datum);
- })
- .on('mouseout', function(datum){
- thisTreeMap._unhighlightElement.call(
- thisTreeMap, datum, d3.select(this));
- thisTreeMap._hideInfoBox.call(thisTreeMap, datum);
- })
- .on('mousemove', function(){
- thisTreeMap._moveInfoBox.call(thisTreeMap, event);
- })
- .on('dblclick', function(datum){
- if (datum !== thisTreeMap._currentRoot) {
- // Zoom into the selection
- thisTreeMap._zoomDatum(datum);
- } else if (datum.parent) {
- console.log('event.shiftKey=' + event.shiftKey);
- if (event.shiftKey === true) {
- // Back to root
- thisTreeMap._zoomDatum(thisTreeMap._treeData);
- } else {
- // Zoom out of the selection
- thisTreeMap._zoomDatum(datum.parent);
- }
- }
- });
- cellsEnter
- .append('div')
- .attr('class', 'label inode_label_entering')
- .style('z-index', function(datum) { return (datum.id * 2) + 1; })
- .style('position', 'absolute')
- .style('left', function(datum){ return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum) { return datum.dx; })
- .style('height', function(datum) { return thisTreeMap.boxPadding.t; })
- .style('opacity', '0')
- .style('pointer-events', 'none')
- .style('-webkit-user-select', 'none')
- .style('overflow', 'hidden') // required for ellipsis
- .style('white-space', 'nowrap') // required for ellipsis
- .style('text-overflow', 'ellipsis')
- .style('text-align', 'center')
- .style('vertical-align', 'top')
- .style('visibility', function(datum) {
- return (datum.dx < 15 || datum.dy < 15) ? 'hidden' : 'visible';
- })
- .text(function(datum) {
- var sizeish = ' [' + thisTreeMap._byteify(datum.value) + ']'
- var text;
- if (datum.k === 'b') { // bucket
- if (datum === thisTreeMap._currentRoot) {
- text = thisTreeMap.pathFor(datum) + ': '
- + D3SymbolTreeMap._getSymbolDescription(datum.t)
- } else {
- text = D3SymbolTreeMap._getSymbolDescription(datum.t);
- }
- } else if (datum === thisTreeMap._currentRoot) {
- // The top-most level should always show the complete path
- text = thisTreeMap.pathFor(datum);
- } else {
- // Anything that isn't a bucket or a leaf (symbol) or the
- // current root should just show its name.
- text = datum.n;
- }
- return text + sizeish;
- }
- );
-
- // Complicated transition logic:
- // For nodes that are entering, we want to fade them in in-place AFTER
- // any adjusting nodes have resized and moved around. That way, new nodes
- // seamlessly appear in the right spot after their containers have resized
- // and moved around.
- // To do this we do some trickery:
- // 1. Define a '_entering' class on the entering elements
- // 2. Use this to select only the entering elements and apply the opacity
- // transition.
- // 3. Use the same transition to drop the '_entering' suffix, so that they
- // will correctly update in later zoom/resize/whatever operations.
- // 4. The update transition is achieved by selecting the elements without
- // the '_entering_' suffix and applying movement and resizing transition
- // effects.
- this._mapContainer.selectAll('div.inode_rect_entering').transition()
- .duration(thisTreeMap._enterDuration).delay(
- this._firstTransition ? 0 : thisTreeMap._exitDuration +
- thisTreeMap._updateDuration)
- .attr('class', 'rect inode_rect')
- .style('opacity', '1')
- this._mapContainer.selectAll('div.inode_label_entering').transition()
- .duration(thisTreeMap._enterDuration).delay(
- this._firstTransition ? 0 : thisTreeMap._exitDuration +
- thisTreeMap._updateDuration)
- .attr('class', 'label inode_label')
- .style('opacity', '1')
- this._mapContainer.selectAll('div.inode_rect').transition()
- .duration(thisTreeMap._updateDuration).delay(thisTreeMap._exitDuration)
- .style('opacity', '1')
- .style('background-image', function(datum) {
- return thisTreeMap._makeSymbolBucketBackgroundImage.call(
- thisTreeMap, datum);
- })
- .style('left', function(datum) { return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum){ return datum.dx; })
- .style('height', function(datum){ return datum.dy; });
- this._mapContainer.selectAll('div.inode_label').transition()
- .duration(thisTreeMap._updateDuration).delay(thisTreeMap._exitDuration)
- .style('opacity', '1')
- .style('visibility', function(datum) {
- return (datum.dx < 15 || datum.dy < 15) ? 'hidden' : 'visible';
- })
- .style('left', function(datum){ return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum) { return datum.dx; })
- .style('height', function(datum) { return thisTreeMap.boxPadding.t; })
- .text(function(datum) {
- var sizeish = ' [' + thisTreeMap._byteify(datum.value) + ']'
- var text;
- if (datum.k === 'b') {
- if (datum === thisTreeMap._currentRoot) {
- text = thisTreeMap.pathFor(datum) + ': ' +
- D3SymbolTreeMap._getSymbolDescription(datum.t)
- } else {
- text = D3SymbolTreeMap._getSymbolDescription(datum.t);
- }
- } else if (datum === thisTreeMap._currentRoot) {
- // The top-most level should always show the complete path
- text = thisTreeMap.pathFor(datum);
- } else {
- // Anything that isn't a bucket or a leaf (symbol) or the
- // current root should just show its name.
- text = datum.n;
- }
- return text + sizeish;
- });
- var exit = this._mapContainer.selectAll('div.inode')
- .data(inodes, function(datum) { return 'inode-' + datum.id; })
- .exit();
- exit.selectAll('div.inode_rect').transition().duration(
- thisTreeMap._exitDuration).style('opacity', 0);
- exit.selectAll('div.inode_label').transition().duration(
- thisTreeMap._exitDuration).style('opacity', 0);
- exit.transition().delay(thisTreeMap._exitDuration + 1).remove();
-
- console.log(inodes.length + ' inodes layed out.');
- console.timeEnd('_handleInodes');
-}
-
-D3SymbolTreeMap.prototype._handleLeaves = function() {
- console.time('_handleLeaves');
- var color_fn = d3.scale.category10();
- var thisTreeMap = this;
- var leaves = this._currentNodes.filter(function(datum){
- return (datum.depth <= thisTreeMap._currentMaxDepth) &&
- datum.children === undefined; });
- var cellsEnter = this._mapContainer.selectAll('div.leaf')
- .data(leaves, function(datum) { return datum.id; })
- .enter()
- .append('div').attr('class', 'leaf').attr('id', function(datum){
- return 'node-' + datum.id;
- });
-
- // Define enter/update/exit for leaves
- cellsEnter
- .append('div')
- .attr('class', 'rect leaf_rect_entering')
- .style('z-index', function(datum) { return datum.id * 2; })
- .style('position', 'absolute')
- .style('left', function(datum){ return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum){ return datum.dx; })
- .style('height', function(datum){ return datum.dy; })
- .style('opacity', '0')
- .style('background-color', function(datum) {
- if (datum.t === undefined) return 'rgb(220,220,220)';
- return D3SymbolTreeMap.getColorForType(datum.t)
- .darker(0.3).toString();
- })
- .style('border', '1px solid black')
- .on('mouseover', function(datum){
- thisTreeMap._highlightElement.call(
- thisTreeMap, datum, d3.select(this));
- thisTreeMap._showInfoBox.call(thisTreeMap, datum);
- })
- .on('mouseout', function(datum){
- thisTreeMap._unhighlightElement.call(
- thisTreeMap, datum, d3.select(this));
- thisTreeMap._hideInfoBox.call(thisTreeMap, datum);
- })
- .on('mousemove', function(){ thisTreeMap._moveInfoBox.call(
- thisTreeMap, event);
- });
- cellsEnter
- .append('div')
- .attr('class', 'label leaf_label_entering')
- .style('z-index', function(datum) { return (datum.id * 2) + 1; })
- .style('position', 'absolute')
- .style('left', function(datum){ return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum) { return datum.dx; })
- .style('height', function(datum) { return datum.dy; })
- .style('opacity', '0')
- .style('pointer-events', 'none')
- .style('-webkit-user-select', 'none')
- .style('overflow', 'hidden') // required for ellipsis
- .style('white-space', 'nowrap') // required for ellipsis
- .style('text-overflow', 'ellipsis')
- .style('text-align', 'center')
- .style('vertical-align', 'middle')
- .style('visibility', function(datum) {
- return (datum.dx < 15 || datum.dy < 15) ? 'hidden' : 'visible';
- })
- .text(function(datum) { return datum.n; });
-
- // Complicated transition logic: See note in _handleInodes()
- this._mapContainer.selectAll('div.leaf_rect_entering').transition()
- .duration(thisTreeMap._enterDuration).delay(
- this._firstTransition ? 0 : thisTreeMap._exitDuration +
- thisTreeMap._updateDuration)
- .attr('class', 'rect leaf_rect')
- .style('opacity', '1')
- this._mapContainer.selectAll('div.leaf_label_entering').transition()
- .duration(thisTreeMap._enterDuration).delay(
- this._firstTransition ? 0 : thisTreeMap._exitDuration +
- thisTreeMap._updateDuration)
- .attr('class', 'label leaf_label')
- .style('opacity', '1')
- this._mapContainer.selectAll('div.leaf_rect').transition()
- .duration(thisTreeMap._updateDuration).delay(thisTreeMap._exitDuration)
- .style('opacity', '1')
- .style('left', function(datum){ return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum){ return datum.dx; })
- .style('height', function(datum){ return datum.dy; });
- this._mapContainer.selectAll('div.leaf_label').transition()
- .duration(thisTreeMap._updateDuration).delay(thisTreeMap._exitDuration)
- .style('opacity', '1')
- .style('visibility', function(datum) {
- return (datum.dx < 15 || datum.dy < 15) ? 'hidden' : 'visible';
- })
- .style('left', function(datum){ return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum) { return datum.dx; })
- .style('height', function(datum) { return datum.dy; });
- var exit = this._mapContainer.selectAll('div.leaf')
- .data(leaves, function(datum) { return 'leaf-' + datum.id; })
- .exit();
- exit.selectAll('div.leaf_rect').transition()
- .duration(thisTreeMap._exitDuration)
- .style('opacity', 0);
- exit.selectAll('div.leaf_label').transition()
- .duration(thisTreeMap._exitDuration)
- .style('opacity', 0);
- exit.transition().delay(thisTreeMap._exitDuration + 1).remove();
-
- console.log(leaves.length + ' leaves layed out.');
- console.timeEnd('_handleLeaves');
-}
-
-D3SymbolTreeMap.prototype._makeSymbolBucketBackgroundImage = function(datum) {
- if (!(datum.t === undefined && datum.depth == this._currentMaxDepth)) {
- return 'none';
- }
- var text = '';
- var lastStop = 0;
- for (var x = 0; x < D3SymbolTreeMap._NM_SYMBOL_TYPES.length; x++) {
- symbol_type = D3SymbolTreeMap._NM_SYMBOL_TYPES.charAt(x);
- var stats = datum.symbol_stats[symbol_type];
- if (stats !== undefined) {
- if (text.length !== 0) {
- text += ', ';
- }
- var percent = 100 * (stats.size / datum.value);
- var nowStop = lastStop + percent;
- var tempcolor = D3SymbolTreeMap.getColorForType(symbol_type);
- var color = d3.rgb(tempcolor).toString();
- text += color + ' ' + lastStop + '%, ' + color + ' ' +
- nowStop + '%';
- lastStop = nowStop;
- }
- }
- return 'linear-gradient(' + (datum.dx > datum.dy ? 'to right' :
- 'to bottom') + ', ' + text + ')';
-}
-
-D3SymbolTreeMap.prototype.pathFor = function(datum) {
- if (datum.__path) return datum.__path;
- parts=[];
- node = datum;
- while (node) {
- if (node.k === 'p') { // path node
- if(node.n !== '/') parts.unshift(node.n);
- }
- node = node.parent;
- }
- datum.__path = '/' + parts.join('/');
- return datum.__path;
-}
-
-D3SymbolTreeMap.prototype._createHighlight = function(datum, selection) {
- var x = parseInt(selection.style('left'));
- var y = parseInt(selection.style('top'));
- var w = parseInt(selection.style('width'));
- var h = parseInt(selection.style('height'));
- datum.highlight = this._mapContainer.append('div')
- .attr('id', 'h-' + datum.id)
- .attr('class', 'highlight')
- .style('pointer-events', 'none')
- .style('-webkit-user-select', 'none')
- .style('z-index', '999999')
- .style('position', 'absolute')
- .style('top', y-2)
- .style('left', x-2)
- .style('width', w+4)
- .style('height', h+4)
- .style('margin', 0)
- .style('padding', 0)
- .style('border', '4px outset rgba(250,40,200,0.9)')
- .style('box-sizing', 'border-box')
- .style('opacity', 0.0);
-}
-
-D3SymbolTreeMap.prototype._showHighlight = function(datum, selection) {
- if (datum === this._currentRoot) return;
- if (datum.highlight === undefined) {
- this._createHighlight(datum, selection);
- }
- datum.highlight.transition().duration(200).style('opacity', 1.0);
-}
-
-D3SymbolTreeMap.prototype._hideHighlight = function(datum, selection) {
- if (datum.highlight === undefined) return;
- datum.highlight.transition().duration(750)
- .style('opacity', 0)
- .each('end', function(){
- if (datum.highlight) datum.highlight.remove();
- delete datum.highlight;
- });
-}
-
-D3SymbolTreeMap.prototype._createInfoBox = function() {
- return d3.select('body')
- .append('div')
- .attr('id', 'infobox')
- .style('z-index', '2147483647') // (2^31) - 1: Hopefully safe :)
- .style('position', 'absolute')
- .style('visibility', 'hidden')
- .style('background-color', 'rgba(255,255,255, 0.9)')
- .style('border', '1px solid black')
- .style('padding', '10px')
- .style('-webkit-user-select', 'none')
- .style('box-shadow', '3px 3px rgba(70,70,70,0.5)')
- .style('border-radius', '10px')
- .style('white-space', 'nowrap');
-}
-
-D3SymbolTreeMap.prototype._showInfoBox = function(datum) {
- this.infobox.text('');
- var numSymbols = 0;
- var sizeish = this._byteify(datum.value);
- if (!this.methodCountMode) {
- sizeish = D3SymbolTreeMap._pretty(datum.value) + ' bytes (' + sizeish + ')'
- }
- if (datum.k === 'p' || datum.k === 'b') { // path or bucket
- if (datum.symbol_stats) { // can be empty if filters are applied
- for (var x = 0; x < D3SymbolTreeMap._NM_SYMBOL_TYPES.length; x++) {
- symbol_type = D3SymbolTreeMap._NM_SYMBOL_TYPES.charAt(x);
- var stats = datum.symbol_stats[symbol_type];
- if (stats !== undefined) numSymbols += stats.count;
- }
- }
- } else if (datum.k === 's') { // symbol
- numSymbols = 1;
- }
-
- if (datum.k === 'p' && !datum.lastPathElement) {
- this.infobox.append('div').text('Directory: ' + this.pathFor(datum))
- this.infobox.append('div').text('Size: ' + sizeish);
- } else {
- if (datum.k === 'p') { // path
- this.infobox.append('div').text('File: ' + this.pathFor(datum))
- this.infobox.append('div').text('Size: ' + sizeish);
- } else if (datum.k === 'b') { // bucket
- this.infobox.append('div').text('Symbol Bucket: ' +
- D3SymbolTreeMap._getSymbolDescription(datum.t));
- this.infobox.append('div').text('Count: ' + numSymbols);
- this.infobox.append('div').text('Size: ' + sizeish);
- this.infobox.append('div').text('Location: ' + this.pathFor(datum))
- } else if (datum.k === 's') { // symbol
- this.infobox.append('div').text('Symbol: ' + datum.n);
- this.infobox.append('div').text('Type: ' +
- D3SymbolTreeMap._getSymbolDescription(datum.t));
- this.infobox.append('div').text('Size: ' + sizeish);
- this.infobox.append('div').text('Location: ' + this.pathFor(datum))
- }
- }
- if (datum.k === 'p' && !this.methodCountMode) {
- this.infobox.append('div')
- .text('Number of symbols: ' + D3SymbolTreeMap._pretty(numSymbols));
- // can be empty if filters are applied
- if (datum.symbol_stats) {
- var table = this.infobox.append('table')
- .attr('border', 1).append('tbody');
- var header = table.append('tr');
- header.append('th').text('Type');
- header.append('th').text('Count');
- header.append('th')
- .style('white-space', 'nowrap')
- .text('Total Size (Bytes)');
- for (var x = 0; x < D3SymbolTreeMap._NM_SYMBOL_TYPES.length; x++) {
- symbol_type = D3SymbolTreeMap._NM_SYMBOL_TYPES.charAt(x);
- var stats = datum.symbol_stats[symbol_type];
- if (stats !== undefined) {
- var tr = table.append('tr');
- tr.append('td')
- .style('white-space', 'nowrap')
- .text(D3SymbolTreeMap._getSymbolDescription(
- symbol_type));
- tr.append('td').text(D3SymbolTreeMap._pretty(stats.count));
- tr.append('td').text(D3SymbolTreeMap._pretty(stats.size));
- }
- }
- }
- }
- this.infobox.style('visibility', 'visible');
-}
-
-D3SymbolTreeMap.prototype._hideInfoBox = function(datum) {
- this.infobox.style('visibility', 'hidden');
-}
-
-D3SymbolTreeMap.prototype._moveInfoBox = function(event) {
- var element = document.getElementById('infobox');
- var w = element.offsetWidth;
- var h = element.offsetHeight;
- var offsetLeft = 10;
- var offsetTop = 10;
-
- var rightLimit = window.innerWidth;
- var rightEdge = event.pageX + offsetLeft + w;
- if (rightEdge > rightLimit) {
- // Too close to screen edge, reflect around the cursor
- offsetLeft = -1 * (w + offsetLeft);
- }
-
- var bottomLimit = window.innerHeight;
- var bottomEdge = event.pageY + offsetTop + h;
- if (bottomEdge > bottomLimit) {
- // Too close ot screen edge, reflect around the cursor
- offsetTop = -1 * (h + offsetTop);
- }
-
- this.infobox.style('top', (event.pageY + offsetTop) + 'px')
- .style('left', (event.pageX + offsetLeft) + 'px');
-}
-
-D3SymbolTreeMap.prototype.biggestSymbols = function(maxRecords) {
- var result = undefined;
- var smallest = undefined;
- var sortFunction = function(a,b) {
- var result = b.value - a.value;
- if (result !== 0) return result; // sort by size
- var pathA = treemap.pathFor(a); // sort by path
- var pathB = treemap.pathFor(b);
- if (pathA > pathB) return 1;
- if (pathB > pathA) return -1;
- return a.n - b.n; // sort by symbol name
- };
- this.visitFromDisplayedRoot(function(datum) {
- if (datum.children) return; // ignore non-leaves
- if (!result) { // first element
- result = [datum];
- smallest = datum.value;
- return;
- }
- if (result.length < maxRecords) { // filling the array
- result.push(datum);
- return;
- }
- if (datum.value > smallest) { // array is already full
- result.push(datum);
- result.sort(sortFunction);
- result.pop(); // get rid of smallest element
- smallest = result[maxRecords - 1].value; // new threshold for entry
- }
- });
- result.sort(sortFunction);
- return result;
-}
-
-D3SymbolTreeMap.prototype.biggestPaths = function(maxRecords) {
- var result = undefined;
- var smallest = undefined;
- var sortFunction = function(a,b) {
- var result = b.value - a.value;
- if (result !== 0) return result; // sort by size
- var pathA = treemap.pathFor(a); // sort by path
- var pathB = treemap.pathFor(b);
- if (pathA > pathB) return 1;
- if (pathB > pathA) return -1;
- console.log('warning, multiple entries for the same path: ' + pathA);
- return 0; // should be impossible
- };
- this.visitFromDisplayedRoot(function(datum) {
- if (!datum.lastPathElement) return; // ignore non-files
- if (!result) { // first element
- result = [datum];
- smallest = datum.value;
- return;
- }
- if (result.length < maxRecords) { // filling the array
- result.push(datum);
- return;
- }
- if (datum.value > smallest) { // array is already full
- result.push(datum);
- result.sort(sortFunction);
- result.pop(); // get rid of smallest element
- smallest = result[maxRecords - 1].value; // new threshold for entry
- }
- });
- result.sort(sortFunction);
- return result;
-}
diff --git a/chromium/tools/binary_size/libsupersize/template/index.html b/chromium/tools/binary_size/libsupersize/template/index.html
deleted file mode 100644
index 88df14d85af..00000000000
--- a/chromium/tools/binary_size/libsupersize/template/index.html
+++ /dev/null
@@ -1,517 +0,0 @@
-<!--
- Copyright 2014 The Chromium Authors. All rights reserved.
- Use of this source code is governed by a BSD-style license that can be
- found in the LICENSE file.
--->
-<html>
-<head>
-<title>Binary Size Analysis</title>
-<script src="d3/d3.js" charset="utf-8"></script>
-<script src="D3SymbolTreeMap.js" charset="utf-8"></script>
-<script src="data.js" charset="utf-8"></script>
-<style>
-body {
- margin: 0px;
- padding: 5px;
-}
-.swatch {
- border: 1px solid rgb(100,100,100);
- -webkit-user-select: none;
- cursor: default;
-}
-</style>
-<script>
-var treemap;
-var filterChanging = false;
-var savedSettings = {};
-var NUM_SYMBOL_TYPES = 11;
-
-function init() {
- if (window.metadata !== undefined && window.metadata.subtitle) {
- document.getElementById('subtitle').innerHTML = ': ' + escape(metadata.subtitle);
- }
- initFilterOptions();
- treemap = new D3SymbolTreeMap(
- savedSettings.width,
- savedSettings.height,
- savedSettings.maxLevels);
- treemap.init();
- applyFilter(); // Required to make .other hidden by default.
-}
-
-function getIdealSizes() {
- var width = window.innerWidth - 20;
- var height = window.innerHeight - 70;
- return {'width': width, 'height': height};
-}
-
-function showReport(title, data, headers, dataFunction, styleFunction) {
- var div = d3.select('body').append('div')
- .style('margin', '0')
- .style('padding', '5px')
- .style('position', 'absolute')
- .style('top', '10%')
- .style('left', '10%')
- .style('background-color', 'rgba(255,255,255,0.9)')
- .style('width', '80%')
- .style('height', '80%')
- .style('z-index', '2147483647')
- .style('border', '3px ridge grey')
- .style('box-shadow', '10px 10px 5px rgba(80,80,80,0.7)')
- .style('text-align', 'center')
- .style('border-radius', '10px');
- var titlebar = div.append('div')
- .style('margin', '0')
- .style('padding', '5px')
- .style('position', 'absolute')
- .style('top', '0%')
- .style('left', '0%')
- .style('width', '100%')
- .style('height', '10%')
- .style('font-size', 'x-large');
- titlebar.text(title);
- var controls = div.append('div')
- .style('margin', '0')
- .style('padding', '5px')
- .style('position', 'absolute')
- .style('top', '90%')
- .style('left', '0%')
- .style('width', '100%')
- .style('height', '10%');
- controls.append('input').attr('type', 'button')
- .attr('value', 'Dismiss')
- .on('click', function(){div.remove();});
-
- var tableDiv = div.append('div')
- .style('overflow', 'auto')
- .style('position', 'absolute')
- .style('top', '10%')
- .style('left', '0%')
- .style('width', '100%')
- .style('height', '80%')
- .style('border-top', '1px solid rgb(230,230,230)')
- .style('border-bottom', '1px solid rgb(230,230,230)');
- var table = tableDiv.append('table')
- .attr('border', '1')
- .attr('cellspacing', '0')
- .attr('cellpadding', '2')
- .style('margin-left', 'auto')
- .style('margin-right', 'auto');
- var header = table.append('tr');
- for (var i = 0; i < headers.length; i++) {
- header.append('th').text(headers[i]);
- }
-
- for (var i = 0; i < data.length; i++) {
- var row = table.append('tr');
- for (j = 0; j < headers.length; j++) {
- var td = row.append('td');
- if (styleFunction) {
- styleFunction.call(this, td, j);
- }
- dataFunction.call(this, data[i], j, td);
- }
- }
-}
-
-function bigSymbolsReport() {
- var list = treemap.biggestSymbols(100);
- var headers = ['Rank', 'Size (Bytes)', 'Type', 'Location'];
- var styleFunction = function(selection, index) {
- if (index === 3) {
- selection.style('font-family', 'monospace');
- }
- };
- var recordIndex = 1;
- var dataFunction = function(record, index, cell) {
- if (index === 0) {
- cell.text(recordIndex++);
- } else if (index === 1) {
- cell.text(D3SymbolTreeMap._pretty(record.value));
- } else if (index === 2) {
- cell.text(record.t);
- } else {
- if (treemap.pathFor(record).indexOf('/out') == 0) {
- cell.append('span').text(treemap.pathFor(record));
- cell.append('br');
- cell.append('span').text('Symbol: ');
- cell.append('span').text(record.n);
- } else {
- var href = 'https://code.google.com/p/chromium/codesearch#chromium/src'
- + treemap.pathFor(record)
- + '&q='
- + record.n;
- cell.append('a')
- .attr('href', href)
- .attr('target', '_blank')
- .text(treemap.pathFor(record));
- cell.append('br');
- cell.append('span').text('Symbol: ');
- cell.append('span').text(record.n);
- }
- }
- };
- showReport('100 Largest Symbols', list, headers, dataFunction, styleFunction);
-}
-
-function bigPathsReport() {
- var list = treemap.biggestPaths(100);
- var headers = ['Rank', 'Size (Bytes)', 'Location'];
- var styleFunction = function(selection, index) {
- if (index === 2) {
- selection.style('font-family', 'monospace');
- }
- };
- var recordIndex = 1;
- var dataFunction = function(record, index, cell) {
- if (index === 0) {
- cell.text(recordIndex++);
- } else if (index === 1) {
- cell.text(D3SymbolTreeMap._pretty(record.value));
- } else if (index === 2) {
- if (treemap.pathFor(record).indexOf('/out') == 0) {
- cell.text(treemap.pathFor(record));
- } else {
- var href = 'https://code.google.com/p/chromium/codesearch#chromium/src' + treemap.pathFor(record);
- cell.append('a')
- .attr('href', href)
- .attr('target', '_blank')
- .text(treemap.pathFor(record));
- }
-
- }
- };
- showReport('100 Largest Paths', list, headers, dataFunction, styleFunction);
-}
-
-function symbolFilterTextChanged() {
- if (filterChanging) return true;
- filterChanging = true;
- var enabled = document.getElementById('symbol_types_filter').value;
- for (var x=0; x<NUM_SYMBOL_TYPES; x++) {
- var checkBox = document.getElementById('check_' + x);
- checkBox.checked = (enabled.indexOf(checkBox.value) != -1);
- }
- filterChanging = false;
-}
-
-function updateFilterText() {
- if (filterChanging) return true;
- filterChanging = true;
- var text = '';
- for (var x=0; x<NUM_SYMBOL_TYPES; x++) {
- var checkBox = document.getElementById('check_' + x);
- if (checkBox.checked) {
- text += checkBox.value;
- }
- }
- document.getElementById('symbol_types_filter').value=text;
- filterChanging = false;
-}
-
-function initFilterOptions() {
- var filterFromUrl = new URL(window.location).searchParams.get('sections');
- if (filterFromUrl) {
- document.getElementById('symbol_types_filter').value = filterFromUrl;
- } else {
- updateFilterText();
- }
- for (var x=0; x<NUM_SYMBOL_TYPES; x++) {
- var checkBox = document.getElementById('check_' + x);
- checkBox.onchange=updateFilterText;
- var swatch = document.getElementById('swatch_' + x);
- swatch.style.backgroundColor = D3SymbolTreeMap.getColorForType(checkBox.value).toString();
- }
- var gteCheckbox = document.getElementById('check_gte');
- gteCheckbox.onchange = function() {
- document.getElementById('symbol_filter_gte').disabled = !gteCheckbox.checked;
- }
- var regexCheckbox = document.getElementById('check_regex');
- regexCheckbox.onchange = function() {
- document.getElementById('symbol_filter_regex').disabled = !regexCheckbox.checked;
- }
- var excludeRegexCheckbox = document.getElementById('check_exclude_regex');
- excludeRegexCheckbox.onchange = function() {
- document.getElementById('symbol_filter_exclude_regex').disabled = !excludeRegexCheckbox.checked;
- }
- var idealSizes = getIdealSizes();
- document.getElementById('width').value = idealSizes.width;
- document.getElementById('height').value = idealSizes.height;
- saveFilterSettings();
-}
-
-function filterSetAll(enabled) {
- for (var x=0; x<NUM_SYMBOL_TYPES; x++) {
- var checkBox = document.getElementById('check_' + x);
- checkBox.checked = enabled;
- }
- updateFilterText();
-}
-
-function showOptions() {
- loadFilterSettings();
- var container = document.getElementById('options_container');
- var w = container.offsetWidth;
- var h = container.offsetHeight;
- container.style.margin = '-' + (h/2) + 'px 0 0 -' + (w/2) + 'px';
- container.style.visibility = 'visible';
-}
-
-function hideOptions() {
- var container = document.getElementById('options_container');
- container.style.visibility = 'hidden';
-}
-
-function applyFilter() {
- // Type filters
- var typeFilter = function(datum) {
- if (datum.depth === 0) return true; // root node
- if (datum.t === undefined) return true;
- return savedSettings.symbolTypes !== undefined &&
- savedSettings.symbolTypes.indexOf(datum.t) !== -1;
- }
-
- // Regex filter
- var regexFilter;
- if (savedSettings.regex !== undefined && savedSettings.regex.length > 0) {
- console.log('filter: regex is "' + savedSettings.regex + '"');
- var regex = new RegExp(savedSettings.regex);
- regexFilter = function(datum) {
- if (datum.depth === 0) return true; // root node
- var fullName = this.pathFor(datum);
- if (datum.children === undefined) { // it is a leaf node (symbol)
- fullName += ':' + datum.n;
- }
- return regex.test(fullName);
- }
- }
-
- // Exclude regex filter
- var excludeRegexFilter = undefined;
- if (savedSettings.excludeRegex !== undefined && savedSettings.excludeRegex.length > 0) {
- console.log('filter: exclude-regex is "' + savedSettings.excludeRegex + '"');
- var excludeRegex = new RegExp(savedSettings.excludeRegex);
- excludeRegexFilter = function(datum) {
- if (datum.depth === 0) return true; // root node
- var fullName = this.pathFor(datum);
- if (datum.children === undefined) { // it is a leaf node (symbol)
- fullName += ':' + datum.n;
- }
- return !excludeRegex.test(fullName);
- }
- }
-
- // Size filter
- var sizeFilter = undefined;
- if (savedSettings.gte !== undefined) {
- console.log('filter: minimum size is ' + savedSettings.gte + ' bytes');
- sizeFilter = function(datum) {
- if (datum.children !== undefined) return true; // non-leaf
- if (datum.value === undefined) console.log('whoops');
- return datum.value >= savedSettings.gte;
- }
- }
-
- // Make a filter to apply to the tree
- var filter = function(datum) {
- if (!typeFilter.call(this, datum)) return false;
- if (regexFilter && !regexFilter.call(this, datum)) return false;
- if (excludeRegexFilter && !excludeRegexFilter.call(this, datum)) return false;
- if (sizeFilter && !sizeFilter.call(this, datum)) return false;
- return true;
- };
- treemap.filter(filter);
-}
-
-function applySettings() {
- hideOptions();
- var oldWidth = savedSettings.width;
- var oldHeight = savedSettings.height;
- var oldSymbols = savedSettings.symbolTypes;
- var oldRegex = savedSettings.regex;
- var oldExcludeRegex = savedSettings.excludeRegex;
- var oldGte = savedSettings.gte;
- var oldMaxLevels = savedSettings.maxLevels;
- saveFilterSettings();
- var resizeNeeded = oldWidth !== savedSettings.width || oldHeight !== savedSettings.height;
- var regexChanged = oldRegex !== savedSettings.regex;
- var excludeRegexChanged = oldExcludeRegex !== savedSettings.excludeRegex;
- var symbolsChanged = oldSymbols !== savedSettings.symbolTypes;
- var gteChanged = oldGte !== savedSettings.gte;
- var filterChanged = regexChanged || excludeRegexChanged || symbolsChanged || gteChanged;
- var maxLevelsChanged = oldMaxLevels !== savedSettings.maxLevels;
-
- if (filterChanged) {
- applyFilter();
- }
-
- // Adjust levels if needed.
- if (maxLevelsChanged) {
- treemap.setMaxLevels(savedSettings.maxLevels);
- }
-
- // Resize map if necessary.
- if (resizeNeeded) {
- console.log('desired treemap dimensions have changed, requesting resize');
- treemap.resize(savedSettings.width, savedSettings.height);
- }
-}
-
-function cancelSettings() {
- hideOptions();
- loadFilterSettings();
-}
-
-function saveFilterSettings() {
- savedSettings.symbolTypes = document.getElementById('symbol_types_filter').value;
- if (document.getElementById('check_regex').checked) {
- savedSettings.regex = document.getElementById('symbol_filter_regex').value;
- } else {
- savedSettings.regex = undefined;
- }
- if (document.getElementById('check_exclude_regex').checked) {
- savedSettings.excludeRegex = document.getElementById('symbol_filter_exclude_regex').value;
- } else {
- savedSettings.excludeRegex = undefined;
- }
- if (document.getElementById('check_gte').checked) {
- savedSettings.gte = parseInt(document.getElementById('symbol_filter_gte').value);
- } else {
- savedSettings.gte = undefined;
- }
- savedSettings.width = parseInt(document.getElementById('width').value);
- savedSettings.height = parseInt(document.getElementById('height').value);
- savedSettings.maxLevels = parseInt(document.getElementById('max_levels').value);
-}
-
-function loadFilterSettings() {
- document.getElementById('symbol_types_filter').value = savedSettings.symbolTypes;
- symbolFilterTextChanged();
- if (savedSettings.regex !== undefined) {
- document.getElementById('check_regex').checked = true;
- document.getElementById('symbol_filter_regex').value = savedSettings.regex;
- } else {
- document.getElementById('check_regex').checked = false;
- }
- if (savedSettings.excludeRegex !== undefined) {
- document.getElementById('check_exclude_regex').checked = true;
- document.getElementById('symbol_filter_exclude_regex').value = savedSettings.excludeRegex;
- } else {
- document.getElementById('check_exclude_regex').checked = false;
- }
- if (savedSettings.gte !== undefined) {
- document.getElementById('check_gte').checked = true;
- document.getElementById('symbol_filter_gte').value = savedSettings.gte;
- } else {
- document.getElementById('check_gte').checked = false;
- }
- document.getElementById('width').value = savedSettings.width;
- document.getElementById('height').value = savedSettings.height;
- document.getElementById('max_levels').value = savedSettings.maxLevels;
-}
-
-function escape(str) {
- return str.replace(/&/g, '&amp;')
- .replace(/"/g, '&quot;')
- .replace(/</g, '&lt;')
- .replace(/>/g, '&gt;');
-}
-</script>
-</head>
-<body onload='init()'>
-<div style='position: absolute; top: 5px; left: 5px;'>
- <input type='button' onclick='showOptions()' value='Options &amp; Legend...'>
- <span style='-webkit-user-select: none; cursor: help;' title='Click to view the symbol legend or to configure filters and options for the treemap'>[?]</span>
-</div>
-<div style='position: absolute; right: 5px; top: 5px; white-space: nowrap;'>
- Reports:
- <input type='button' onclick='bigSymbolsReport()' value='Large Symbols' title='Click to view a report of the largest 100 symbols that are with the bounds of the treemap that is currently displayed.'>
- <input type='button' onclick='bigPathsReport()' value='Large Files' title='Click to view a report of the largest 100 source files that are with the bounds of the treemap that is currently displayed.'>
-</div>
-<div style='text-align: center; margin-bottom: 5px;'>
- <span style='font-size: x-large; font-weight: bold; font-variant: small-caps'>Binary Size Analysis<span id='subtitle'></span></span>
- <br><span style='font-size: small; font-style: italic;'>Double-click a box to zoom in, double-click outermost title to zoom out.</span>
-</div>
-<table id='options_container' style='visibility: hidden; border: 3px ridge grey; padding: 0px; top: 50%; left: 50%; position: fixed; z-index: 2147483646; overflow: auto; background-color: rgba(255,255,255,0.9); border-radius: 10px; box-shadow: 10px 10px 5px rgba(80,80,80,0.7);'><tr><td style='vertical-align: top'>
- <table cellspacing=0 cellborder=0 style='width:100%'>
- <tr><th style='padding-bottom: .25em; text-decoration: underline;'>Symbol Types To Show</th></tr>
- <tr>
- <td style='white-space: nowrap; vertical-align: top;'>
- <br><span class='swatch' id='swatch_0'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_0' value='b'>Uninitialized data (.bss)
- <br><span class='swatch' id='swatch_1'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_1' value='d'>Initialized data (.data)
- <br><span class='swatch' id='swatch_2'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_2' value='r'>Read-only data (.rodata)
- <br><span class='swatch' id='swatch_3'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_3' value='t'>Code (.text)
- <br><span class='swatch' id='swatch_4'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_4' value='v'>Vtable entries
- <br><span class='swatch' id='swatch_5'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_5' value='!'>Generated Symbols (typeinfo, thunks, etc)
- <br><span class='swatch' id='swatch_6'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_6' value='x'>Dex non-method entries
- <br><span class='swatch' id='swatch_7'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_7' value='m'>Dex methods
- <br><span class='swatch' id='swatch_8'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_8' value='p'>Locale Pak Entries
- <br><span class='swatch' id='swatch_9'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_9' value='P'>Non-Locale Pak Entries
- <br><span class='swatch' id='swatch_10'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_10' value='o'>Other Entries
- </td>
- </tr>
- <tr><td style='text-align: center; white-space: nowrap; padding-top: 1em;'>
- Select <input type='button' onclick='filterSetAll(true)' value='All'>,
- <input type='button' onclick='filterSetAll(false)' value='None'>,
- or type a string: <input id='symbol_types_filter' size=30 value='' onkeyup='symbolFilterTextChanged()' onblur='updateFilterText()'>
- <span style='-webkit-user-select: none; cursor: help;' title='Enter codes from the list above for the symbols you want to see. The checkboxes will update automatically to match the string that you enter.'>[?]</span>
- </td></tr>
- </table>
-</td></tr><tr><td style='vertical-align: top; padding-top: 10px; border-top: 1px solid grey;'>
- <table cellspacing=0 cellborder=0 style='width: 100%'>
- <tr><th colspan=2 style='padding-bottom: .25em; text-decoration: underline;'>Advanced Options</th></tr>
- <tr>
- <td style='white-space: nowrap; vertical-align: top;'>
- <input type='checkbox' id='check_regex'>
- Only include symbols matching this regex:
- </td>
- <td style='text-align: right; vertical-align: top;'>
- <input disabled id='symbol_filter_regex' size=30 value='' style='text-align: right;'>
- <span style='-webkit-user-select: none; cursor: help;' title='Enter a javascript regex. Only symbols that match this regex will be shown. This filter applies before any exclusion regex specified below. The format of each symbol is [path]:[symbol_name]'>[?]</span>
- </td>
- </tr>
- <tr>
- <td style='white-space: nowrap; vertical-align: top;'>
- <input type='checkbox' id='check_exclude_regex'>
- Exclude all symbols matching this regex:
- </td>
- <td style='text-align: right; vertical-align: top;'>
- <input disabled id='symbol_filter_exclude_regex' size=30 value='' style='text-align: right;'>
- <span style='-webkit-user-select: none; cursor: help;' title='Enter a javascript regex. Symbols that match this tegex will not be shown. This filter applies after any inclusion filter specified above. The format of each symbol is [path]:[symbol_name]'>[?]</span>
- </td>
- </tr>
- <tr>
- <td style='white-space: nowrap; vertical-align: top;'>
- <input type='checkbox' id='check_gte'>
- Only include symbols that are at least <span style='font-style: italic;'>n</span> bytes:
- </td>
- <td style='text-align: right; vertical-align: top;'>
- <input disabled id='symbol_filter_gte' size=8 value='' style='text-align: right;'>
- <span style='-webkit-user-select: none; cursor: help;' title='Symbols whose size is less than this value will be hidden.'>[?]</span>
- </td>
- </tr>
- <tr>
- <td style='white-space: nowrap vertical-align: top;;'>
- Show at most <span style='font-style: italic;'>n</span> levels of detail at a time:
- </td>
- <td style='text-align: right; vertical-align: top;'>
- <input id='max_levels' size=4 value='2' style='text-align: right;'><span style='-webkit-user-select: none; cursor: help;' title='Increasing this value shows more detail without the need to zoom, but uses more computing power.'>[?]</span>
- </td>
- </tr>
- <tr>
- <td style='white-space: nowrap vertical-align: top;;'>
- Set the size of the treemap to <span style='font-style: italic;'>W x H</span> pixels:
- </td>
- <td style='text-align: right; vertical-align: top;'>
- <input id='width' size=4 value='' style='text-align: right;'>
- &nbsp;x&nbsp;<input id='height' size=4 value='' style='text-align: right;'>
- </td>
- </tr>
- </table>
-</td></tr>
-<tr><td style='padding-top: 10px; text-align: right; border-top: 1px solid grey'>
- <input type='button' value='Apply' onclick='applySettings()'>
- <input type='button' value='Cancel' onclick='cancelSettings()'>
-</td></tr></table>
-</body>
-</html>
diff --git a/chromium/tools/binary_size/libsupersize/template/test-data-generator.html b/chromium/tools/binary_size/libsupersize/template/test-data-generator.html
deleted file mode 100644
index 9c6790a8f9e..00000000000
--- a/chromium/tools/binary_size/libsupersize/template/test-data-generator.html
+++ /dev/null
@@ -1,157 +0,0 @@
-<!DOCTYPE html>
-<!--
- Copyright 2014 The Chromium Authors. All rights reserved.
- Use of this source code is governed by a BSD-style license that can be
- found in the LICENSE file.
--->
-<html>
-<head>
-<script>
-function rnd(max) {
- return Math.round(Math.random()*max);
-}
-
-function gen() {
- var dirs1=['usr1', 'etc1', 'var1'];
- var dirs2=['aaa2', 'bbb2', 'ccc2', 'ddd2', 'eee2', 'fff2', 'ggg2', 'hhh2',
- 'frobozz2', 'kazaam2', 'shazam2'];
- var dirs3=['iii3', 'jjj3', 'kkk3', 'lll3', 'mmm3', 'nnn3', 'ooo3', 'ppp3',
- 'wonderllama3', 'excelsior3', 'src3'];
- var filenames=['awesome.cc', 'rad.h', 'tubular.cxx', 'cool.cc', 'groovy.h',
- 'excellent.c', 'gnarly.h', 'green.C', 'articulate.cc'];
- //All possible types (we only see a subset in practice): 'ABbCDdGgiNpRrSsTtUuVvWw-?';
- var nm_symbol_types = 'trd';
- var minSize = 4;
- var maxSize = 10000;
- var numGen = 300000;
- var text = 'var nm_data=[\n';
- var vtablePercent = 5;
- for (var x=0; x<numGen; x++) {
- var path = '/' +
- dirs1[rnd(dirs1.length - 1)] + '/' +
- dirs2[rnd(dirs2.length - 1)] + '/' +
- dirs3[rnd(dirs3.length - 1)] + '/' +
- filenames[rnd(filenames.length - 1)];
- var isVtable = Math.floor((Math.random()*100)+1) <= vtablePercent;
- var size = rnd(maxSize);
- var symbol_name;
- var type;
- if (!isVtable) {
- symbol_name = 'sym' + x.toString(16);
- type = nm_symbol_types.charAt(rnd(nm_symbol_types.length - 1));
- } else {
- symbol_name = 'vtable for ' + x.toString(16);
- type = '@'
- }
- text = text + "{'n': '" + symbol_name +
- "', 't': '" + type +
- "', 's': " + size +
- ", 'p': '" + path + "'},\n";
- }
- text += '];';
-
- eval(text);
- var treeified = to_d3_tree(nm_data);
- generateDownloadLink('tree_data=' + JSON.stringify(treeified));
-}
-
-function generateDownloadLink(content) {
- var blob = new Blob([content], {type: 'text/plain'});
- var link = document.createElement('a');
- link.download = 'generated-content.txt';
- link.href = window.URL.createObjectURL(blob);
- link.textContent = 'Download ready, click here.';
- link.dataset.downloadurl = ['text/plain', link.download, link.href].join(':');
- link.onclick = function(e) {
- if ('disabled' in this.dataset) { return false; }
- link.dataset.disabled = true;
- setTimeout(function() { window.URL.revokeObjectURL(link.href); }, 1500);
- };
- document.getElementById('linkcontainer').innerHTML = '';
- document.getElementById('linkcontainer').appendChild(link);
-}
-
-/**
- * This function takes in an array of nm records and converts them into a
- * hierarchical data structure suitable for use in a d3-base treemap layout.
- * Leaves are individual symbols. The parents of the leaves are logical
- * groupings by common symbol-type (for BSS, read-only data, code, etc).
- * Above this, each node represents part of a filesystem path relative
- * to the parent node. The root node has the name '/', and represents
- * a root (though not necessarily THE root) of a file system traversal.
- * The root node also has a special property, 'maxDepth', to which is bound
- * the deepest level of nesting that was found during conversion: for the
- * record at path /a/b/c/d.foo, the maxDepth will be 6; the file 'd.foo'
- * is at depth 4, the type-bucket is depth 5 and the symbols are depth 6.
- */
-function to_d3_tree(records) {
- var result = {'n': '/', 'children': [], 'k': 'p'};
- var maxDepth = 0;
- //{'n': 'symbol1', 't': 'b', 's': 1000, 'p': '/usr/local/foo/foo.cc'},
- for (index in records) {
- var record = records[index];
- var parts = record.p.split("/");
- var node = result;
- var depth = 0;
- // Walk the tree and find the file that is named by the "location"
- // field of the record. We create any intermediate nodes required.
- // This is directly analogous to "mkdir -p".
- while(parts.length > 0) {
- var part = parts.shift();
- if (part.length == 0) continue;
- depth++;
- node = _mk_child(node, part, record.s);
- node.k = 'p'; // p for path
- }
- node.lastPathElement = true;
-
- // 'node' is now the file node. Find the symbol-type bucket.
- node = _mk_child(node, record.t, record.s);
- node.t = record.t;
- node.k = 'b'; // b for bucket
- depth++;
- // 'node' is now the symbol-type bucket. Make the child entry.
- node = _mk_child(node, record.n, record.s);
- delete node.children;
- node.value = record.s;
- node.t = record.t;
- node.k = 's'; // s for symbol
- depth++;
-
- maxDepth = Math.max(maxDepth, depth);
- }
- result.maxDepth = maxDepth;
- return result;
-}
-
-/**
- * Given a node and a name, return the child within node.children whose
- * name matches the specified name. If necessary, a new child node is
- * created and appended to node.children.
- * If this method creates a new node, the 'name' attribute is set to the
- * specified name and the 'children' attribute is an empty array, and
- * total_size is the specified size. Otherwise, the existing node is
- * returned and its total_size value is incremented by the specified size.
- */
-function _mk_child(node, name, size) {
- var child = undefined;
- for (child_index in node.children) {
- if (node.children[child_index].n == name) {
- child = node.children[child_index];
- }
- }
- if (child === undefined) {
- child = {'n': name, 'children': []};
- node.children.push(child);
- }
- return child;
-}
-</script>
-</head>
-<body style='white-space: pre; font-family: monospace;'>
-This script generates sample data for use in D3SymbolTreeMap, and can be used
-for testing.
-<input type=button onclick='gen();' value='Generate data'></input>
-<div id='linkcontainer'></div>
-</body>
-</html>
diff --git a/chromium/tools/binary_size/libsupersize/testdata/mock_output_directory/args.gn b/chromium/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/args.gn
index b8526773c3d..b8526773c3d 100644
--- a/chromium/tools/binary_size/libsupersize/testdata/mock_output_directory/args.gn
+++ b/chromium/tools/binary_size/libsupersize/testdata/mock_source_directory/out/Release/args.gn
diff --git a/chromium/tools/binary_size/libsupersize/third_party/gvr-android-sdk/libgvr_shim_static_arm.a b/chromium/tools/binary_size/libsupersize/third_party/gvr-android-sdk/libgvr_shim_static_arm.a
deleted file mode 100644
index 52881b6f2a6..00000000000
--- a/chromium/tools/binary_size/libsupersize/third_party/gvr-android-sdk/libgvr_shim_static_arm.a
+++ /dev/null
@@ -1,3 +0,0 @@
-This file has to exist so that it can be checked for whether or not it is a
-thin archive. Thin archives start with "!<thin>\n". As you can see, this file is
-not a thin archive.
diff --git a/chromium/tools/binary_size/supersize.pydeps b/chromium/tools/binary_size/supersize.pydeps
index c9ded25ad4d..5b4d56aca49 100644
--- a/chromium/tools/binary_size/supersize.pydeps
+++ b/chromium/tools/binary_size/supersize.pydeps
@@ -57,4 +57,7 @@ libsupersize/match_util.py
libsupersize/models.py
libsupersize/ninja_parser.py
libsupersize/nm.py
+libsupersize/obj_analyzer.py
libsupersize/path_util.py
+libsupersize/start_server.py
+libsupersize/string_extract.py
diff --git a/chromium/tools/binary_size/trybot_commit_size_checker.py b/chromium/tools/binary_size/trybot_commit_size_checker.py
new file mode 100755
index 00000000000..664be053c99
--- /dev/null
+++ b/chromium/tools/binary_size/trybot_commit_size_checker.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Fails if a try job increases binary size unexpectedly."""
+
+import argparse
+import sys
+
+
+_MAX_UNNOTICED_INCREASE = 16 * 1024
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--author', help='CL author')
+ parser.add_argument('--resource-sizes-diff',
+ help='Path to resource sizes diff produced by '
+ '"diagnose_bloat.py diff sizes".')
+ args = parser.parse_args()
+
+ # Last line looks like:
+ # MonochromePublic.apk_Specifics normalized apk size=1234
+ with open(args.resource_sizes_diff) as f:
+ last_line = f.readlines()[-1]
+ size_delta = int(last_line.partition('=')[2])
+
+ is_roller = '-autoroll' in args.author
+
+ # Useful for bot debugging to have these printed out:
+ print 'Is Roller:', is_roller
+ print 'Increase:', size_delta
+
+ if size_delta > _MAX_UNNOTICED_INCREASE and not is_roller:
+ # Failure message printed to stderr, so flush first.
+ sys.stdout.flush()
+ failure_message = """
+
+Binary size increase is non-trivial (where "non-trivial" means the normalized \
+size increased by more than {} bytes).
+
+Please look at the symbol diffs from the "Show Resource Sizes Diff" and the \
+"Show Supersize Diff" bot steps. Try and understand the growth and see if it \
+can be mitigated. There is guidance at:
+
+https://chromium.googlesource.com/chromium/src/+/master/docs/speed/apk_size_regressions.md#Debugging-Apk-Size-Increase
+
+If the growth is expected / justified, then you can bypass this bot failure by \
+adding "Binary-Size: $JUSTIFICATION" to your commit description. Here are some \
+examples:
+
+Binary-Size: Increase is due to translations and so cannot be avoided.
+Binary-Size: Increase is due to new images, which are already optimally encoded.
+Binary-Size: Increase is temporary due to a "new way" / "old way" refactoring.
+ It should go away once the "old way" is removed.
+Binary-Size: Increase is temporary and will be reverted before next branch cut.
+Binary-Size: Increase needed to reduce RAM of a common user flow.
+Binary-Size: Increase needed to reduce runtime of a common user flow.
+Binary-Size: Increase needed to implement a feature, and I've already spent a
+ non-trivial amount of time trying to reduce its size.
+""".format(_MAX_UNNOTICED_INCREASE)
+ # Make blank lines not blank prevent them from being stripped.
+ # https://crbug.com/855671
+ failure_message.replace('\n\n', '\n.\n')
+ sys.exit(failure_message)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/cfi/blacklist.txt b/chromium/tools/cfi/blacklist.txt
index 2301ebdb4fd..41e5b4d1148 100644
--- a/chromium/tools/cfi/blacklist.txt
+++ b/chromium/tools/cfi/blacklist.txt
@@ -151,7 +151,6 @@ src:*audio/pulse/pulse_stubs.cc
src:*chrome/browser/speech/tts_linux.cc
src:*device/udev_linux/udev0_loader.cc
src:*device/udev_linux/udev1_loader.cc
-src:*net/proxy_resolution/proxy_config_service_linux.cc
# Calls to auto-generated stubs by ui/gl/generate_bindings.py
src:*ui/gl/gl_bindings_autogen_*
diff --git a/chromium/tools/checkperms/checkperms.py b/chromium/tools/checkperms/checkperms.py
index 7388a7ef2fc..23c58cd12a0 100755
--- a/chromium/tools/checkperms/checkperms.py
+++ b/chromium/tools/checkperms/checkperms.py
@@ -321,7 +321,8 @@ def check_file(root_path, rel_path):
def check_files(root, files):
- gen = (check_file(root, f) for f in files if not is_ignored(f))
+ gen = (check_file(root, f) for f in files
+ if not is_ignored(f) and not os.path.isdir(f))
return filter(None, gen)
diff --git a/chromium/tools/chrome_proxy/webdriver/bypass.py b/chromium/tools/chrome_proxy/webdriver/bypass.py
index 315e2311dba..474ec720c68 100644
--- a/chromium/tools/chrome_proxy/webdriver/bypass.py
+++ b/chromium/tools/chrome_proxy/webdriver/bypass.py
@@ -188,7 +188,7 @@ class Bypass(IntegrationTest):
self.skipTest('This test cannot be run with other experiments.')
with TestDriver() as test_driver:
test_driver.AddChromeArg('--enable-spdy-proxy-auth')
- test_driver.AddChromeArg('--data-reduction-proxy-experiment=test')
+ test_driver.AddChromeArg('--data-reduction-proxy-experiment=client_test_bypass')
# Verify that loading a page other than the specific exp directive test
# page loads through the proxy without being bypassed.
@@ -198,7 +198,7 @@ class Bypass(IntegrationTest):
for response in responses:
self.assertHasChromeProxyViaHeader(response)
- # Verify that loading the exp directive test page with "exp=test" triggers
+ # Verify that loading the exp directive test page with "exp=client_test_bypass" triggers
# a bypass.
test_driver.LoadURL('http://check.googlezip.net/exp/')
responses = test_driver.GetHTTPResponses()
@@ -206,7 +206,7 @@ class Bypass(IntegrationTest):
for response in responses:
self.assertNotHasChromeProxyViaHeader(response)
- # Verify that loading the same test page without setting "exp=test" loads
+ # Verify that loading the same test page without setting "exp=client_test_bypass" loads
# through the proxy without being bypassed.
with TestDriver() as test_driver:
test_driver.AddChromeArg('--enable-spdy-proxy-auth')
diff --git a/chromium/tools/chrome_proxy/webdriver/lite_page.py b/chromium/tools/chrome_proxy/webdriver/lite_page.py
index 398cefc3ed1..655abe7c236 100644
--- a/chromium/tools/chrome_proxy/webdriver/lite_page.py
+++ b/chromium/tools/chrome_proxy/webdriver/lite_page.py
@@ -143,110 +143,6 @@ class LitePage(IntegrationTest):
# Verify that a main frame without Lite Page was seen.
self.assertEqual(1, non_lite_page_responses)
- # Checks that a Lite Page does not have an error when scrolling to the bottom
- # of the page and is able to load all resources. This test is only run on
- # Android because it depends on window size of the browser.
- @AndroidOnly
- @ChromeVersionBeforeM(65)
- def testLitePageBTFOldFlags(self):
- # If it was attempted to run with another experiment, skip this test.
- if common.ParseFlags().browser_args and ('--data-reduction-proxy-experiment'
- in common.ParseFlags().browser_args):
- self.skipTest('This test cannot be run with other experiments.')
- with TestDriver() as test_driver:
- test_driver.AddChromeArg('--enable-spdy-proxy-auth')
- # Need to force lite page so target page doesn't fallback to Lo-Fi
- test_driver.AddChromeArg('--data-reduction-proxy-lo-fi=always-on')
- test_driver.AddChromeArg('--enable-data-reduction-proxy-lite-page')
- test_driver.AddChromeArg('--data-reduction-proxy-experiment=alt6')
-
- # This page is long and has many media resources.
- test_driver.LoadURL('http://check.googlezip.net/metrics/index.html')
-
- # Verify that a Lite Page response for the main frame was seen.
- lite_page_responses = 0
- for response in test_driver.GetHTTPResponses():
- # Skip CSI requests when validating Lite Page headers. CSI requests
- # aren't expected to have LoFi headers.
- if '/csi?' in response.url:
- continue
- if response.url.startswith('data:'):
- continue
- if (self.checkLitePageResponse(response)):
- lite_page_responses = lite_page_responses + 1
- self.assertEqual(1, lite_page_responses)
-
- # Scroll to the bottom of the window and ensure scrollHeight increases.
- original_scroll_height = test_driver.ExecuteJavascriptStatement(
- 'document.body.scrollHeight')
- test_driver.ExecuteJavascriptStatement(
- 'window.scrollTo(0,Math.max(document.body.scrollHeight));')
- # Give some time for loading after scrolling.
- time.sleep(2)
- new_scroll_height = test_driver.ExecuteJavascriptStatement(
- 'document.body.scrollHeight')
- self.assertGreater(new_scroll_height, original_scroll_height)
-
- # Make sure there were more requests that were proxied.
- responses = test_driver.GetHTTPResponses(override_has_logs=True)
- self.assertNotEqual(0, len(responses))
- for response in responses:
- self.assertHasChromeProxyViaHeader(response)
- self.assertIn(response.status, [200, 204])
-
- # Checks that a Lite Page does not have an error when scrolling to the bottom
- # of the page and is able to load all resources. This test is only run on
- # Android because it depends on window size of the browser.
- @AndroidOnly
- @ChromeVersionEqualOrAfterM(65)
- def testLitePageBTFWithoutFallback(self):
- # If it was attempted to run with another experiment, skip this test.
- if common.ParseFlags().browser_args and ('--data-reduction-proxy-experiment'
- in common.ParseFlags().browser_args):
- self.skipTest('This test cannot be run with other experiments.')
- with TestDriver() as test_driver:
- test_driver.AddChromeArg('--enable-spdy-proxy-auth')
- # Need to force 2G speed to get lite-page response.
- test_driver.AddChromeArg('--force-effective-connection-type=2G')
-
- # Need to force lite page so target page doesn't fallback to Lo-Fi
- # Set exp=alt6 to force Lite-page response.
- test_driver.AddChromeArg('--data-reduction-proxy-experiment=alt6')
-
- # This page is long and has many media resources.
- test_driver.LoadURL('http://check.googlezip.net/metrics/index.html')
-
- # Verify that a Lite Page response for the main frame was seen.
- lite_page_responses = 0
- for response in test_driver.GetHTTPResponses():
- # Skip CSI requests when validating Lite Page headers. CSI requests
- # aren't expected to have LoFi headers.
- if '/csi?' in response.url:
- continue
- if response.url.startswith('data:'):
- continue
- if (self.checkLitePageResponse(response)):
- lite_page_responses = lite_page_responses + 1
- self.assertEqual(1, lite_page_responses)
-
- # Scroll to the bottom of the window and ensure scrollHeight increases.
- original_scroll_height = test_driver.ExecuteJavascriptStatement(
- 'document.body.scrollHeight')
- test_driver.ExecuteJavascriptStatement(
- 'window.scrollTo(0,Math.max(document.body.scrollHeight));')
- # Give some time for loading after scrolling.
- time.sleep(2)
- new_scroll_height = test_driver.ExecuteJavascriptStatement(
- 'document.body.scrollHeight')
- self.assertGreater(new_scroll_height, original_scroll_height)
-
- # Make sure there were more requests that were proxied.
- responses = test_driver.GetHTTPResponses(override_has_logs=True)
- self.assertNotEqual(0, len(responses))
- for response in responses:
- self.assertHasChromeProxyViaHeader(response)
- self.assertIn(response.status, [200, 204])
-
# Checks that a Nano Lite Page does not have an error when scrolling to the
# bottom of the page and is able to load all resources. Nano pages don't
# request additional resources when scrolling. This test is only run on
@@ -260,10 +156,12 @@ class LitePage(IntegrationTest):
self.skipTest('This test cannot be run with other experiments.')
with TestDriver() as test_driver:
test_driver.AddChromeArg('--enable-spdy-proxy-auth')
+ test_driver.AddChromeArg('--enable-features='
+ 'Previews,DataReductionProxyDecidesTransform')
# Need to force 2G speed to get lite-page response.
test_driver.AddChromeArg('--force-effective-connection-type=2G')
- # Set exp=alt2 to force Nano response.
- test_driver.AddChromeArg('--data-reduction-proxy-experiment=alt2')
+ # Set exp=client_test_nano to force Nano response.
+ test_driver.AddChromeArg('--data-reduction-proxy-experiment=client_test_nano')
# This page is long and has many media resources.
test_driver.LoadURL('http://check.googlezip.net/metrics/index.html')
@@ -497,7 +395,7 @@ class LitePage(IntegrationTest):
'Previews,DataReductionProxyDecidesTransform')
# Need to force 2G speed to get a preview.
test_driver.AddChromeArg('--force-effective-connection-type=2G')
- # Set exp=ihdp_integration to force iCASPR response.
+ # Set exp=client_test_icaspr to force iCASPR response.
test_driver.AddChromeArg(
'--data-reduction-proxy-experiment=ihdp_integration')
diff --git a/chromium/tools/chrome_proxy/webdriver/lofi.py b/chromium/tools/chrome_proxy/webdriver/lofi.py
index 8c707ee6ed6..050be5b1f01 100644
--- a/chromium/tools/chrome_proxy/webdriver/lofi.py
+++ b/chromium/tools/chrome_proxy/webdriver/lofi.py
@@ -468,5 +468,48 @@ class LoFi(IntegrationTest):
self.assertNotEqual(0, intervention_headers)
+ # Checks that Client LoFi range requests that go through the Data Reduction
+ # Proxy are returned correctly.
+ @ChromeVersionEqualOrAfterM(62)
+ def testClientLoFiRangeRequestThroughDataReductionProxy(self):
+ with TestDriver() as test_driver:
+ test_driver.AddChromeArg('--enable-spdy-proxy-auth')
+ # Enable Previews and Client-side LoFi, but disable server previews in
+ # order to force Chrome to use Client-side LoFi for the images on the
+ # page.
+ test_driver.AddChromeArg('--enable-features=Previews,PreviewsClientLoFi')
+ test_driver.AddChromeArg(
+ '--disable-features=DataReductionProxyDecidesTransform')
+
+ test_driver.AddChromeArg(
+ '--force-fieldtrial-params=NetworkQualityEstimator.Enabled:'
+ 'force_effective_connection_type/2G,'
+ 'PreviewsClientLoFi.Enabled:'
+ 'max_allowed_effective_connection_type/4G')
+
+ test_driver.AddChromeArg(
+ '--force-fieldtrials=NetworkQualityEstimator/Enabled/'
+ 'PreviewsClientLoFi/Enabled')
+
+ # Fetch a non-SSL page with multiple images on it, such that the images
+ # are fetched through the Data Reduction Proxy.
+ test_driver.LoadURL('http://check.googlezip.net/static/index.html')
+
+ image_response_count = 0
+ for response in test_driver.GetHTTPResponses():
+ if response.url.endswith('.png'):
+ self.assertHasChromeProxyViaHeader(response)
+ self.assertIn('range', response.request_headers)
+ self.assertIn('content-range', response.response_headers)
+ self.assertTrue(response.response_headers['content-range'].startswith(
+ 'bytes 0-2047/'))
+ image_response_count = image_response_count + 1
+
+ self.assertNotEqual(0, image_response_count)
+
+ # Verify Lo-Fi previews info bar recorded.
+ histogram = test_driver.GetHistogram('Previews.InfoBarAction.LoFi', 5)
+ self.assertEqual(1, histogram['count'])
+
if __name__ == '__main__':
IntegrationTest.RunAllTests()
diff --git a/chromium/tools/chrome_proxy/webdriver/variations_combinations.py b/chromium/tools/chrome_proxy/webdriver/variations_combinations.py
index 20c565ac2f8..fc6d36d5408 100644
--- a/chromium/tools/chrome_proxy/webdriver/variations_combinations.py
+++ b/chromium/tools/chrome_proxy/webdriver/variations_combinations.py
@@ -42,12 +42,12 @@ def GetExperimentArgs():
elif platform.system().lower() == 'linux':
my_platform = 'linux'
elif platform.system().lower() == 'windows':
- my_platform = 'win'
+ my_platform = 'windows'
elif platform.system().lower() == 'darwin':
my_platform = 'mac'
else:
raise Exception('unknown platform!')
- return fieldtrial_util.GenerateArgs(config_path, my_platform)
+ return fieldtrial_util.GenerateArgs(config_path, [my_platform])
def GenerateTestSuites():
"""A generator function that yields non-blacklisted tests to run.
diff --git a/chromium/tools/clang/base_bind_rewriters/BaseBindRewriters.cpp b/chromium/tools/clang/base_bind_rewriters/BaseBindRewriters.cpp
index b906f7ad7dd..4f6c068e54b 100644
--- a/chromium/tools/clang/base_bind_rewriters/BaseBindRewriters.cpp
+++ b/chromium/tools/clang/base_bind_rewriters/BaseBindRewriters.cpp
@@ -161,9 +161,8 @@ class BindOnceRewriter : public MatchFinder::MatchCallback, public Rewriter {
auto constructor_conversion = cxxConstructExpr(
is_once_callback, argumentCountIs(1),
hasArgument(0, ignoringImplicit(parameter_construction)));
- auto implicit_conversion = implicitCastExpr(
- is_once_callback, hasSourceExpression(constructor_conversion));
- return implicit_conversion;
+ return implicitCastExpr(is_once_callback,
+ hasSourceExpression(constructor_conversion));
}
void run(const MatchFinder::MatchResult& result) override {
@@ -577,6 +576,66 @@ class AddStdMoveRewriter : public MatchFinder::MatchCallback, public Rewriter {
Replacements* replacements_;
};
+// Remove base::AdaptCallbackForRepeating() where resulting
+// base::RepeatingCallback is implicitly converted into base::OnceCallback.
+// Example:
+// // Before
+// base::PostTask(
+// FROM_HERE,
+// base::AdaptCallbackForRepeating(base::BindOnce(&Foo)));
+// base::OnceCallback<void()> cb = base::AdaptCallbackForRepeating(
+// base::OnceBind(&Foo));
+//
+// // After
+// base::PostTask(FROM_HERE, base::BindOnce(&Foo));
+// base::OnceCallback<void()> cb = base::BindOnce(&Foo);
+class AdaptCallbackForRepeatingRewriter : public MatchFinder::MatchCallback,
+ public Rewriter {
+ public:
+ explicit AdaptCallbackForRepeatingRewriter(Replacements* replacements)
+ : replacements_(replacements) {}
+
+ StatementMatcher GetMatcher() {
+ auto is_once_callback = hasType(hasCanonicalType(hasDeclaration(
+ classTemplateSpecializationDecl(hasName("::base::OnceCallback")))));
+ auto is_repeating_callback =
+ hasType(hasCanonicalType(hasDeclaration(classTemplateSpecializationDecl(
+ hasName("::base::RepeatingCallback")))));
+
+ auto adapt_callback_call =
+ callExpr(
+ callee(namedDecl(hasName("::base::AdaptCallbackForRepeating"))))
+ .bind("target");
+ auto parameter_construction =
+ cxxConstructExpr(is_repeating_callback, argumentCountIs(1),
+ hasArgument(0, ignoringImplicit(adapt_callback_call)));
+ auto constructor_conversion = cxxConstructExpr(
+ is_once_callback, argumentCountIs(1),
+ hasArgument(0, ignoringImplicit(parameter_construction)));
+ return implicitCastExpr(is_once_callback,
+ hasSourceExpression(constructor_conversion));
+ }
+
+ void run(const MatchFinder::MatchResult& result) override {
+ auto* target = result.Nodes.getNodeAs<clang::CallExpr>("target");
+
+ auto left = clang::CharSourceRange::getTokenRange(
+ result.SourceManager->getSpellingLoc(target->getLocStart()),
+ result.SourceManager->getSpellingLoc(target->getArg(0)->getExprLoc())
+ .getLocWithOffset(-1));
+
+ // We use " " as replacement to work around https://crbug.com/861886.
+ replacements_->emplace_back(*result.SourceManager, left, " ");
+ auto r_paren = clang::CharSourceRange::getTokenRange(
+ result.SourceManager->getSpellingLoc(target->getRParenLoc()),
+ result.SourceManager->getSpellingLoc(target->getRParenLoc()));
+ replacements_->emplace_back(*result.SourceManager, r_paren, " ");
+ }
+
+ private:
+ Replacements* replacements_;
+};
+
llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
llvm::cl::OptionCategory rewriter_category("Rewriter Options");
@@ -588,6 +647,7 @@ Available rewriters are:
bind_to_bind_once
pass_by_value
add_std_move
+ remove_unneeded_adapt_callback
The default is remove_unneeded_passed.
)"),
llvm::cl::init("remove_unneeded_passed"),
@@ -623,6 +683,12 @@ int main(int argc, const char* argv[]) {
auto add_std_move = llvm::make_unique<AddStdMoveRewriter>(&replacements);
match_finder.addMatcher(add_std_move->GetMatcher(), add_std_move.get());
rewriter = std::move(add_std_move);
+ } else if (rewriter_option == "remove_unneeded_adapt_callback") {
+ auto remove_unneeded_adapt_callback =
+ llvm::make_unique<AdaptCallbackForRepeatingRewriter>(&replacements);
+ match_finder.addMatcher(remove_unneeded_adapt_callback->GetMatcher(),
+ remove_unneeded_adapt_callback.get());
+ rewriter = std::move(remove_unneeded_adapt_callback);
} else {
abort();
}
diff --git a/chromium/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp b/chromium/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
index ff6af461330..36db12aba53 100644
--- a/chromium/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
+++ b/chromium/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
@@ -37,8 +37,6 @@ class BlinkGCPluginAction : public PluginASTAction {
options_.warn_unneeded_finalizer = true;
} else if (arg == "enable-weak-members-in-unmanaged-classes") {
options_.enable_weak_members_in_unmanaged_classes = true;
- } else if (arg == "warn-trace-wrappers-missing-base-dispatch") {
- options_.warn_trace_wrappers_missing_base_dispatch = true;
} else {
llvm::errs() << "Unknown blink-gc-plugin argument: " << arg << "\n";
return false;
diff --git a/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp b/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp
index 4deee9cb369..7768fe355f3 100644
--- a/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp
+++ b/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp
@@ -13,7 +13,6 @@
#include "CheckFinalizerVisitor.h"
#include "CheckGCRootsVisitor.h"
#include "CheckTraceVisitor.h"
-#include "CheckTraceWrappersVisitor.h"
#include "CollectVisitor.h"
#include "JsonWriter.h"
#include "RecordInfo.h"
@@ -119,11 +118,6 @@ void BlinkGCPluginConsumer::HandleTranslationUnit(ASTContext& context) {
for (const auto& method : visitor.trace_decls())
CheckTracingMethod(method);
- if (options_.warn_trace_wrappers_missing_base_dispatch) {
- for (const auto& method : visitor.trace_wrapper_decls())
- CheckWrapperTracingMethod(method);
- }
-
if (json_) {
json_->CloseList();
delete json_;
@@ -531,16 +525,6 @@ void BlinkGCPluginConsumer::CheckTracingMethod(CXXMethodDecl* method) {
CheckTraceOrDispatchMethod(parent, method);
}
-void BlinkGCPluginConsumer::CheckWrapperTracingMethod(CXXMethodDecl* method) {
- RecordInfo* parent = cache_.Lookup(method->getParent());
- if (IsIgnored(parent))
- return;
-
- Config::TraceWrappersMethodType trace_wrappers_type =
- Config::GetTraceWrappersMethodType(method);
- CheckTraceWrappersMethod(parent, method, trace_wrappers_type);
-}
-
void BlinkGCPluginConsumer::CheckTraceOrDispatchMethod(
RecordInfo* parent,
CXXMethodDecl* method) {
@@ -580,18 +564,6 @@ void BlinkGCPluginConsumer::CheckTraceMethod(
}
}
-void BlinkGCPluginConsumer::CheckTraceWrappersMethod(
- RecordInfo* parent,
- clang::CXXMethodDecl* trace_wrappers,
- Config::TraceWrappersMethodType trace_wrappers_type) {
- CheckTraceWrappersVisitor visitor(trace_wrappers, parent, &cache_);
- visitor.TraverseCXXMethodDecl(trace_wrappers);
-
- for (auto& base : parent->GetBases())
- if (!base.second.IsProperlyWrapperTraced())
- reporter_.BaseRequiresWrapperTracing(parent, trace_wrappers, base.first);
-}
-
void BlinkGCPluginConsumer::DumpClass(RecordInfo* info) {
if (!json_)
return;
diff --git a/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.h b/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.h
index d76ccf236e0..bcfb3afbd59 100644
--- a/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.h
+++ b/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.h
@@ -57,8 +57,6 @@ class BlinkGCPluginConsumer : public clang::ASTConsumer {
// This is the main entry for tracing method definitions.
void CheckTracingMethod(clang::CXXMethodDecl* method);
- void CheckWrapperTracingMethod(clang::CXXMethodDecl* method);
-
// Determine what type of tracing method this is (dispatch or trace).
void CheckTraceOrDispatchMethod(RecordInfo* parent,
clang::CXXMethodDecl* method);
@@ -68,11 +66,6 @@ class BlinkGCPluginConsumer : public clang::ASTConsumer {
clang::CXXMethodDecl* trace,
Config::TraceMethodType trace_type);
- void CheckTraceWrappersMethod(
- RecordInfo* parent,
- clang::CXXMethodDecl* trace_wrappers,
- Config::TraceWrappersMethodType trace_wrappers_type);
-
void DumpClass(RecordInfo* info);
// Adds either a warning or error, based on the current handling of -Werror.
diff --git a/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h b/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h
index f69976d9824..4af8950f11f 100644
--- a/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h
+++ b/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h
@@ -30,9 +30,6 @@ struct BlinkGCPluginOptions {
// TODO(sof): remove this option once safely rolled out.
bool enable_weak_members_in_unmanaged_classes = false;
- // Warn on missing dispatches to base class TraceWrappers.
- bool warn_trace_wrappers_missing_base_dispatch = false;
-
std::set<std::string> ignored_classes;
std::set<std::string> checked_namespaces;
std::vector<std::string> ignored_directories;
diff --git a/chromium/tools/clang/blink_gc_plugin/CMakeLists.txt b/chromium/tools/clang/blink_gc_plugin/CMakeLists.txt
index 5188def93de..1429f0b9ee1 100644
--- a/chromium/tools/clang/blink_gc_plugin/CMakeLists.txt
+++ b/chromium/tools/clang/blink_gc_plugin/CMakeLists.txt
@@ -9,7 +9,6 @@ set(plugin_sources
CheckFinalizerVisitor.cpp
CheckGCRootsVisitor.cpp
CheckTraceVisitor.cpp
- CheckTraceWrappersVisitor.cpp
CollectVisitor.cpp
Config.cpp
DiagnosticsReporter.cpp
diff --git a/chromium/tools/clang/blink_gc_plugin/CheckTraceWrappersVisitor.cpp b/chromium/tools/clang/blink_gc_plugin/CheckTraceWrappersVisitor.cpp
deleted file mode 100644
index 106f9833551..00000000000
--- a/chromium/tools/clang/blink_gc_plugin/CheckTraceWrappersVisitor.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "CheckTraceWrappersVisitor.h"
-
-#include <vector>
-
-#include "Config.h"
-
-using namespace clang;
-
-CheckTraceWrappersVisitor::CheckTraceWrappersVisitor(CXXMethodDecl* trace,
- RecordInfo* info,
- RecordCache* cache)
- : trace_wrappers_(trace), info_(info), cache_(cache) {}
-
-bool CheckTraceWrappersVisitor::VisitCallExpr(CallExpr* call) {
- CheckTraceBaseCall(call);
- return true;
-}
-
-bool CheckTraceWrappersVisitor::IsTraceWrappersCallName(
- const std::string& name) {
- // See CheckTraceVisitor::IsTraceCallName.
- return name == trace_wrappers_->getName();
-}
-
-bool CheckTraceWrappersVisitor::CheckTraceBaseCall(CallExpr* call) {
- // Checks for "Base::TraceWrappers(visitor)"-like calls.
-
- // For example, if we've got "Base::TraceWrappers(visitor)" as |call|,
- // callee_record will be "Base", and func_name will be "TraceWrappers".
- CXXRecordDecl* callee_record = nullptr;
- std::string func_name;
-
- if (MemberExpr* callee = dyn_cast<MemberExpr>(call->getCallee())) {
- if (!callee->hasQualifier())
- return false;
-
- FunctionDecl* trace_decl = dyn_cast<FunctionDecl>(callee->getMemberDecl());
- if (!trace_decl || !Config::IsTraceWrappersMethod(trace_decl))
- return false;
-
- const Type* type = callee->getQualifier()->getAsType();
- if (!type)
- return false;
-
- callee_record = type->getAsCXXRecordDecl();
- func_name = trace_decl->getName();
- }
-
- if (!callee_record)
- return false;
-
- if (!IsTraceWrappersCallName(func_name))
- return false;
-
- for (auto& base : info_->GetBases()) {
- // We want to deal with omitted TraceWrappers() function in an intermediary
- // class in the class hierarchy, e.g.:
- // class A : public TraceWrapperBase<A> { TraceWrappers() { ... } };
- // class B : public A {
- // /* No TraceWrappers(); have nothing to trace. */
- // };
- // class C : public B { TraceWrappers() { B::TraceWrappers(visitor); } }
- // where, B::TraceWrappers() is actually A::TraceWrappers(), and in some
- // cases we get A as |callee_record| instead of B. We somehow need to mark B
- // as wrapper traced if we find A::TraceWrappers() call.
- //
- // To solve this, here we keep going up the class hierarchy as long as
- // they are not required to have a trace method. The implementation is
- // a simple DFS, where |base_records| represents the set of base classes
- // we need to visit.
-
- std::vector<CXXRecordDecl*> base_records;
- base_records.push_back(base.first);
-
- while (!base_records.empty()) {
- CXXRecordDecl* base_record = base_records.back();
- base_records.pop_back();
-
- if (base_record == callee_record) {
- // If we find a matching trace method, pretend the user has written
- // a correct trace() method of the base; in the example above, we
- // find A::trace() here and mark B as correctly traced.
- base.second.MarkWrapperTraced();
- return true;
- }
-
- if (RecordInfo* base_info = cache_->Lookup(base_record)) {
- if (!base_info->RequiresTraceWrappersMethod()) {
- // If this base class is not required to have a trace method, then
- // the actual trace method may be defined in an ancestor.
- for (auto& inner_base : base_info->GetBases())
- base_records.push_back(inner_base.first);
- }
- }
- }
- }
-
- return false;
-}
diff --git a/chromium/tools/clang/blink_gc_plugin/CheckTraceWrappersVisitor.h b/chromium/tools/clang/blink_gc_plugin/CheckTraceWrappersVisitor.h
deleted file mode 100644
index 619046583cc..00000000000
--- a/chromium/tools/clang/blink_gc_plugin/CheckTraceWrappersVisitor.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_BLINK_GC_PLUGIN_CHECK_TRACE_WRAPPERS_VISITOR_H_
-#define TOOLS_BLINK_GC_PLUGIN_CHECK_TRACE_WRAPPERS_VISITOR_H_
-
-#include <string>
-
-#include "RecordInfo.h"
-#include "clang/AST/AST.h"
-#include "clang/AST/RecursiveASTVisitor.h"
-
-class RecordCache;
-class RecordInfo;
-
-// This visitor checks a wrapper tracing method by traversing its body.
-// - A base is wrapper traced if a base-qualified call to a trace method is
-// found.
-class CheckTraceWrappersVisitor
- : public clang::RecursiveASTVisitor<CheckTraceWrappersVisitor> {
- public:
- CheckTraceWrappersVisitor(clang::CXXMethodDecl* trace,
- RecordInfo* info,
- RecordCache* cache);
-
- bool VisitCallExpr(clang::CallExpr* call);
-
- private:
- bool IsTraceWrappersCallName(const std::string& name);
-
- bool CheckTraceBaseCall(clang::CallExpr* call);
-
- clang::CXXMethodDecl* trace_wrappers_;
- RecordInfo* info_;
- RecordCache* cache_;
-};
-
-#endif // TOOLS_BLINK_GC_PLUGIN_CHECK_TRACE_WRAPPERS_VISITOR_H_
diff --git a/chromium/tools/clang/blink_gc_plugin/CollectVisitor.cpp b/chromium/tools/clang/blink_gc_plugin/CollectVisitor.cpp
index 0f999a4ad1d..89af6fc2107 100644
--- a/chromium/tools/clang/blink_gc_plugin/CollectVisitor.cpp
+++ b/chromium/tools/clang/blink_gc_plugin/CollectVisitor.cpp
@@ -19,10 +19,6 @@ CollectVisitor::MethodVector& CollectVisitor::trace_decls() {
return trace_decls_;
}
-CollectVisitor::MethodVector& CollectVisitor::trace_wrapper_decls() {
- return trace_wrapper_decls_;
-}
-
bool CollectVisitor::VisitCXXRecordDecl(CXXRecordDecl* record) {
if (record->hasDefinition() && record->isCompleteDefinition())
record_decls_.push_back(record);
@@ -34,8 +30,6 @@ bool CollectVisitor::VisitCXXMethodDecl(CXXMethodDecl* method) {
if (Config::IsTraceMethod(method)) {
trace_decls_.push_back(method);
}
- if (Config::IsTraceWrappersMethod(method))
- trace_wrapper_decls_.push_back(method);
}
return true;
}
diff --git a/chromium/tools/clang/blink_gc_plugin/CollectVisitor.h b/chromium/tools/clang/blink_gc_plugin/CollectVisitor.h
index 4adf81904b4..a3ccdd8a331 100644
--- a/chromium/tools/clang/blink_gc_plugin/CollectVisitor.h
+++ b/chromium/tools/clang/blink_gc_plugin/CollectVisitor.h
@@ -20,7 +20,6 @@ class CollectVisitor : public clang::RecursiveASTVisitor<CollectVisitor> {
RecordVector& record_decls();
MethodVector& trace_decls();
- MethodVector& trace_wrapper_decls();
// Collect record declarations, including nested declarations.
bool VisitCXXRecordDecl(clang::CXXRecordDecl* record);
@@ -31,7 +30,6 @@ class CollectVisitor : public clang::RecursiveASTVisitor<CollectVisitor> {
private:
RecordVector record_decls_;
MethodVector trace_decls_;
- MethodVector trace_wrapper_decls_;
};
#endif // TOOLS_BLINK_GC_PLUGIN_COLLECT_VISITOR_H_
diff --git a/chromium/tools/clang/blink_gc_plugin/Config.cpp b/chromium/tools/clang/blink_gc_plugin/Config.cpp
index 4b3a1a3a9b8..df8867a9b29 100644
--- a/chromium/tools/clang/blink_gc_plugin/Config.cpp
+++ b/chromium/tools/clang/blink_gc_plugin/Config.cpp
@@ -13,7 +13,6 @@ using namespace clang;
const char kNewOperatorName[] = "operator new";
const char kCreateName[] = "Create";
const char kTraceName[] = "Trace";
-const char kTraceWrappersName[] = "TraceWrappers";
const char kFinalizeName[] = "FinalizeGarbageCollectedObject";
const char kTraceAfterDispatchName[] = "TraceAfterDispatch";
const char kRegisterWeakMembersName[] = "RegisterWeakMembers";
@@ -29,10 +28,6 @@ const char kIteratorName[] = "iterator";
const char kConstReverseIteratorName[] = "const_reverse_iterator";
const char kReverseIteratorName[] = "reverse_iterator";
-const char* kIgnoredTraceWrapperNames[] = {
- "blink::ScriptWrappableVisitor::TraceWrappers",
- "blink::WrapperMarkingData::TraceWrappers"};
-
bool Config::IsTemplateInstantiation(CXXRecordDecl* record) {
ClassTemplateSpecializationDecl* spec =
dyn_cast<clang::ClassTemplateSpecializationDecl>(record);
@@ -52,29 +47,3 @@ bool Config::IsTemplateInstantiation(CXXRecordDecl* record) {
assert(false && "Unknown template specialization kind");
return false;
}
-
-// static
-Config::TraceWrappersMethodType Config::GetTraceWrappersMethodType(
- const clang::FunctionDecl* method) {
- if (method->getNumParams() != 1)
- return NOT_TRACE_WRAPPERS_METHOD;
-
- const std::string& name = method->getNameAsString();
- const std::string& full_name = method->getQualifiedNameAsString();
- for (size_t i = 0; i < (sizeof(kIgnoredTraceWrapperNames) /
- sizeof(kIgnoredTraceWrapperNames[0]));
- i++) {
- if (full_name == kIgnoredTraceWrapperNames[i])
- return NOT_TRACE_WRAPPERS_METHOD;
- }
-
- if (name == kTraceWrappersName)
- return TRACE_WRAPPERS_METHOD;
-
- return NOT_TRACE_WRAPPERS_METHOD;
-}
-
-// static
-bool Config::IsTraceWrappersMethod(const clang::FunctionDecl* method) {
- return GetTraceWrappersMethodType(method) != NOT_TRACE_WRAPPERS_METHOD;
-}
diff --git a/chromium/tools/clang/blink_gc_plugin/Config.h b/chromium/tools/clang/blink_gc_plugin/Config.h
index 527fe1c3bf3..bd347b89243 100644
--- a/chromium/tools/clang/blink_gc_plugin/Config.h
+++ b/chromium/tools/clang/blink_gc_plugin/Config.h
@@ -20,7 +20,6 @@
extern const char kNewOperatorName[];
extern const char kCreateName[];
extern const char kTraceName[];
-extern const char kTraceWrappersName[];
extern const char kFinalizeName[];
extern const char kTraceAfterDispatchName[];
extern const char kRegisterWeakMembersName[];
@@ -36,8 +35,6 @@ extern const char kIteratorName[];
extern const char kConstReverseIteratorName[];
extern const char kReverseIteratorName[];
-extern const char* kIgnoredTraceWrapperNames[];
-
class Config {
public:
static bool IsMember(const std::string& name) {
@@ -142,10 +139,6 @@ class Config {
IsGCMixinBase(name);
}
- static bool IsTraceWrapperBase(const std::string& name) {
- return name == "TraceWrapperBase";
- }
-
static bool IsIterator(const std::string& name) {
return name == kIteratorName || name == kConstIteratorName ||
name == kReverseIteratorName || name == kConstReverseIteratorName;
@@ -246,15 +239,6 @@ class Config {
return GetTraceMethodType(method) != NOT_TRACE_METHOD;
}
- enum TraceWrappersMethodType {
- NOT_TRACE_WRAPPERS_METHOD,
- TRACE_WRAPPERS_METHOD,
- // TODO(mlippautz): TRACE_WRAPPERS_AFTER_DISPATCH_METHOD
- };
-
- static TraceWrappersMethodType GetTraceWrappersMethodType(
- const clang::FunctionDecl* method);
-
static bool IsTraceWrappersMethod(const clang::FunctionDecl* method);
static bool StartsWith(const std::string& str, const std::string& prefix) {
diff --git a/chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp b/chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp
index 6e704f2221d..82175817e6e 100644
--- a/chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp
+++ b/chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp
@@ -184,8 +184,6 @@ DiagnosticsReporter::DiagnosticsReporter(
diagnostic_.getCustomDiagID(getErrorLevel(), kClassRequiresTraceMethod);
diag_base_requires_tracing_ =
diagnostic_.getCustomDiagID(getErrorLevel(), kBaseRequiresTracing);
- diag_base_requires_wrapper_tracing_ =
- diagnostic_.getCustomDiagID(getErrorLevel(), kBaseRequiresWrapperTracing);
diag_fields_require_tracing_ =
diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing);
diag_fields_improperly_traced_ =
@@ -318,13 +316,6 @@ void DiagnosticsReporter::BaseRequiresTracing(
<< base << derived->record();
}
-void DiagnosticsReporter::BaseRequiresWrapperTracing(RecordInfo* derived,
- CXXMethodDecl* trace,
- CXXRecordDecl* base) {
- ReportDiagnostic(trace->getLocStart(), diag_base_requires_wrapper_tracing_)
- << base << derived->record();
-}
-
void DiagnosticsReporter::FieldsImproperlyTraced(
RecordInfo* info,
CXXMethodDecl* trace) {
diff --git a/chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.h b/chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.h
index 784e4d8cc6b..512874d646e 100644
--- a/chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.h
+++ b/chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.h
@@ -30,9 +30,6 @@ class DiagnosticsReporter {
void BaseRequiresTracing(RecordInfo* derived,
clang::CXXMethodDecl* trace,
clang::CXXRecordDecl* base);
- void BaseRequiresWrapperTracing(RecordInfo* derived,
- clang::CXXMethodDecl* trace,
- clang::CXXRecordDecl* base);
void FieldsImproperlyTraced(RecordInfo* info,
clang::CXXMethodDecl* trace);
void ClassContainsInvalidFields(
@@ -106,7 +103,6 @@ class DiagnosticsReporter {
unsigned diag_class_must_left_mostly_derive_gc_;
unsigned diag_class_requires_trace_method_;
unsigned diag_base_requires_tracing_;
- unsigned diag_base_requires_wrapper_tracing_;
unsigned diag_fields_require_tracing_;
unsigned diag_fields_improperly_traced_;
unsigned diag_class_contains_invalid_fields_;
diff --git a/chromium/tools/clang/blink_gc_plugin/RecordInfo.cpp b/chromium/tools/clang/blink_gc_plugin/RecordInfo.cpp
index 5f4f7ca4808..30a5c745d29 100644
--- a/chromium/tools/clang/blink_gc_plugin/RecordInfo.cpp
+++ b/chromium/tools/clang/blink_gc_plugin/RecordInfo.cpp
@@ -24,9 +24,7 @@ RecordInfo::RecordInfo(CXXRecordDecl* record, RecordCache* cache)
is_declaring_local_trace_(kNotComputed),
is_eagerly_finalized_(kNotComputed),
determined_trace_methods_(false),
- determined_wrapper_trace_methods_(false),
trace_method_(0),
- trace_wrappers_method_(0),
trace_dispatch_method_(0),
finalize_dispatch_method_(0),
is_gc_derived_(false) {}
@@ -78,6 +76,34 @@ bool RecordInfo::IsHeapAllocatedCollection() {
return Config::IsGCCollection(name_);
}
+bool RecordInfo::HasOptionalFinalizer() {
+ if (!IsHeapAllocatedCollection())
+ return false;
+ // Heap collections may have a finalizer but it is optional (i.e. may be
+ // delayed until FinalizeGarbageCollectedObject() gets called), unless there
+ // is an inline buffer. Vector, Deque, and ListHashSet can have an inline
+ // buffer.
+ if (name_ != "Vector" && name_ != "Deque" && name_ != "HeapVector" &&
+ name_ != "HeapDeque")
+ return true;
+ ClassTemplateSpecializationDecl* tmpl =
+ dyn_cast<ClassTemplateSpecializationDecl>(record_);
+ // These collections require template specialization so tmpl should always be
+ // non-null for valid code.
+ if (!tmpl)
+ return false;
+ const TemplateArgumentList& args = tmpl->getTemplateArgs();
+ if (args.size() < 2)
+ return true;
+ TemplateArgument arg = args[1];
+ // The second template argument must be void or 0 so there is no inline
+ // buffer.
+ return (arg.getKind() == TemplateArgument::Type &&
+ arg.getAsType()->isVoidType()) ||
+ (arg.getKind() == TemplateArgument::Integral &&
+ arg.getAsIntegral().getExtValue() == 0);
+}
+
// Test if a record is derived from a garbage collected base.
bool RecordInfo::IsGCDerived() {
// If already computed, return the known result.
@@ -172,14 +198,6 @@ bool RecordInfo::IsGCAllocated() {
return IsGCDerived() || IsHeapAllocatedCollection();
}
-bool RecordInfo::IsTraceWrapperBase() {
- for (const auto& gc_base : gc_base_names_) {
- if (Config::IsTraceWrapperBase(gc_base))
- return true;
- }
- return false;
-}
-
bool RecordInfo::IsEagerlyFinalized() {
if (is_eagerly_finalized_ != kNotComputed)
return is_eagerly_finalized_;
@@ -302,23 +320,6 @@ bool RecordInfo::RequiresTraceMethod() {
return fields_need_tracing_.IsNeeded();
}
-bool RecordInfo::RequiresTraceWrappersMethod() {
- if (IsStackAllocated())
- return false;
-
- if (IsTraceWrapperBase())
- return true;
-
- unsigned bases_with_trace_wrappers = 0;
- for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) {
- if (it->second.NeedsWrapperTracing().IsNeeded())
- ++bases_with_trace_wrappers;
- }
- if (bases_with_trace_wrappers > 1)
- return true;
- return false;
-}
-
// Get the actual tracing method (ie, can be traceAfterDispatch if there is a
// dispatch method).
CXXMethodDecl* RecordInfo::GetTraceMethod() {
@@ -326,11 +327,6 @@ CXXMethodDecl* RecordInfo::GetTraceMethod() {
return trace_method_;
}
-CXXMethodDecl* RecordInfo::GetTraceWrappersMethod() {
- DetermineWrapperTracingMethods();
- return trace_wrappers_method_;
-}
-
// Get the static trace dispatch method.
CXXMethodDecl* RecordInfo::GetTraceDispatchMethod() {
DetermineTracingMethods();
@@ -358,16 +354,6 @@ bool RecordInfo::InheritsTrace() {
return false;
}
-bool RecordInfo::InheritsTraceWrappers() {
- if (GetTraceWrappersMethod())
- return true;
- for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) {
- if (it->second.info()->InheritsTraceWrappers())
- return true;
- }
- return false;
-}
-
CXXMethodDecl* RecordInfo::InheritsNonVirtualTrace() {
if (CXXMethodDecl* trace = GetTraceMethod())
return trace->isVirtual() ? 0 : trace;
@@ -434,11 +420,7 @@ RecordInfo::Bases* RecordInfo::CollectBases() {
TracingStatus status = info->InheritsTrace()
? TracingStatus::Needed()
: TracingStatus::Unneeded();
- TracingStatus wrapper_status = info->InheritsTraceWrappers()
- ? TracingStatus::Needed()
- : TracingStatus::Unneeded();
- bases->push_back(
- std::make_pair(base, BasePoint(spec, info, status, wrapper_status)));
+ bases->push_back(std::make_pair(base, BasePoint(spec, info, status)));
}
return bases;
}
@@ -477,36 +459,6 @@ RecordInfo::Fields* RecordInfo::CollectFields() {
return fields;
}
-void RecordInfo::DetermineWrapperTracingMethods() {
- if (determined_wrapper_trace_methods_)
- return;
- determined_wrapper_trace_methods_ = true;
-
- if (Config::IsTraceWrapperBase(name_))
- return;
-
- CXXMethodDecl* trace_wrappers = nullptr;
- for (Decl* decl : record_->decls()) {
- CXXMethodDecl* method = dyn_cast<CXXMethodDecl>(decl);
- if (!method) {
- if (FunctionTemplateDecl* func_template =
- dyn_cast<FunctionTemplateDecl>(decl))
- method = dyn_cast<CXXMethodDecl>(func_template->getTemplatedDecl());
- }
- if (!method)
- continue;
-
- switch (Config::GetTraceWrappersMethodType(method)) {
- case Config::TRACE_METHOD:
- trace_wrappers = method;
- break;
- case Config::NOT_TRACE_METHOD:
- break;
- }
- }
- trace_wrappers_method_ = trace_wrappers;
-}
-
void RecordInfo::DetermineTracingMethods() {
if (determined_trace_methods_)
return;
@@ -579,6 +531,11 @@ void RecordInfo::DetermineTracingMethods() {
// TODO: Add classes with a finalize() method that specialize FinalizerTrait.
bool RecordInfo::NeedsFinalization() {
if (does_need_finalization_ == kNotComputed) {
+ if (HasOptionalFinalizer()) {
+ does_need_finalization_ = kFalse;
+ return does_need_finalization_;
+ }
+
// Rely on hasNonTrivialDestructor(), but if the only
// identifiable reason for it being true is the presence
// of a safely ignorable class as a direct base,
@@ -635,18 +592,6 @@ TracingStatus RecordInfo::NeedsTracing(Edge::NeedsTracingOption option) {
return fields_need_tracing_;
}
-TracingStatus RecordInfo::NeedsWrapperTracing() {
- if (IsStackAllocated())
- return TracingStatus::Unneeded();
-
- for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) {
- if (it->second.info()->NeedsWrapperTracing().IsNeeded())
- return TracingStatus::Needed();
- }
-
- return TracingStatus::Unneeded();
-}
-
static bool isInStdNamespace(clang::Sema& sema, NamespaceDecl* ns)
{
while (ns) {
diff --git a/chromium/tools/clang/blink_gc_plugin/RecordInfo.h b/chromium/tools/clang/blink_gc_plugin/RecordInfo.h
index 8ec92ec6fc2..3ac082fb5c0 100644
--- a/chromium/tools/clang/blink_gc_plugin/RecordInfo.h
+++ b/chromium/tools/clang/blink_gc_plugin/RecordInfo.h
@@ -23,35 +23,24 @@ class RecordCache;
// A potentially tracable and/or lifetime affecting point in the object graph.
class GraphPoint {
public:
- GraphPoint() : traced_(false), wrapper_traced_(false) {}
+ GraphPoint() : traced_(false) {}
virtual ~GraphPoint() {}
void MarkTraced() { traced_ = true; }
- void MarkWrapperTraced() { wrapper_traced_ = true; }
bool IsProperlyTraced() { return traced_ || !NeedsTracing().IsNeeded(); }
bool IsInproperlyTraced() { return traced_ && NeedsTracing().IsIllegal(); }
- bool IsProperlyWrapperTraced() {
- return wrapper_traced_ || !NeedsWrapperTracing().IsNeeded();
- }
virtual const TracingStatus NeedsTracing() = 0;
- virtual const TracingStatus NeedsWrapperTracing() = 0;
private:
bool traced_;
- bool wrapper_traced_;
};
class BasePoint : public GraphPoint {
public:
BasePoint(const clang::CXXBaseSpecifier& spec,
RecordInfo* info,
- const TracingStatus& status,
- const TracingStatus& wrapper_status)
- : spec_(spec),
- info_(info),
- status_(status),
- wrapper_status_(wrapper_status) {}
+ const TracingStatus& status)
+ : spec_(spec), info_(info), status_(status) {}
const TracingStatus NeedsTracing() { return status_; }
- const TracingStatus NeedsWrapperTracing() { return wrapper_status_; }
const clang::CXXBaseSpecifier& spec() { return spec_; }
RecordInfo* info() { return info_; }
@@ -59,7 +48,6 @@ class BasePoint : public GraphPoint {
const clang::CXXBaseSpecifier& spec_;
RecordInfo* info_;
TracingStatus status_;
- TracingStatus wrapper_status_;
};
class FieldPoint : public GraphPoint {
@@ -69,7 +57,6 @@ class FieldPoint : public GraphPoint {
const TracingStatus NeedsTracing() {
return edge_->NeedsTracing(Edge::kRecursive);
}
- const TracingStatus NeedsWrapperTracing() { return TracingStatus::Illegal(); }
clang::FieldDecl* field() { return field_; }
Edge* edge() { return edge_; }
@@ -113,7 +100,6 @@ class RecordInfo {
bool IsGCAllocated();
bool IsGCFinalized();
bool IsGCMixin();
- bool IsTraceWrapperBase();
bool IsStackAllocated();
bool IsNonNewable();
bool IsOnlyPlacementNewable();
@@ -125,11 +111,9 @@ class RecordInfo {
bool RequiresTraceMethod();
bool NeedsFinalization();
- bool RequiresTraceWrappersMethod();
bool DeclaresGCMixinMethods();
bool DeclaresLocalTraceMethod();
TracingStatus NeedsTracing(Edge::NeedsTracingOption);
- TracingStatus NeedsWrapperTracing();
clang::CXXMethodDecl* InheritsNonVirtualTrace();
bool IsConsideredAbstract();
@@ -143,13 +127,13 @@ class RecordInfo {
Fields* CollectFields();
Bases* CollectBases();
void DetermineTracingMethods();
- void DetermineWrapperTracingMethods();
bool InheritsTrace();
- bool InheritsTraceWrappers();
Edge* CreateEdge(const clang::Type* type);
Edge* CreateEdgeFromOriginalType(const clang::Type* type);
+ bool HasOptionalFinalizer();
+
RecordCache* cache_;
clang::CXXRecordDecl* record_;
const std::string name_;
@@ -167,9 +151,7 @@ class RecordInfo {
CachedBool is_eagerly_finalized_;
bool determined_trace_methods_;
- bool determined_wrapper_trace_methods_;
clang::CXXMethodDecl* trace_method_;
- clang::CXXMethodDecl* trace_wrappers_method_;
clang::CXXMethodDecl* trace_dispatch_method_;
clang::CXXMethodDecl* finalize_dispatch_method_;
diff --git a/chromium/tools/clang/plugins/OWNERS b/chromium/tools/clang/plugins/OWNERS
index 4733a4f06bf..859c2c608c3 100644
--- a/chromium/tools/clang/plugins/OWNERS
+++ b/chromium/tools/clang/plugins/OWNERS
@@ -1 +1 @@
-erg@chromium.org
+dcheng@chromium.org
diff --git a/chromium/tools/clang/pylib/clang/compile_db.py b/chromium/tools/clang/pylib/clang/compile_db.py
index bbf5e3c30e9..4dbe39cd15d 100755
--- a/chromium/tools/clang/pylib/clang/compile_db.py
+++ b/chromium/tools/clang/pylib/clang/compile_db.py
@@ -17,7 +17,7 @@ _debugging = False
def _ProcessEntry(entry):
"""Transforms one entry in the compile database to be clang-tool friendly."""
- split_command = shlex.split(entry['command'])
+ split_command = shlex.split(entry['command'], posix=(sys.platform != 'win32'))
# Drop gomacc.exe from the front, if present.
if split_command[0].endswith('gomacc.exe'):
@@ -84,11 +84,12 @@ def GetNinjaPath():
# FIXME: This really should be a build target, rather than generated at runtime.
-def GenerateWithNinja(path):
+def GenerateWithNinja(path, targets=[]):
"""Generates a compile database using ninja.
Args:
path: The build directory to generate a compile database for.
+ targets: Additional targets to pass to ninja.
Returns:
List of the contents of the compile database.
@@ -96,9 +97,9 @@ def GenerateWithNinja(path):
# TODO(dcheng): Ensure that clang is enabled somehow.
# First, generate the compile database.
- json_compile_db = subprocess.check_output([
- GetNinjaPath(), '-C', path, '-t', 'compdb', 'cc', 'cxx', 'objc',
- 'objcxx'])
+ json_compile_db = subprocess.check_output(
+ [GetNinjaPath(), '-C', path] + targets +
+ ['-t', 'compdb', 'cc', 'cxx', 'objc', 'objcxx'])
return json.loads(json_compile_db)
diff --git a/chromium/tools/clang/scripts/generate_compdb.py b/chromium/tools/clang/scripts/generate_compdb.py
index bf56712bd4f..73780936c83 100755
--- a/chromium/tools/clang/scripts/generate_compdb.py
+++ b/chromium/tools/clang/scripts/generate_compdb.py
@@ -28,9 +28,24 @@ def main(argv):
'-p',
required=True,
help='Path to build directory')
+ parser.add_argument(
+ 'targets',
+ nargs='*',
+ help='Additional targets to pass to ninja')
+ parser.add_argument(
+ '-o',
+ help='File to write the compilation database to. Defaults to stdout')
+
args = parser.parse_args()
- print json.dumps(compile_db.GenerateWithNinja(args.p))
+ compdb_text = json.dumps(
+ compile_db.ProcessCompileDatabaseIfNeeded(
+ compile_db.GenerateWithNinja(args.p, args.targets)))
+ if args.o is None:
+ print(compdb_text)
+ else:
+ with open(args.o, 'w') as f:
+ f.write(compdb_text)
if __name__ == '__main__':
diff --git a/chromium/tools/clang/scripts/package.py b/chromium/tools/clang/scripts/package.py
index bc9f4a0d5ca..5abba310079 100755
--- a/chromium/tools/clang/scripts/package.py
+++ b/chromium/tools/clang/scripts/package.py
@@ -352,7 +352,8 @@ def main():
objdumpdir = 'llvmobjdump-' + stamp
shutil.rmtree(objdumpdir, ignore_errors=True)
os.makedirs(os.path.join(objdumpdir, 'bin'))
- for filename in ['llvm-cxxfilt', 'llvm-nm', 'llvm-objdump', 'llvm-readobj']:
+ for filename in ['llvm-bcanalyzer', 'llvm-cxxfilt', 'llvm-nm', 'llvm-objdump',
+ 'llvm-readobj']:
shutil.copy(os.path.join(LLVM_RELEASE_DIR, 'bin', filename + exe_ext),
os.path.join(objdumpdir, 'bin'))
llvmobjdump_stamp_file_base = 'llvmobjdump_build_revision'
diff --git a/chromium/tools/clang/scripts/run_tool.py b/chromium/tools/clang/scripts/run_tool.py
index 388f2416fc3..82ae64def61 100755
--- a/chromium/tools/clang/scripts/run_tool.py
+++ b/chromium/tools/clang/scripts/run_tool.py
@@ -82,6 +82,7 @@ def _PruneGitFiles(git_files, paths):
"""
if not git_files:
return []
+ git_files.sort()
pruned_list = []
git_index = 0
for path in sorted(paths):
@@ -215,6 +216,10 @@ def _ExecuteTool(toolname, tool_args, build_directory, compdb_entry):
# passed to the tool twice - once directly and once via
# the compile args.
if a != compdb_entry.filename
+ # /showIncludes is used by Ninja to track header file dependencies on
+ # Windows. We don't need to do this here, and it results in lots of spam
+ # and a massive log file, so we strip it.
+ and a != '/showIncludes'
])
# shlex.split escapes double qoutes in non-Posix mode, so we need to strip
@@ -294,9 +299,12 @@ class _CompilerDispatcher(object):
sys.stderr.write('\n')
done_count = self.__success_count + self.__failed_count
percentage = (float(done_count) / len(self.__compdb_entries)) * 100
- sys.stderr.write(
- 'Processed %d files with %s tool (%d failures) [%.2f%%]\r' %
- (done_count, self.__toolname, self.__failed_count, percentage))
+ # Only output progress for every 100th entry, to make log files easier to
+ # inspect.
+ if done_count % 100 == 0 or done_count == len(self.__compdb_entries):
+ sys.stderr.write(
+ 'Processed %d files with %s tool (%d failures) [%.2f%%]\r' %
+ (done_count, self.__toolname, self.__failed_count, percentage))
def main():
diff --git a/chromium/tools/clang/scripts/update.py b/chromium/tools/clang/scripts/update.py
index 1dffa88154b..f69d2eb8915 100755
--- a/chromium/tools/clang/scripts/update.py
+++ b/chromium/tools/clang/scripts/update.py
@@ -27,7 +27,7 @@ import zipfile
# Do NOT CHANGE this if you don't know what you're doing -- see
# https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang.md
# Reverting problematic clang rolls is safe, though.
-CLANG_REVISION = '332838'
+CLANG_REVISION = '337439'
use_head_revision = bool(os.environ.get('LLVM_FORCE_HEAD_REVISION', '0')
in ('1', 'YES'))
@@ -80,12 +80,6 @@ LLVM_REPO_URL='https://llvm.org/svn/llvm-project'
if 'LLVM_REPO_URL' in os.environ:
LLVM_REPO_URL = os.environ['LLVM_REPO_URL']
-# Bump after VC updates.
-DIA_DLL = {
- '2013': 'msdia120.dll',
- '2015': 'msdia140.dll',
- '2017': 'msdia140.dll',
-}
def DownloadUrl(url, output_file):
@@ -204,7 +198,8 @@ def RunCommand(command, msvc_arch=None, env=None, fail_hard=True):
shell with the msvc tools for that architecture."""
if msvc_arch and sys.platform == 'win32':
- command = GetVSVersion().SetupScript(msvc_arch) + ['&&'] + command
+ command = [os.path.join(GetWinSDKDir(), 'bin', 'SetEnv.cmd'),
+ "/" + msvc_arch, '&&'] + command
# https://docs.python.org/2/library/subprocess.html:
# "On Unix with shell=True [...] if args is a sequence, the first item
@@ -370,31 +365,45 @@ def AddGnuWinToPath():
os.environ['PATH'] = gnuwin_dir + os.pathsep + os.environ.get('PATH', '')
-vs_version = None
-def GetVSVersion():
- global vs_version
- if vs_version:
- return vs_version
+win_sdk_dir = None
+dia_dll = None
+def GetWinSDKDir():
+ """Get the location of the current SDK. Sets dia_dll as a side-effect."""
+ global win_sdk_dir
+ global dia_dll
+ if win_sdk_dir:
+ return win_sdk_dir
+
+ # Bump after VC updates.
+ DIA_DLL = {
+ '2013': 'msdia120.dll',
+ '2015': 'msdia140.dll',
+ '2017': 'msdia140.dll',
+ }
+
+ # Don't let vs_toolchain overwrite our environment.
+ environ_bak = os.environ
- # Try using the toolchain in depot_tools.
- # This sets environment variables used by SelectVisualStudioVersion below.
sys.path.append(os.path.join(CHROMIUM_DIR, 'build'))
import vs_toolchain
- vs_toolchain.SetEnvironmentAndGetRuntimeDllDirs()
+ win_sdk_dir = vs_toolchain.SetEnvironmentAndGetSDKDir()
+ msvs_version = vs_toolchain.GetVisualStudioVersion()
+
+ if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))):
+ dia_path = os.path.join(win_sdk_dir, '..', 'DIA SDK', 'bin', 'amd64')
+ else:
+ vs_path = vs_toolchain.DetectVisualStudioPath()
+ dia_path = os.path.join(vs_path, 'DIA SDK', 'bin', 'amd64')
+
+ dia_dll = os.path.join(dia_path, DIA_DLL[msvs_version])
- # Use gyp to find the MSVS installation, either in depot_tools as per above,
- # or a system-wide installation otherwise.
- sys.path.append(os.path.join(CHROMIUM_DIR, 'tools', 'gyp', 'pylib'))
- import gyp.MSVSVersion
- vs_version = gyp.MSVSVersion.SelectVisualStudioVersion(
- vs_toolchain.GetVisualStudioVersion())
- return vs_version
+ os.environ = environ_bak
+ return win_sdk_dir
def CopyDiaDllTo(target_dir):
# This script always wants to use the 64-bit msdia*.dll.
- dia_path = os.path.join(GetVSVersion().Path(), 'DIA SDK', 'bin', 'amd64')
- dia_dll = os.path.join(dia_path, DIA_DLL[GetVSVersion().ShortName()])
+ GetWinSDKDir()
CopyFile(dia_dll, target_dir)
diff --git a/chromium/tools/clang/translation_unit/TranslationUnitGenerator.cpp b/chromium/tools/clang/translation_unit/TranslationUnitGenerator.cpp
index be61238bf46..579e64747b5 100644
--- a/chromium/tools/clang/translation_unit/TranslationUnitGenerator.cpp
+++ b/chromium/tools/clang/translation_unit/TranslationUnitGenerator.cpp
@@ -29,11 +29,15 @@
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
using clang::HeaderSearchOptions;
using clang::tooling::CommonOptionsParser;
+using llvm::sys::fs::real_path;
+using llvm::SmallVector;
using std::set;
using std::stack;
using std::string;
@@ -203,7 +207,13 @@ string IncludeFinderPPCallbacks::DoubleSlashSystemHeaders(
void IncludeFinderPPCallbacks::EndOfMainFile() {
const clang::FileEntry* main_file =
source_manager_->getFileEntryForID(source_manager_->getMainFileID());
- assert(*main_source_file_ == main_file->getName());
+
+ SmallVector<char, 100> main_source_file_real_path;
+ SmallVector<char, 100> main_file_name_real_path;
+ assert(!real_path(*main_source_file_, main_source_file_real_path));
+ assert(!real_path(main_file->getName(), main_file_name_real_path));
+ assert(main_source_file_real_path == main_file_name_real_path);
+
AddFile(main_file->getName());
}
diff --git a/chromium/tools/clang/translation_unit/test_files/compile_commands.json.template b/chromium/tools/clang/translation_unit/test_files/compile_commands.json.template
index f7710877fb1..9fef4cf92e6 100644
--- a/chromium/tools/clang/translation_unit/test_files/compile_commands.json.template
+++ b/chromium/tools/clang/translation_unit/test_files/compile_commands.json.template
@@ -8,5 +8,10 @@
"directory": "$test_files_dir",
"command": "clang++ -fsyntax-only -std=c++11 --sysroot ./sysroot -c test_relative_sysroot.cc",
"file": "test_relative_sysroot.cc"
+ },
+ {
+ "directory": "$test_files_dir",
+ "command": "clang++ -I.",
+ "file": "includes_self.cc"
}
-] \ No newline at end of file
+]
diff --git a/chromium/tools/clang/translation_unit/test_files/includes_self.cc b/chromium/tools/clang/translation_unit/test_files/includes_self.cc
new file mode 100644
index 00000000000..fbacda4b668
--- /dev/null
+++ b/chromium/tools/clang/translation_unit/test_files/includes_self.cc
@@ -0,0 +1,6 @@
+#ifndef GUARD
+#define GUARD
+
+#include "includes_self.cc"
+
+#endif
diff --git a/chromium/tools/clang/translation_unit/test_files/includes_self.cc.filepaths.expected b/chromium/tools/clang/translation_unit/test_files/includes_self.cc.filepaths.expected
new file mode 100644
index 00000000000..45527860d54
--- /dev/null
+++ b/chromium/tools/clang/translation_unit/test_files/includes_self.cc.filepaths.expected
@@ -0,0 +1 @@
+includes_self.cc
diff --git a/chromium/tools/clang/translation_unit/test_files/test.cc.filepaths.expected b/chromium/tools/clang/translation_unit/test_files/test.cc.filepaths.expected
index adb9e6514e9..90693537239 100644
--- a/chromium/tools/clang/translation_unit/test_files/test.cc.filepaths.expected
+++ b/chromium/tools/clang/translation_unit/test_files/test.cc.filepaths.expected
@@ -1,4 +1,4 @@
-./binomial.h
-./test.h
//bits/wchar.h
+binomial.h
test.cc
+test.h
diff --git a/chromium/tools/clang/translation_unit/test_translation_unit.py b/chromium/tools/clang/translation_unit/test_translation_unit.py
index 0482a7873f6..426aa7b65e2 100755
--- a/chromium/tools/clang/translation_unit/test_translation_unit.py
+++ b/chromium/tools/clang/translation_unit/test_translation_unit.py
@@ -47,7 +47,9 @@ def main():
args = ['python',
os.path.join(tools_clang_scripts_directory, 'run_tool.py'),
+ '--tool',
'translation_unit',
+ '-p',
test_directory_for_tool]
args.extend(source_files)
run_tool = subprocess.Popen(args, stdout=subprocess.PIPE)
diff --git a/chromium/tools/code_coverage/test_suite.txt b/chromium/tools/code_coverage/test_suite.txt
index 9e62e1738db..abe7e5788d1 100644
--- a/chromium/tools/code_coverage/test_suite.txt
+++ b/chromium/tools/code_coverage/test_suite.txt
@@ -23,6 +23,9 @@ compositor_unittests
content_browsertests
content_unittests
courgette_unittests
+crashpad_tests
+cronet_tests
+cronet_unittests
crypto_unittests
dbus_unittests
device_unittests
@@ -35,7 +38,6 @@ gcm_unit_tests
gfx_unittests
gin_unittests
gl_unittests
-gn_unittests
google_apis_unittests
gpu_unittests
headless_browsertests
@@ -43,14 +45,17 @@ headless_unittests
interactive_ui_tests
ipc_tests
jingle_unittests
-keyboard_unittests
+latency_unittests
leveldb_service_unittests
libjingle_xmpp_unittests
media_blink_unittests
media_mojo_unittests
media_service_unittests
media_unittests
+message_center_unittests
midi_unittests
+mojo_unittests
+nacl_helper_nonsfi_unittests
nacl_loader_unittests
native_theme_unittests
net_unittests
diff --git a/chromium/tools/cygprofile/BUILD.gn b/chromium/tools/cygprofile/BUILD.gn
deleted file mode 100644
index 037c31e41b7..00000000000
--- a/chromium/tools/cygprofile/BUILD.gn
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/android/config.gni")
-
-if (target_cpu == "arm") {
- static_library("cygprofile") {
- sources = [
- "delayed_dumper.cc",
- "lightweight_cygprofile.cc",
- "lightweight_cygprofile.h",
- ]
- deps = [
- "//base",
- ]
- }
-
- executable("cygprofile_perftests") {
- testonly = true
-
- sources = [
- "lightweight_cygprofile_perftest.cc",
- ]
-
- deps = [
- ":cygprofile",
- "//base",
- "//testing/gtest",
- "//testing/perf",
- ]
- }
-}
diff --git a/chromium/tools/cygprofile/delayed_dumper.cc b/chromium/tools/cygprofile/delayed_dumper.cc
deleted file mode 100644
index 513b6a53a3f..00000000000
--- a/chromium/tools/cygprofile/delayed_dumper.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <time.h>
-#include <unistd.h>
-
-#include <thread>
-
-#include "base/android/library_loader/anchor_functions.h"
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "tools/cygprofile/lightweight_cygprofile.h"
-
-#if !defined(ARCH_CPU_ARMEL)
-#error Only supported on ARM.
-#endif // !defined(ARCH_CPU_ARMEL)
-
-namespace cygprofile {
-namespace {
-
-// Disables the recording of addresses after |kDelayInSeconds| and dumps the
-// result to a file.
-class DelayedDumper {
- public:
- DelayedDumper() {
- // Not using base::TimeTicks() to not call too many base:: symbol that would
- // pollute the reached symbols dumps.
- struct timespec ts;
- if (clock_gettime(CLOCK_MONOTONIC, &ts))
- PLOG(FATAL) << "clock_gettime.";
- uint64_t start_ns_since_epoch =
- static_cast<uint64_t>(ts.tv_sec) * 1000 * 1000 * 1000 + ts.tv_nsec;
- int pid = getpid();
-
- std::thread([pid, start_ns_since_epoch]() {
- sleep(kInitialDelayInSeconds);
- while (!SwitchToNextPhaseOrDump(pid, start_ns_since_epoch))
- sleep(kDelayInSeconds);
- })
- .detach();
- }
-
- static constexpr int kDelayInSeconds = 30;
- static constexpr int kInitialDelayInSeconds =
- kPhases == 1 ? kDelayInSeconds : 5;
-};
-
-// Static initializer on purpose. Will disable instrumentation after
-// |kDelayInSeconds|.
-DelayedDumper g_dump_later;
-
-} // namespace
-} // namespace cygprofile
diff --git a/chromium/tools/cygprofile/lightweight_cygprofile.cc b/chromium/tools/cygprofile/lightweight_cygprofile.cc
deleted file mode 100644
index f872f8661c2..00000000000
--- a/chromium/tools/cygprofile/lightweight_cygprofile.cc
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/cygprofile/lightweight_cygprofile.h"
-
-#include <atomic>
-#include <cstdio>
-#include <cstring>
-#include <string>
-#include <vector>
-
-#include "base/android/library_loader/anchor_functions.h"
-#include "base/files/file.h"
-#include "base/format_macros.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/stringprintf.h"
-#include "build/build_config.h"
-
-#if !defined(ARCH_CPU_ARMEL)
-#error Only supported on ARM.
-#endif // !defined(ARCH_CPU_ARMEL)
-
-// Must be applied to all functions within this file.
-#define NO_INSTRUMENT_FUNCTION __attribute__((no_instrument_function))
-
-namespace cygprofile {
-namespace {
-
-// These are large overestimates, which is not an issue, as the data is
-// allocated in .bss, and on linux doesn't take any actual memory when it's not
-// touched.
-constexpr size_t kBitfieldSize = 1 << 22;
-constexpr size_t kMaxTextSizeInBytes = kBitfieldSize * (4 * 32);
-constexpr size_t kMaxElements = 1 << 20;
-
-// Data required to log reached offsets.
-struct LogData {
- std::atomic<uint32_t> offsets[kBitfieldSize];
- std::atomic<size_t> ordered_offsets[kMaxElements];
- std::atomic<size_t> index;
-};
-
-LogData g_data[kPhases];
-std::atomic<int> g_data_index;
-
-// |RecordAddress()| adds an element to a concurrent bitset and to a concurrent
-// append-only list of offsets.
-//
-// Ordering:
-// Two consecutive calls to |RecordAddress()| from the same thread will be
-// ordered in the same way in the result, as written by
-// |StopAndDumpToFile()|. The result will contain exactly one instance of each
-// unique offset relative to |kStartOfText| passed to |RecordAddress()|.
-//
-// Implementation:
-// The "set" part is implemented with a bitfield, |g_offset|. The insertion
-// order is recorded in |g_ordered_offsets|.
-// This is not a class to make sure there isn't a static constructor, as it
-// would cause issue with an instrumented static constructor calling this code.
-//
-// Limitations:
-// - Only records offsets to addresses between |kStartOfText| and |kEndOfText|.
-// - Capacity of the set is limited by |kMaxElements|.
-// - Some insertions at the end of collection may be lost.
-
-// Records that |address| has been reached, if recording is enabled.
-// To avoid infinite recursion, this *must* *never* call any instrumented
-// function, unless |Disable()| is called first.
-template <bool for_testing>
-__attribute__((always_inline, no_instrument_function)) void RecordAddress(
- size_t address) {
- int index = g_data_index.load(std::memory_order_relaxed);
- if (index >= kPhases)
- return;
-
- const size_t start =
- for_testing ? kStartOfTextForTesting : base::android::kStartOfText;
- const size_t end =
- for_testing ? kEndOfTextForTesting : base::android::kEndOfText;
- if (UNLIKELY(address < start || address > end)) {
- Disable();
- // If the start and end addresses are set incorrectly, this code path is
- // likely happening during a static initializer. Logging at this time is
- // prone to deadlock. By crashing immediately we at least have a chance to
- // get a stack trace from the system to give some clue about the nature of
- // the problem.
- IMMEDIATE_CRASH();
- }
-
- size_t offset = address - start;
- static_assert(sizeof(int) == 4,
- "Collection and processing code assumes that sizeof(int) == 4");
- size_t offset_index = offset / 4;
-
- auto* offsets = g_data[index].offsets;
- // Atomically set the corresponding bit in the array.
- std::atomic<uint32_t>* element = offsets + (offset_index / 32);
- // First, a racy check. This saves a CAS if the bit is already set, and
- // allows the cache line to remain shared acoss CPUs in this case.
- uint32_t value = element->load(std::memory_order_relaxed);
- uint32_t mask = 1 << (offset_index % 32);
- if (value & mask)
- return;
-
- auto before = element->fetch_or(mask, std::memory_order_relaxed);
- if (before & mask)
- return;
-
- // We were the first one to set the element, record it in the ordered
- // elements list.
- // Use relaxed ordering, as the value is not published, or used for
- // synchronization.
- auto* ordered_offsets = g_data[index].ordered_offsets;
- auto& ordered_offsets_index = g_data[index].index;
- size_t insertion_index =
- ordered_offsets_index.fetch_add(1, std::memory_order_relaxed);
- if (UNLIKELY(insertion_index >= kMaxElements)) {
- Disable();
- LOG(FATAL) << "Too many reached offsets";
- }
- ordered_offsets[insertion_index].store(offset, std::memory_order_relaxed);
-}
-
-NO_INSTRUMENT_FUNCTION void DumpToFile(const base::FilePath& path,
- const LogData& data) {
- auto file =
- base::File(path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
- if (!file.IsValid()) {
- PLOG(ERROR) << "Could not open " << path;
- return;
- }
-
- size_t count = data.index - 1;
- for (size_t i = 0; i < count; i++) {
- // |g_ordered_offsets| is initialized to 0, so a 0 in the middle of it
- // indicates a case where the index was incremented, but the write is not
- // visible in this thread yet. Safe to skip, also because the function at
- // the start of text is never called.
- auto offset = data.ordered_offsets[i].load(std::memory_order_relaxed);
- if (!offset)
- continue;
- auto offset_str = base::StringPrintf("%" PRIuS "\n", offset);
- file.WriteAtCurrentPos(offset_str.c_str(),
- static_cast<int>(offset_str.size()));
- }
-}
-
-// Stops recording, and outputs the data to |path|.
-NO_INSTRUMENT_FUNCTION void StopAndDumpToFile(int pid,
- uint64_t start_ns_since_epoch) {
- Disable();
-
- for (int phase = 0; phase < kPhases; phase++) {
- auto path = base::StringPrintf(
- "/data/local/tmp/chrome/cyglog/"
- "cygprofile-instrumented-code-hitmap-%d-%" PRIu64 ".txt_%d",
- pid, start_ns_since_epoch, phase);
- DumpToFile(base::FilePath(path), g_data[phase]);
- }
-}
-
-} // namespace
-
-NO_INSTRUMENT_FUNCTION void Disable() {
- g_data_index.store(kPhases, std::memory_order_relaxed);
- std::atomic_thread_fence(std::memory_order_seq_cst);
-}
-
-NO_INSTRUMENT_FUNCTION void SanityChecks() {
- CHECK_LT(base::android::kEndOfText - base::android::kStartOfText,
- kMaxTextSizeInBytes);
- CHECK(base::android::IsOrderingSane());
-}
-
-NO_INSTRUMENT_FUNCTION bool SwitchToNextPhaseOrDump(
- int pid,
- uint64_t start_ns_since_epoch) {
- int before = g_data_index.fetch_add(1, std::memory_order_relaxed);
- if (before + 1 == kPhases) {
- StopAndDumpToFile(pid, start_ns_since_epoch);
- return true;
- }
- return false;
-}
-
-NO_INSTRUMENT_FUNCTION void ResetForTesting() {
- Disable();
- g_data_index = 0;
- for (int i = 0; i < kPhases; i++) {
- memset(reinterpret_cast<uint32_t*>(g_data[i].offsets), 0,
- sizeof(uint32_t) * kBitfieldSize);
- memset(reinterpret_cast<uint32_t*>(g_data[i].ordered_offsets), 0,
- sizeof(uint32_t) * kMaxElements);
- g_data[i].index.store(0);
- }
-}
-
-NO_INSTRUMENT_FUNCTION void RecordAddressForTesting(size_t address) {
- return RecordAddress<true>(address);
-}
-
-NO_INSTRUMENT_FUNCTION std::vector<size_t> GetOrderedOffsetsForTesting() {
- std::vector<size_t> result;
- size_t max_index = g_data[0].index.load(std::memory_order_relaxed);
- for (size_t i = 0; i < max_index; ++i) {
- auto value = g_data[0].ordered_offsets[i].load(std::memory_order_relaxed);
- if (value)
- result.push_back(value);
- }
- return result;
-}
-
-} // namespace cygprofile
-
-extern "C" {
-
-NO_INSTRUMENT_FUNCTION void __cyg_profile_func_enter_bare() {
- cygprofile::RecordAddress<false>(
- reinterpret_cast<size_t>(__builtin_return_address(0)));
-}
-
-} // extern "C"
diff --git a/chromium/tools/cygprofile/lightweight_cygprofile.h b/chromium/tools/cygprofile/lightweight_cygprofile.h
deleted file mode 100644
index 2cabd2af685..00000000000
--- a/chromium/tools/cygprofile/lightweight_cygprofile.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_CYGPROFILE_LIGHTWEIGHT_CYGPROFILE_H_
-#define TOOLS_CYGPROFILE_LIGHTWEIGHT_CYGPROFILE_H_
-
-#include <cstdint>
-#include <vector>
-
-namespace cygprofile {
-constexpr int kPhases = 1;
-constexpr size_t kStartOfTextForTesting = 1000;
-constexpr size_t kEndOfTextForTesting = kStartOfTextForTesting + 1000 * 1000;
-
-// Stop recording.
-void Disable();
-
-// CHECK()s that the offsets are correctly set up.
-void SanityChecks();
-
-// Switches to the next recording phase. If called from the last phase, dumps
-// the data to disk, and returns |true|. |pid| is the current process pid, and
-// |start_ns_since_epoch| the process start timestamp.
-bool SwitchToNextPhaseOrDump(int pid, uint64_t start_ns_since_epoch);
-
-// Record an |address|, if recording is enabled. Only for testing.
-void RecordAddressForTesting(size_t address);
-
-// Resets the state. Only for testing.
-void ResetForTesting();
-
-// Returns an ordered list of reached offsets. Only for testing.
-std::vector<size_t> GetOrderedOffsetsForTesting();
-} // namespace cygprofile
-
-#endif // TOOLS_CYGPROFILE_LIGHTWEIGHT_CYGPROFILE_H_
diff --git a/chromium/tools/cygprofile/lightweight_cygprofile_perftest.cc b/chromium/tools/cygprofile/lightweight_cygprofile_perftest.cc
deleted file mode 100644
index 689dd609c93..00000000000
--- a/chromium/tools/cygprofile/lightweight_cygprofile_perftest.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/cygprofile/lightweight_cygprofile.h"
-
-#include <thread>
-
-#include "base/android/library_loader/anchor_functions.h"
-#include "base/strings/stringprintf.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/perf/perf_test.h"
-
-namespace cygprofile {
-
-namespace {
-
-// Records |addresses_count| distinct addresses |iterations| times, in
-// |threads|.
-void RunBenchmark(int iterations, int addresses_count, int threads) {
- auto iterate = [iterations, addresses_count]() {
- for (int i = 0; i < iterations; i++) {
- for (size_t addr = kStartOfTextForTesting;
- addr < static_cast<size_t>(addresses_count); addr += sizeof(int)) {
- RecordAddressForTesting(addr);
- }
- }
- };
- if (threads != 1) {
- for (int i = 0; i < threads - 1; ++i)
- std::thread(iterate).detach();
- }
- auto tick = base::TimeTicks::Now();
- iterate();
- auto tock = base::TimeTicks::Now();
- double nanos = static_cast<double>((tock - tick).InNanoseconds());
- auto ns_per_call =
- nanos / (iterations * static_cast<double>(addresses_count));
- auto modifier =
- base::StringPrintf("_%d_%d_%d", iterations, addresses_count, threads);
- perf_test::PrintResult("RecordAddressCostPerCall", modifier, "", ns_per_call,
- "ns", true);
-}
-
-} // namespace
-
-class LightweightCygprofileTest : public ::testing::Test {
- protected:
- void SetUp() override { ResetForTesting(); }
-};
-
-TEST_F(LightweightCygprofileTest, RecordOffset) {
- size_t first = 1234, second = 1456;
- RecordAddressForTesting(first);
- RecordAddressForTesting(second);
- RecordAddressForTesting(first); // No duplicates.
- RecordAddressForTesting(first + 1); // 4 bytes granularity.
- Disable();
-
- auto reached = GetOrderedOffsetsForTesting();
- EXPECT_EQ(2UL, reached.size());
- EXPECT_EQ(first - kStartOfTextForTesting, reached[0]);
- EXPECT_EQ(second - kStartOfTextForTesting, reached[1]);
-}
-
-TEST_F(LightweightCygprofileTest, RecordingStops) {
- size_t first = 1234, second = 1456, third = 1789;
- RecordAddressForTesting(first);
- RecordAddressForTesting(second);
- Disable();
- RecordAddressForTesting(third);
-
- auto reached = GetOrderedOffsetsForTesting();
- ASSERT_EQ(2UL, reached.size());
- ASSERT_EQ(first - kStartOfTextForTesting, reached[0]);
- ASSERT_EQ(second - kStartOfTextForTesting, reached[1]);
-}
-
-TEST_F(LightweightCygprofileTest, OutOfBounds) {
- EXPECT_DEATH(RecordAddressForTesting(kEndOfTextForTesting + 100), "");
- EXPECT_DEATH(RecordAddressForTesting(kStartOfTextForTesting - 100), "");
-}
-
-TEST(LightweightCygprofilePerfTest, RecordAddress_10_10000) {
- RunBenchmark(10, 10000, 1);
-}
-
-TEST(LightweightCygprofilePerfTest, RecordAddress_100_10000) {
- RunBenchmark(100, 10000, 1);
-}
-
-TEST(LightweightCygprofilePerfTest, RecordAddress_10_100000) {
- RunBenchmark(10, 100000, 1);
-}
-
-TEST(LightweightCygprofilePerfTest, RecordAddress_100_100000) {
- RunBenchmark(100, 100000, 1);
-}
-
-TEST(LightweightCygprofilePerfTest, RecordAddress_1000_100000_2) {
- RunBenchmark(1000, 100000, 2);
-}
-
-TEST(LightweightCygprofilePerfTest, RecordAddress_1000_100000_3) {
- RunBenchmark(1000, 100000, 3);
-}
-
-TEST(LightweightCygprofilePerfTest, RecordAddress_1000_100000_4) {
- RunBenchmark(1000, 100000, 4);
-}
-
-TEST(LightweightCygprofilePerfTest, RecordAddress_1000_100000_6) {
- RunBenchmark(1000, 100000, 6);
-}
-
-} // namespace cygprofile
-
-// Custom runner implementation since base's one requires JNI on Android.
-int main(int argc, char** argv) {
- testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/chromium/tools/cygprofile/orderfile_generator_backend.py b/chromium/tools/cygprofile/orderfile_generator_backend.py
index 73232066887..c2a2bfd856e 100755
--- a/chromium/tools/cygprofile/orderfile_generator_backend.py
+++ b/chromium/tools/cygprofile/orderfile_generator_backend.py
@@ -26,6 +26,7 @@ import sys
import tempfile
import time
+import cyglog_to_orderfile
import cygprofile_utils
import patch_orderfile
import process_profiles
@@ -429,7 +430,7 @@ class OrderfileGenerator(object):
if options.profile:
output_directory = os.path.join(self._instrumented_out_dir, 'Release')
- host_cyglog_dir = os.path.join(output_directory, 'cyglog_data')
+ host_profile_dir = os.path.join(output_directory, 'profile_data')
urls = [profile_android_startup.AndroidProfileTool.TEST_URL]
use_wpr = True
simulate_user = False
@@ -437,7 +438,8 @@ class OrderfileGenerator(object):
use_wpr = not options.no_wpr
simulate_user = options.simulate_user
self._profiler = profile_android_startup.AndroidProfileTool(
- output_directory, host_cyglog_dir, use_wpr, urls, simulate_user)
+ output_directory, host_profile_dir, use_wpr, urls, simulate_user,
+ device=options.device)
self._output_data = {}
self._step_recorder = StepRecorder(options.buildbot)
@@ -479,7 +481,7 @@ class OrderfileGenerator(object):
files = self._profiler.CollectProfile(
self._compiler.chrome_apk,
constants.PACKAGE_INFO['chrome'])
- self._step_recorder.BeginStep('Process cyglog')
+ self._step_recorder.BeginStep('Process profile')
assert os.path.exists(self._compiler.lib_chrome_so)
offsets = process_profiles.GetReachedOffsetsFromDumpFiles(
files, self._compiler.lib_chrome_so)
@@ -615,6 +617,9 @@ class OrderfileGenerator(object):
profile_uploaded = False
orderfile_uploaded = False
+ assert (bool(self._options.profile) ^
+ bool(self._options.manual_symbol_offsets))
+
if self._options.profile:
try:
_UnstashOutputDirectory(self._instrumented_out_dir)
@@ -630,6 +635,22 @@ class OrderfileGenerator(object):
finally:
self._DeleteTempFiles()
_StashOutputDirectory(self._instrumented_out_dir)
+ elif self._options.manual_symbol_offsets:
+ assert self._options.manual_libname
+ assert self._options.manual_objdir
+ with file(self._options.manual_symbol_offsets) as f:
+ symbol_offsets = [int(x) for x in f.xreadlines()]
+ processor = process_profiles.SymbolOffsetProcessor(
+ self._options.manual_libname)
+ generator = cyglog_to_orderfile.OffsetOrderfileGenerator(
+ processor, cyglog_to_orderfile.ObjectFileProcessor(
+ self._options.manual_objdir))
+ ordered_sections = generator.GetOrderedSections(symbol_offsets)
+ if not ordered_sections: # Either None or empty is a problem.
+ raise Exception('Failed to get ordered sections')
+ with open(self._GetUnpatchedOrderfileFilename(), 'w') as orderfile:
+ orderfile.write('\n'.join(ordered_sections))
+
if self._options.patch:
if self._options.profile:
self._RemoveBlanks(self._GetUnpatchedOrderfileFilename(),
@@ -679,6 +700,9 @@ def CreateArgumentParser():
'--buildbot', action='store_true',
help='If true, the script expects to be run on a buildbot')
parser.add_argument(
+ '--device', default=None, type=str,
+ help='Device serial number on which to run profiling.')
+ parser.add_argument(
'--verify', action='store_true',
help='If true, the script only verifies the current orderfile')
parser.add_argument('--target-arch', action='store', dest='arch',
@@ -711,6 +735,18 @@ def CreateArgumentParser():
parser.add_argument(
'--use-goma', action='store_true', help='Enable GOMA.', default=False)
parser.add_argument('--adb-path', help='Path to the adb binary.')
+
+ parser.add_argument('--manual-symbol-offsets', default=None, type=str,
+ help=('File of list of ordered symbol offsets generated '
+ 'by manual profiling. Must set other --manual* '
+ 'flags if this is used, and must --skip-profile.'))
+ parser.add_argument('--manual-libname', default=None, type=str,
+ help=('Library filename corresponding to '
+ '--manual-symbol-offsets.'))
+ parser.add_argument('--manual-objdir', default=None, type=str,
+ help=('Root of object file directory corresponding to '
+ '--manual-symbol-offsets.'))
+
profile_android_startup.AddProfileCollectionArguments(parser)
return parser
diff --git a/chromium/tools/cygprofile/profile_android_startup.py b/chromium/tools/cygprofile/profile_android_startup.py
index 47ea35fda7b..57499a41dc8 100755
--- a/chromium/tools/cygprofile/profile_android_startup.py
+++ b/chromium/tools/cygprofile/profile_android_startup.py
@@ -38,11 +38,11 @@ from telemetry.internal.util import webpagereplay_go_server
from telemetry.internal.util import binary_manager
-class NoCyglogDataError(Exception):
- """An error used to indicate that no cyglog data was collected."""
+class NoProfileDataError(Exception):
+ """An error used to indicate that no profile data was collected."""
def __init__(self, value):
- super(NoCyglogDataError, self).__init__()
+ super(NoProfileDataError, self).__init__()
self.value = value
def __str__(self):
@@ -174,35 +174,43 @@ class WprManager(object):
class AndroidProfileTool(object):
- """A utility for generating cygprofile data for chrome on andorid.
+ """A utility for generating orderfile profile data for chrome on android.
Runs cygprofile_unittest found in output_directory, does profiling runs,
- and pulls the data to the local machine in output_directory/cyglog_data.
+ and pulls the data to the local machine in output_directory/profile_data.
"""
- _DEVICE_CYGLOG_DIR = '/data/local/tmp/chrome/cyglog'
+ _DEVICE_PROFILE_DIR = '/data/local/tmp/chrome/orderfile'
+
+ # Old profile data directories that used to be used. These are cleaned up in
+ # order to keep devices tidy.
+ _LEGACY_PROFILE_DIRS = ['/data/local/tmp/chrome/cyglog']
TEST_URL = 'https://www.google.com/#hl=en&q=science'
_WPR_ARCHIVE = os.path.join(
os.path.dirname(__file__), 'memory_top_10_mobile_000.wprgo')
- def __init__(self, output_directory, host_cyglog_dir, use_wpr, urls,
- simulate_user):
+ def __init__(self, output_directory, host_profile_dir, use_wpr, urls,
+ simulate_user, device=None):
"""Constructor.
Args:
output_directory: (str) Chrome build directory.
- host_cyglog_dir: (str) Where to store the profiles.
+ host_profile_dir: (str) Where to store the profiles on the host.
use_wpr: (bool) Whether to use Web Page Replay.
urls: (str) URLs to load. Have to be contained in the WPR archive if
use_wpr is True.
simulate_user: (bool) Whether to simulate a user.
"""
- devices = device_utils.DeviceUtils.HealthyDevices()
- self._device = devices[0]
+ if device is None:
+ devices = device_utils.DeviceUtils.HealthyDevices()
+ assert len(devices) == 1, 'Expected exactly one connected device'
+ self._device = devices[0]
+ else:
+ self._device = device_utils.DeviceUtils(device)
self._cygprofile_tests = os.path.join(
output_directory, 'cygprofile_unittests')
- self._host_cyglog_dir = host_cyglog_dir
+ self._host_profile_dir = host_profile_dir
self._use_wpr = use_wpr
self._urls = urls
self._simulate_user = simulate_user
@@ -238,7 +246,7 @@ class AndroidProfileTool(object):
A list of cygprofile data files.
Raises:
- NoCyglogDataError: No data was found on the device.
+ NoProfileDataError: No data was found on the device.
"""
self._Install(apk)
try:
@@ -253,7 +261,7 @@ class AndroidProfileTool(object):
finally:
self._RestoreChromeFlags(changer)
- data = self._PullCyglogData()
+ data = self._PullProfileData()
self._DeleteDeviceData()
return data
@@ -308,7 +316,7 @@ class AndroidProfileTool(object):
"""When profiling, files are output to the disk by every process. This
means running without sandboxing enabled.
"""
- # We need to have adb root in order to pull cyglog data
+ # We need to have adb root in order to pull profile data
try:
print 'Enabling root...'
self._device.EnableRoot()
@@ -334,18 +342,18 @@ class AndroidProfileTool(object):
changer.Restore()
def _SetUpDeviceFolders(self):
- """Creates folders on the device to store cyglog data."""
+ """Creates folders on the device to store profile data."""
print 'Setting up device folders...'
self._DeleteDeviceData()
- self._device.RunShellCommand(
- ['mkdir', '-p', str(self._DEVICE_CYGLOG_DIR)],
- check_return=True)
+ self._device.RunShellCommand(['mkdir', '-p', self._DEVICE_PROFILE_DIR],
+ check_return=True)
def _DeleteDeviceData(self):
- """Clears out cyglog storage locations on the device. """
- self._device.RunShellCommand(
- ['rm', '-rf', str(self._DEVICE_CYGLOG_DIR)],
- check_return=True)
+ """Clears out profile storage locations on the device. """
+ for profile_dir in [self._DEVICE_PROFILE_DIR] + self._LEGACY_PROFILE_DIRS:
+ self._device.RunShellCommand(
+ ['rm', '-rf', str(profile_dir)],
+ check_return=True)
def _StartChrome(self, package_info, url):
print 'Launching chrome...'
@@ -360,43 +368,44 @@ class AndroidProfileTool(object):
self._device.KillAll(package_info.package)
def _DeleteHostData(self):
- """Clears out cyglog storage locations on the host."""
- shutil.rmtree(self._host_cyglog_dir, ignore_errors=True)
+ """Clears out profile storage locations on the host."""
+ shutil.rmtree(self._host_profile_dir, ignore_errors=True)
def _SetUpHostFolders(self):
self._DeleteHostData()
- os.mkdir(self._host_cyglog_dir)
+ os.mkdir(self._host_profile_dir)
- def _PullCyglogData(self):
- """Pulls the cyglog data off of the device.
+ def _PullProfileData(self):
+ """Pulls the profile data off of the device.
Returns:
- A list of cyglog data files which were pulled.
+ A list of profile data files which were pulled.
Raises:
- NoCyglogDataError: No data was found on the device.
+ NoProfileDataError: No data was found on the device.
"""
- print 'Pulling cyglog data...'
+ print 'Pulling profile data...'
self._SetUpHostFolders()
- self._device.PullFile(self._DEVICE_CYGLOG_DIR, self._host_cyglog_dir)
- files = os.listdir(self._host_cyglog_dir)
-
- if len(files) == 0:
- raise NoCyglogDataError('No cyglog data was collected')
+ self._device.PullFile(self._DEVICE_PROFILE_DIR, self._host_profile_dir)
# Temporary workaround/investigation: if (for unknown reason) 'adb pull' of
- # the directory 'cyglog' into '.../Release/cyglog_data' produces
- # '...cyglog_data/cyglog/files' instead of the usual '...cyglog_data/files',
- # list the files deeper in the tree.
- cyglog_dir = self._host_cyglog_dir
- if (len(files) == 1) and (files[0] == 'cyglog'):
- cyglog_dir = os.path.join(self._host_cyglog_dir, 'cyglog')
- files = os.listdir(cyglog_dir)
+ # the directory 'orderfile' '.../Release/profile_data' produces
+ # '...profile_data/orderfile/files' instead of the usual
+ # '...profile_data/files', list the files deeper in the tree.
+ files = []
+ redundant_dir_root = os.path.basename(self._DEVICE_PROFILE_DIR)
+ for root_file in os.listdir(self._host_profile_dir):
+ if root_file == redundant_dir_root:
+ profile_dir = os.path.join(self._host_profile_dir, root_file)
+ files.extend(os.path.join(profile_dir, f)
+ for f in os.listdir(profile_dir))
+ else:
+ files.append(root_file)
if len(files) == 0:
- raise NoCyglogDataError('No cyglog data was collected')
+ raise NoProfileDataError('No profile data was collected')
- return [os.path.join(cyglog_dir, x) for x in files]
+ return [os.path.join(profile_dir, x) for x in files]
def AddProfileCollectionArguments(parser):
@@ -424,8 +433,8 @@ def CreateArgumentParser():
help='Chromium output directory (e.g. out/Release)')
parser.add_argument(
'--trace-directory', type=os.path.realpath,
- help='Directory in which cyglog traces will be stored. '
- 'Defaults to <output-directory>/cyglog_data')
+ help='Directory in which profile traces will be stored. '
+ 'Defaults to <output-directory>/profile_data')
AddProfileCollectionArguments(parser)
return parser
@@ -446,8 +455,11 @@ def main():
else:
raise Exception('Unable to determine package info for %s' % args.apk_path)
+ trace_directory = args.trace_directory
+ if not trace_directory:
+ trace_directory = os.path.join(args.output_directory, 'profile_data')
profiler = AndroidProfileTool(
- args.output_directory, host_cyglog_dir=args.trace_directory,
+ args.output_directory, host_profile_dir=trace_directory,
use_wpr=not args.no_wpr, urls=args.urls, simulate_user=args.simulate_user)
profiler.CollectProfile(args.apk_path, package_info)
return 0
diff --git a/chromium/tools/determinism/compare_build_artifacts.py b/chromium/tools/determinism/compare_build_artifacts.py
index 62dae004beb..6a8282593a2 100755
--- a/chromium/tools/determinism/compare_build_artifacts.py
+++ b/chromium/tools/determinism/compare_build_artifacts.py
@@ -164,7 +164,7 @@ def compare_files(first_filepath, second_filepath):
return diff_binary(first_filepath, second_filepath, file_len)
-def get_deps(build_dir, target):
+def get_deps(ninja_path, build_dir, target):
"""Returns list of object files needed to build target."""
NODE_PATTERN = re.compile(r'label="([a-zA-Z0-9_\\/.-]+)"')
CHECK_EXTS = ('.o', '.obj')
@@ -181,7 +181,7 @@ def get_deps(build_dir, target):
shutil.move(build_dir, fixed_build_dir)
try:
- out = subprocess.check_output(['ninja', '-C', fixed_build_dir,
+ out = subprocess.check_output([ninja_path, '-C', fixed_build_dir,
'-t', 'graph', target])
except subprocess.CalledProcessError as e:
print >> sys.stderr, 'error to get graph for %s: %s' % (target, e)
@@ -207,12 +207,12 @@ def get_deps(build_dir, target):
return files
-def compare_deps(first_dir, second_dir, targets):
+def compare_deps(first_dir, second_dir, ninja_path, targets):
"""Print difference of dependent files."""
diffs = set()
for target in targets:
- first_deps = get_deps(first_dir, target)
- second_deps = get_deps(second_dir, target)
+ first_deps = get_deps(ninja_path, first_dir, target)
+ second_deps = get_deps(ninja_path, second_dir, target)
print 'Checking %s difference: (%s deps)' % (target, len(first_deps))
if set(first_deps) != set(second_deps):
# Since we do not thiks this case occur, we do not do anything special
@@ -231,7 +231,7 @@ def compare_deps(first_dir, second_dir, targets):
return list(diffs)
-def compare_build_artifacts(first_dir, second_dir, target_platform,
+def compare_build_artifacts(first_dir, second_dir, ninja_path, target_platform,
json_output, recursive=False):
"""Compares the artifacts from two distinct builds."""
if not os.path.isdir(first_dir):
@@ -300,7 +300,8 @@ def compare_build_artifacts(first_dir, second_dir, target_platform,
all_diffs = expected_diffs + unexpected_diffs
diffs_to_investigate = sorted(set(all_diffs).difference(missing_files))
- deps_diff = compare_deps(first_dir, second_dir, diffs_to_investigate)
+ deps_diff = compare_deps(first_dir, second_dir,
+ ninja_path, diffs_to_investigate)
if json_output:
try:
@@ -326,6 +327,8 @@ def main():
parser.add_option('-r', '--recursive', action='store_true', default=False,
help='Indicates if the comparison should be recursive.')
parser.add_option('--json-output', help='JSON file to output differences')
+ parser.add_option('--ninja-path', help='path to ninja command.',
+ default='ninja')
target = {
'darwin': 'mac', 'linux2': 'linux', 'win32': 'win'
}.get(sys.platform, sys.platform)
@@ -342,6 +345,7 @@ def main():
return compare_build_artifacts(os.path.abspath(options.first_build_dir),
os.path.abspath(options.second_build_dir),
+ options.ninja_path,
options.target_platform,
options.json_output,
options.recursive)
diff --git a/chromium/tools/determinism/deterministic_build_whitelist.pyl b/chromium/tools/determinism/deterministic_build_whitelist.pyl
index 3be370171ec..ce6a518b69e 100644
--- a/chromium/tools/determinism/deterministic_build_whitelist.pyl
+++ b/chromium/tools/determinism/deterministic_build_whitelist.pyl
@@ -164,7 +164,6 @@
'angle_unittests.exe',
'app_driver_library.dll',
'app_list_demo.exe',
- 'app_list_presenter_unittests.exe',
'app_list_unittests.exe',
'app_shell.exe',
'app_shell_unittests.exe',
diff --git a/chromium/tools/dump_process_memory/BUILD.gn b/chromium/tools/dump_process_memory/BUILD.gn
new file mode 100644
index 00000000000..4c1a2419391
--- /dev/null
+++ b/chromium/tools/dump_process_memory/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+executable("dump_process") {
+ sources = [
+ "dump_process.cc",
+ ]
+ deps = [
+ "//base",
+ ]
+}
+
+group("all") {
+ deps = [
+ ":dump_process",
+ ]
+}
diff --git a/chromium/tools/dump_process_memory/OWNERS b/chromium/tools/dump_process_memory/OWNERS
new file mode 100644
index 00000000000..ef8590f575f
--- /dev/null
+++ b/chromium/tools/dump_process_memory/OWNERS
@@ -0,0 +1,3 @@
+lizeb@chromium.org
+pasko@chromium.org
+
diff --git a/chromium/tools/dump_process_memory/analyze_dumps.py b/chromium/tools/dump_process_memory/analyze_dumps.py
new file mode 100755
index 00000000000..666e9da413f
--- /dev/null
+++ b/chromium/tools/dump_process_memory/analyze_dumps.py
@@ -0,0 +1,253 @@
+#!/usr/bin/python
+#
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""From a dump generated by dump_process.cc dump, prints statistics about
+its content.
+"""
+
+import array
+import collections
+import hashlib
+import logging
+import os
+import struct
+import sys
+import zlib
+
+
+PAGE_SIZE = 1 << 12
+
+
+def _ReadPage(f):
+ """Reads a page of data from a file.
+
+ Args:
+ f: (file) An opened file to read from.
+
+ Returns:
+ An array.array() of unsigned int with the page content.
+ """
+ result = array.array('I')
+ result.fromfile(f, PAGE_SIZE / result.itemsize)
+ return result
+
+
+def _PrettyPrintSize(x):
+ """Pretty print sizes in bytes, e.g. 123456 -> 123.45kB.
+
+ Args:
+ x: (int) size
+
+ Returns:
+ (str) Pretty printed version, 2 decimal places.
+ """
+ if x < 1e3:
+ return str(x)
+ elif 1e3 <= x < 1e6:
+ return '%.2fkB' % (x / 1e3)
+ elif 1e6 <= x < 1e9:
+ return '%.2fMB' % (x / 1e6)
+ else:
+ return '%.2fGB' % (x / 1e9)
+
+
+class MappingStats(object):
+ """Statistics about a mapping, from a dump.
+
+ Slots:
+ filename: (str) Dump filename.
+ start: (int) Start address of the mapping.
+ end: (int) End address of the mapping.
+ pages: (int) Sizs of the mapping in pages.
+ is_zero: ([bool]) For each page, whether it's a zero page.
+ is_present: ([bool]) For each page, whether it's present.
+ is_swapped: ([bool]) For each page, whether it has been swapped out.
+ compressed_size: ([int]) If a page is not zero, its compressed size.
+ hashes: ([str]) If a page is not zero, its SHA1 hash.
+ """
+ __slots__ = ('filename', 'start', 'end', 'pages', 'is_zero', 'is_present',
+ 'is_swapped', 'compressed_size', 'hashes', 'freed')
+ def __init__(self, filename, start, end):
+ """Init.
+
+ Args:
+ filename: (str) Dump filename.
+ start: (int) Start address.
+ end: (int) End address
+ """
+ self.filename = filename
+ self.start = start
+ self.end = end
+ self.pages = (end - start) / PAGE_SIZE
+ self.is_zero = [False for i in range(self.pages)]
+ self.is_present = [False for i in range(self.pages)]
+ self.is_swapped = [False for i in range(self.pages)]
+ self.compressed_size = [0 for i in range(self.pages)]
+ self.hashes = [None for i in range(self.pages)]
+ self.freed = 0
+
+
+def _GetStatsFromFileDump(filename):
+ """Computes per-dump statistics.
+
+ Args:
+ filename: (str) Path to the dump.
+
+ Returns:
+ MappingStats for the mapping.
+ """
+ # These are typically only populated with DCHECK() on.
+ FREED_PATTERNS = (0xcccccccc, # V8
+ 0xcdcdcdcd, # PartitionAlloc "zapped"
+ 0xabababab, # PartitionAlloc "uninitialized"
+ 0xdeadbeef, # V8 "zapped"
+ 0x0baddeaf, # V8 zapped handles
+ 0x0baffedf, # V8 zapped global handles
+ 0x0beefdaf, # V8 zapped from space
+ 0xbeefdeef, # V8 zapped slots
+ 0xbadbaddb, # V8 debug zapped
+ 0xfeed1eaf) # V8 zapped freelist
+ # Dump integrity checks.
+ metadata_filename = filename + '.metadata'
+ pid_start_end = os.path.basename(filename)[:-len('.dump')]
+ (_, start, end) = [int(x, 10) for x in pid_start_end.split('-')]
+ file_stat = os.stat(filename)
+ assert start % PAGE_SIZE == 0
+ assert end % PAGE_SIZE == 0
+ assert file_stat.st_size == (end - start)
+ metadata_file_stat = os.stat(metadata_filename)
+ result = MappingStats(filename, start, end)
+ # each line is [01]{2}\n, eg '10\n', 1 line per page.
+ assert metadata_file_stat.st_size == 3 * result.pages
+
+ with open(filename, 'r') as f, open(metadata_filename, 'r') as metadata_f:
+ for i in range(result.pages):
+ page = _ReadPage(f)
+ assert len(page) == 1024
+ result.freed += 4 * sum(x in FREED_PATTERNS for x in page)
+ is_zero = max(page) == 0
+ present, swapped = (bool(int(x)) for x in metadata_f.readline().strip())
+ # Not present, not swapped private anonymous == lazily initialized zero
+ # page.
+ if not present and not swapped:
+ assert is_zero
+ result.is_zero[i] = is_zero
+ result.is_present[i] = present
+ result.is_swapped[i] = swapped
+ if not is_zero:
+ sha1 = hashlib.sha1()
+ sha1.update(page)
+ page_hash = sha1.digest()
+ result.hashes[i] = page_hash
+ compressed = zlib.compress(page, 1)
+ result.compressed_size[i] = len(compressed)
+ return result
+
+
+def _FindPageFromHash(mappings, page_hash):
+ """Returns a page with a given hash from a list of mappings.
+
+ Args:
+ mappings: ([MappingStats]) List of mappings.
+ page_hash: (str) Page hash to look for,
+
+ Returns:
+ array.array(uint32_t) with the page content
+ """
+ for mapping in mappings:
+ for i in range(mapping.pages):
+ if mapping.hashes[i] == page_hash:
+ with open(mapping.filename, 'r') as f:
+ f.seek(i * PAGE_SIZE)
+ page = _ReadPage(f)
+ sha1 = hashlib.sha1()
+ sha1.update(page)
+ assert page_hash == sha1.digest()
+ return page
+
+
+def _PrintPage(page):
+ """Prints the content of a page."""
+ for i, x in enumerate(page):
+ print '{:08x}'.format(x),
+ if i % 16 == 15:
+ print
+
+
+def PrintStats(dumps):
+ """Logs statistics about a process mappings dump.
+
+ Args:
+ dumps: ([str]) List of dumps.
+ """
+ dump_stats = [_GetStatsFromFileDump(filename) for filename in dumps]
+ content_to_count = collections.defaultdict(int)
+ total_pages = sum(stats.pages for stats in dump_stats)
+ total_zero_pages = sum(sum(stats.is_zero) for stats in dump_stats)
+ total_compressed_size = sum(sum(stats.compressed_size)
+ for stats in dump_stats)
+ total_swapped_pages = sum(sum(stats.is_swapped) for stats in dump_stats)
+ total_not_present_pages = sum(stats.pages - sum(stats.is_present)
+ for stats in dump_stats)
+ total_present_zero_pages = sum(
+ sum(x == (True, True) for x in zip(stats.is_zero, stats.is_present))
+ for stats in dump_stats)
+ total_freed_space = sum(stats.freed for stats in dump_stats)
+
+ content_to_count = collections.defaultdict(int)
+ for stats in dump_stats:
+ for page_hash in stats.hashes:
+ if page_hash:
+ content_to_count[page_hash] += 1
+
+ print 'Total pages = %d (%s)' % (total_pages,
+ _PrettyPrintSize(total_pages * PAGE_SIZE))
+ print 'Total zero pages = %d (%.02f%%)' % (
+ total_zero_pages, (100. * total_zero_pages) / total_pages)
+ print 'Total present zero pages = %d (%s)' % (
+ total_present_zero_pages,
+ _PrettyPrintSize(total_present_zero_pages * PAGE_SIZE))
+ total_size_non_zero_pages = (total_pages - total_zero_pages) * PAGE_SIZE
+ print 'Total size of non-zero pages = %d (%s)' % (
+ total_size_non_zero_pages, _PrettyPrintSize(total_size_non_zero_pages))
+ print 'Total compressed size = %d (%.02f%%)' % (
+ total_compressed_size,
+ (100. * total_compressed_size) / total_size_non_zero_pages)
+ duplicated_pages = sum(x - 1 for x in content_to_count.values())
+ print 'Duplicated non-zero pages = %d' % duplicated_pages
+ count_and_hashes = sorted(((v, k) for k, v in content_to_count.items()),
+ reverse=True)
+ max_common_pages = count_and_hashes[0][0] - 1
+ print 'Max non-zero pages with the same content = %d' % max_common_pages
+ print 'Swapped pages = %d (%s)' % (
+ total_swapped_pages, _PrettyPrintSize(total_swapped_pages * PAGE_SIZE))
+ print 'Non-present pages = %d (%s)' % (
+ total_not_present_pages,
+ _PrettyPrintSize(total_not_present_pages * PAGE_SIZE))
+ print 'Freed = %d (%s)' % (
+ total_freed_space, _PrettyPrintSize(total_freed_space))
+ print 'Top Duplicated Pages:'
+ for i in range(10):
+ count, page_hash = count_and_hashes[i]
+ print '%d common pages' % count
+ page = _FindPageFromHash(dump_stats, page_hash)
+ _PrintPage(page)
+ print
+
+
+def main():
+ logging.basicConfig(level=logging.INFO)
+ if len(sys.argv) != 2:
+ logging.error('Usage: %s <dumps_directory>', sys.argv[0])
+ sys.exit(1)
+ directory = sys.argv[1]
+ dumps = [os.path.join(directory, f) for f in os.listdir(directory)
+ if f.endswith('.dump')]
+ PrintStats(dumps)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/chromium/tools/dump_process_memory/dump_process.cc b/chromium/tools/dump_process_memory/dump_process.cc
new file mode 100644
index 00000000000..de6384be76f
--- /dev/null
+++ b/chromium/tools/dump_process_memory/dump_process.cc
@@ -0,0 +1,259 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <limits>
+#include <string>
+#include <vector>
+
+#include "base/debug/proc_maps_linux.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/format_macros.h"
+#include "base/logging.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+
+namespace {
+
+using base::debug::MappedMemoryRegion;
+constexpr size_t kPageSize = 1 << 12;
+
+// See https://www.kernel.org/doc/Documentation/vm/pagemap.txt.
+struct PageMapEntry {
+ uint64_t pfn_or_swap : 55;
+ uint64_t soft_dirty : 1;
+ uint64_t exclusively_mapped : 1;
+ uint64_t unused : 4;
+ uint64_t file_mapped_or_shared_anon : 1;
+ uint64_t swapped : 1;
+ uint64_t present : 1;
+};
+static_assert(sizeof(PageMapEntry) == sizeof(uint64_t), "Wrong bitfield size");
+
+// Calls ptrace() on a process, and detaches in the destructor.
+class ScopedPtracer {
+ public:
+ ScopedPtracer(pid_t pid) : pid_(pid), is_attached_(false) {
+ // ptrace() delivers a SIGSTOP signal to one thread in the target process,
+ // unless it is already stopped. Since we want to stop the whole process,
+ // send a signal to every thread in the process group.
+ pid_t process_group_id = getpgid(pid);
+ if (killpg(process_group_id, SIGSTOP)) {
+ PLOG(ERROR) << "Cannot stop the process group of " << pid;
+ return;
+ }
+
+ if (ptrace(PTRACE_ATTACH, pid, nullptr, nullptr)) {
+ PLOG(ERROR) << "Unable to attach to " << pid;
+ return;
+ }
+ // ptrace(PTRACE_ATTACH) sends a SISTOP signal to the process, need to wait
+ // for it.
+ int status;
+ pid_t ret = HANDLE_EINTR(waitpid(pid, &status, 0));
+ if (ret != pid) {
+ PLOG(ERROR) << "Waiting for the process failed";
+ return;
+ }
+ if (!WIFSTOPPED(status)) {
+ LOG(ERROR) << "The process is not stopped";
+ ptrace(PTRACE_DETACH, pid, 0, 0);
+ return;
+ }
+ is_attached_ = true;
+ }
+
+ ~ScopedPtracer() {
+ if (!is_attached_)
+ return;
+ if (ptrace(PTRACE_DETACH, pid_, 0, 0)) {
+ PLOG(ERROR) << "Cannot detach from " << pid_;
+ }
+ pid_t process_group_id = getpgid(pid_);
+ if (killpg(process_group_id, SIGCONT)) {
+ PLOG(ERROR) << "Cannot resume the process " << pid_;
+ return;
+ }
+ }
+
+ bool IsAttached() const { return is_attached_; }
+
+ private:
+ pid_t pid_;
+ bool is_attached_;
+};
+
+bool ParseProcMaps(pid_t pid, std::vector<MappedMemoryRegion>* regions) {
+ std::string path = base::StringPrintf("/proc/%d/maps", pid);
+ std::string proc_maps;
+ bool ok = base::ReadFileToString(base::FilePath(path), &proc_maps);
+ if (!ok) {
+ LOG(ERROR) << "Cannot read " << path;
+ return false;
+ }
+ ok = base::debug::ParseProcMaps(proc_maps, regions);
+ if (!ok) {
+ LOG(ERROR) << "Cannot parse " << path;
+ return false;
+ }
+ return true;
+}
+
+// Keep anonynmous rw-p regions.
+bool ShouldDump(const MappedMemoryRegion& region) {
+ const auto rw_p = MappedMemoryRegion::READ | MappedMemoryRegion::WRITE |
+ MappedMemoryRegion::PRIVATE;
+ if (region.permissions != rw_p)
+ return false;
+ if (base::StartsWith(region.path, "/", base::CompareCase::SENSITIVE) ||
+ base::StartsWith(region.path, "[stack]", base::CompareCase::SENSITIVE)) {
+ return false;
+ }
+ return true;
+}
+
+base::File OpenProcPidFile(const char* filename, pid_t pid) {
+ std::string path = base::StringPrintf("/proc/%d/%s", pid, filename);
+ auto file = base::File(base::FilePath(path),
+ base::File::FLAG_OPEN | base::File::FLAG_READ);
+ if (!file.IsValid()) {
+ PLOG(ERROR) << "Cannot open " << path;
+ }
+ return file;
+}
+
+bool DumpRegion(const MappedMemoryRegion& region,
+ pid_t pid,
+ base::File* proc_mem,
+ base::File* proc_pagemap) {
+ size_t size_in_pages = (region.end - region.start) / kPageSize;
+ std::string output_path = base::StringPrintf("%d-%" PRIuS "-%" PRIuS ".dump",
+ pid, region.start, region.end);
+ base::File output_file(base::FilePath(output_path),
+ base::File::FLAG_WRITE | base::File::FLAG_CREATE);
+ if (!output_file.IsValid()) {
+ PLOG(ERROR) << "Cannot open " << output_path;
+ return false;
+ }
+ std::string metadata_path = output_path + std::string(".metadata");
+ base::File metadata_file(base::FilePath(metadata_path),
+ base::File::FLAG_WRITE | base::File::FLAG_CREATE);
+ if (!metadata_file.IsValid()) {
+ PLOG(ERROR) << "Cannot open " << metadata_path;
+ return false;
+ }
+
+ // Dump metadata.
+ // Important: Metadata must be dumped before the data, as reading from
+ // /proc/pid/mem will move the data back from swap, so dumping metadata
+ // later would not show anything in swap.
+ // This also means that dumping the same process twice will result in
+ // inaccurate metadata.
+ for (size_t i = 0; i < size_in_pages; ++i) {
+ // See https://www.kernel.org/doc/Documentation/vm/pagemap.txt
+ // 64 bits per page.
+ int64_t pagemap_offset =
+ ((region.start / kPageSize) + i) * sizeof(PageMapEntry);
+ PageMapEntry entry;
+ proc_pagemap->Seek(base::File::FROM_BEGIN, pagemap_offset);
+ int size_read = proc_pagemap->ReadAtCurrentPos(
+ reinterpret_cast<char*>(&entry), sizeof(PageMapEntry));
+ if (size_read != sizeof(PageMapEntry)) {
+ PLOG(ERROR) << "Cannot read from /proc/pid/pagemap at offset "
+ << pagemap_offset;
+ return false;
+ }
+ std::string metadata = base::StringPrintf(
+ "%c%c\n", entry.present ? '1' : '0', entry.swapped ? '1' : '0');
+ metadata_file.WriteAtCurrentPos(metadata.c_str(), metadata.size());
+ }
+
+ // Writing data page by page to avoid allocating too much memory.
+ std::vector<char> buffer(kPageSize);
+ for (size_t i = 0; i < size_in_pages; ++i) {
+ uint64_t address = region.start + i * kPageSize;
+ // Works because the upper half of the address space is reserved for the
+ // kernel on at least ARM64 and x86_64 bit architectures.
+ CHECK(address <= std::numeric_limits<int64_t>::max());
+ proc_mem->Seek(base::File::FROM_BEGIN, static_cast<int64_t>(address));
+ int size_read = proc_mem->ReadAtCurrentPos(&buffer[0], kPageSize);
+ if (size_read != kPageSize) {
+ PLOG(ERROR) << "Cannot read from /proc/pid/mem at offset " << address;
+ return false;
+ }
+
+ int64_t output_offset = i * kPageSize;
+ int size_written = output_file.Write(output_offset, &buffer[0], kPageSize);
+ if (size_written != kPageSize) {
+ PLOG(ERROR) << "Cannot write to output file";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Dumps the content of all the anonymous rw-p mappings in a given process to
+// disk.
+bool DumpMappings(pid_t pid) {
+ LOG(INFO) << "Attaching to " << pid;
+ ScopedPtracer tracer(pid);
+ if (!tracer.IsAttached())
+ return false;
+
+ LOG(INFO) << "Reading /proc/pid/maps";
+ std::vector<base::debug::MappedMemoryRegion> regions;
+ bool ok = ParseProcMaps(pid, &regions);
+ if (!ok)
+ return false;
+
+ base::File proc_mem = OpenProcPidFile("mem", pid);
+ if (!proc_mem.IsValid())
+ return false;
+ base::File proc_pagemap = OpenProcPidFile("pagemap", pid);
+ if (!proc_pagemap.IsValid())
+ return false;
+
+ for (const auto& region : regions) {
+ if (!ShouldDump(region))
+ continue;
+ std::string message =
+ base::StringPrintf("%" PRIuS "-%" PRIuS " (size %" PRIuS ")",
+ region.start, region.end, region.end - region.start);
+ LOG(INFO) << "Dumping " << message;
+ ok = DumpRegion(region, pid, &proc_mem, &proc_pagemap);
+ if (!ok) {
+ LOG(WARNING) << "Failed to dump region";
+ }
+ }
+ return true;
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ CHECK(sysconf(_SC_PAGESIZE) == kPageSize);
+
+ if (argc != 2) {
+ LOG(ERROR) << "Usage: " << argv[0] << " <pid>";
+ return 1;
+ }
+ pid_t pid;
+ bool ok = base::StringToInt(argv[1], &pid);
+ if (!ok) {
+ LOG(ERROR) << "Cannot parse PID";
+ return 1;
+ }
+
+ ok = DumpMappings(pid);
+ return ok ? 0 : 1;
+}
diff --git a/chromium/tools/emacs/trybot-mac.txt b/chromium/tools/emacs/trybot-mac.txt
index d12efd5f1ca..7ce02be6617 100644
--- a/chromium/tools/emacs/trybot-mac.txt
+++ b/chromium/tools/emacs/trybot-mac.txt
@@ -1591,7 +1591,7 @@ Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-norm
setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
setenv LANG en_US.US-ASCII
setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
- /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_host_manager.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_view_host_manager.o
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/tab_contents/render_view_host_manager.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/render_view_host_manager.o
Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/blob_dispatcher_host.o browser/renderer_host/blob_dispatcher_host.cc normal i386 c++ com.apple.compilers.gcc.4_2
cd /b/build/slave/mac/build/src/chrome
@@ -1613,7 +1613,7 @@ Distributed-CompileC ../xcodebuild/chrome.build/Debug/browser.build/Objects-norm
setenv INCLUDE_SERVER_DIR /tmp/distcc-pump.C2DZDO
setenv INCLUDE_SERVER_PID 983
setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
- setenv LANG en_US.US-ASCII
+ setenv LANG en_US.US-ASCII
setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
/Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x objective-c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DCHROME_V8 -DGOOGLE_PROTOBUF_NO_RTTI -DXML_STATIC -DFEATURE_ENABLE_SSL -DFEATURE_ENABLE_VOICEMAIL -DEXPAT_RELATIVE_PATH -DOSX -DPOSIX -DLIBXML_STATIC -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/DerivedSources/Debug -I../third_party/apple -I../third_party/GTM -I../third_party/GTM/AppKit -I../third_party/GTM/Foundation -I../third_party/GTM/DebugUtils -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_resources -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_locale_settings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app/app_strings -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I../third_party/bzip2 -I../third_party/expat/files/lib -I../third_party/libjingle/overrides -I../third_party/libjingle/source -I../third_party/expat/files -I../third_party/libxml/mac/include -I../third_party/libxml/src/include -I../third_party/npapi -I../third_party/npapi/bindings -I../third_party/speex/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/browser/tab_contents/tab_contents_view_mac.mm -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/browser.build/Objects-normal/i386/tab_contents_view_mac.o
@@ -1885,7 +1885,7 @@ Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-nor
setenv INCLUDE_SERVER_PORT /tmp/distcc-pump.C2DZDO/socket
setenv LANG en_US.US-ASCII
setenv PATH "/usr/bin:/Developer/usr/bin:/usr/bin:/b/build/../depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"
- /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/device_orientation_dispatcher.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/device_orientation_dispatcher.o
+ /Developer/usr/bin/distcc /Developer/usr/bin/gcc-4.2 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fno-exceptions -fno-rtti -O0 -Werror -Wnewline-eof -DCHROMIUM_BUILD -DENABLE_REMOTING=1 -DENABLE_GPU=1 -DNACL_WINDOWS=0 -DNACL_LINUX=0 -DNACL_OSX=1 -DNACL_TARGET_SUBARCH=32 -DNACL_BUILD_SUBARCH=32 -DGOOGLE_PROTOBUF_NO_RTTI -DHUNSPELL_STATIC -DHUNSPELL_CHROME_CLIENT -DUSE_HUNSPELL -DCLD_WINDOWS -DCOMPILER_GCC -D__STDC_CONSTANT_MACROS -DNACL_BLOCK_SHIFT=5 -DNACL_BLOCK_SIZE=32 -D__STDC_FORMAT_MACROS -DDYNAMIC_ANNOTATIONS_ENABLED=1 -D_DEBUG -isysroot /Developer/SDKs/MacOSX10.5.sdk -fvisibility=hidden -fvisibility-inlines-hidden -fno-threadsafe-statics -mmacosx-version-min=10.5 -gdwarf-2 -Wall -Wendif-labels -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -fpch-preprocess -F/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug -F/Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks/ApplicationServices.framework/Frameworks -I/b/build/slave/mac/build/src/chrome/../xcodebuild/Debug/include -I../third_party/icu/public/common -I../third_party/icu/public/i18n -I.. -I../third_party/cld -I../gpu -I../third_party -I../third_party/mesa/MesaLib/include -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/app -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/chrome -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/protoc_out -I../third_party/protobuf -I../third_party/protobuf/src -I../skia/config -I../third_party/skia/include/config -I../third_party/skia/include/core -I../third_party/skia/include/effects -I../skia/ext -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/ffmpeg -I../third_party/ffmpeg/config -I../third_party/ffmpeg/patched-ffmpeg-mt -I../third_party/npapi -I../third_party/npapi/bindings -I/b/build/slave/mac/build/src/chrome/../xcodebuild/DerivedSources/Debug/webkit -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources/i386 -I/b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/DerivedSources -g1 -c /b/build/slave/mac/build/src/chrome/renderer/device_orientation_dispatcher.cc -o /b/build/slave/mac/build/src/chrome/../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/device_orientation_dispatcher.o
Distributed-CompileC ../xcodebuild/chrome.build/Debug/renderer.build/Objects-normal/i386/audio_message_filter.o renderer/audio_message_filter.cc normal i386 c++ com.apple.compilers.gcc.4_2
cd /b/build/slave/mac/build/src/chrome
diff --git a/chromium/tools/fuchsia/comparative_tester/comparative_tester.py b/chromium/tools/fuchsia/comparative_tester/comparative_tester.py
index d42f3391fc4..09bd203c308 100755
--- a/chromium/tools/fuchsia/comparative_tester/comparative_tester.py
+++ b/chromium/tools/fuchsia/comparative_tester/comparative_tester.py
@@ -7,18 +7,24 @@
# Fuchsia devices and then compares their output to each other, extracting the
# relevant performance data from the output of gtest.
+import argparse
+import logging
import os
import re
import subprocess
import sys
-from typing import *
+import time
+
+from collections import defaultdict
+from typing import Tuple, Dict, List
import target_spec
+import test_results
-def RunCommand(command: List[str], msg: str,
- ignore_errors: bool = False) -> str:
+def RunCommand(command: List[str], msg: str) -> str:
"One-shot start and complete command with useful default kwargs"
+ command = [piece for piece in command if piece != ""]
proc = subprocess.run(
command,
stdout=subprocess.PIPE,
@@ -29,70 +35,76 @@ def RunCommand(command: List[str], msg: str,
if proc.returncode != 0:
sys.stderr.write("{}\nreturn code: {}\nstdout: {}\nstderr: {}".format(
msg, proc.returncode, out, err))
- if not ignore_errors:
- raise subprocess.SubprocessError(
- "Command failed to complete successfully. {}".format(command))
+ raise subprocess.SubprocessError(
+ "Command failed to complete successfully. {}".format(command))
return out
+# TODO(crbug.com/848465): replace with --test-launcher-filter-file directly
+def ParseFilterFile(filepath: str) -> str:
+ positive_filters = []
+ negative_filters = []
+ with open(filepath, "r") as file:
+ for line in file:
+ # Only take the part of a line before a # sign
+ line = line.split("#", 1)[0].strip()
+ if line == "":
+ continue
+ elif line.startswith("-"):
+ negative_filters.append(line[1:])
+ else:
+ positive_filters.append(line)
+
+ return "--gtest_filter={}-{}".format(":".join(positive_filters),
+ ":".join(negative_filters))
+
+
class TestTarget(object):
"""TestTarget encapsulates a single BUILD.gn target, extracts a name from the
target string, and manages the building and running of the target for both
Linux and Fuchsia.
"""
- def __init__(self, target: str, filters: str = "") -> None:
- self.Target = target
- self.Name = target.split(":")[-1]
- if filters != "":
- self.FilterFlag = "--gtest_filter='" + filters + "'"
+ def __init__(self, target: str) -> None:
+ self._target = target
+ self._name = target.split(":")[-1]
+ self._filter_file = "testing/buildbot/filters/fuchsia.{}.filter".format(
+ self._name)
+ if not os.path.isfile(self._filter_file):
+ self._filter_flag = ""
+ self._filter_file = ""
else:
- self.FilterFlag = ""
+ self._filter_flag = ParseFilterFile(self._filter_file)
def ExecFuchsia(self, out_dir: str, run_locally: bool) -> str:
- runner_name = "{}/bin/run_{}".format(out_dir, self.Name)
- command = [runner_name, self.FilterFlag]
+ runner_name = "{}/bin/run_{}".format(out_dir, self._name)
+ command = [runner_name, self._filter_flag, "--exclude-system-logs"]
if not run_locally:
command.append("-d")
-
- # TODO(stephanstross): Remove this when fuchsia logging fix lands
- command.extend([
- "--test-launcher-summary-output", "/tmp/fuchsia.json", "--",
- "--gtest_output=json:/data/test_summary.json"
- ])
- return RunCommand(
- command,
- "Test {} failed on fuchsia!".format(self.Target),
- ignore_errors=True)
+ return RunCommand(command,
+ "Test {} failed on fuchsia!".format(self._target))
def ExecLinux(self, out_dir: str, run_locally: bool) -> str:
- local_path = "{}/{}".format(out_dir, self.Name)
- command = []
+ command = [] # type: List[str]
+ user = target_spec.linux_device_user
+ ip = target_spec.linux_device_ip
+ host_machine = "{0}@{1}".format(user, ip)
if not run_locally:
- user = target_spec.linux_device_user
- ip = target_spec.linux_device_hostname
- host_machine = "{0}@{1}".format(user, ip)
# Next is the transfer of all the directories to the destination device.
self.TransferDependencies(out_dir, host_machine)
command = [
- "ssh", "{}@{}".format(user, ip), "xvfb-run -a {1}/{0}/{1} {2}".format(
- out_dir, self.Name, self.FilterFlag)
+ "ssh", "{}@{}".format(user, ip), "{1}/{0}/{1} -- {2}".format(
+ out_dir, self._name, self._filter_flag)
]
else:
- command = [local_path, self.FilterFlag]
- result = RunCommand(
- command,
- "Test {} failed on linux!".format(self.Target),
- ignore_errors=True)
- # Clean up the copy of the test files on the host after execution
- RunCommand(["rm", "-rf", self.Name],
- "Failed to remove host directory for {}".format(self.Target))
- return result
+ local_path = "{}/{}".format(out_dir, self._name)
+ command = [local_path, "--", self._filter_flag]
+ return RunCommand(command, "Test {} failed on linux!".format(self._target))
def TransferDependencies(self, out_dir: str, host: str):
- gn_desc = ["gn", "desc", out_dir, self.Target, "runtime_deps"]
+ gn_desc = ["gn", "desc", out_dir, self._target, "runtime_deps"]
out = RunCommand(
- gn_desc, "Failed to get dependencies of target {}".format(self.Target))
+ gn_desc, "Failed to get dependencies of target {}".format(self._target))
paths = []
for line in out.split("\n"):
@@ -104,237 +116,65 @@ class TestTarget(object):
common = os.path.commonpath(paths)
paths = [os.path.relpath(path, common) for path in paths]
- archive_name = self.Name + ".tar.gz"
+ archive_name = self._name + ".tar.gz"
# Compress the dependencies of the test.
+ command = ["tar", "-czf", archive_name] + paths
+ if self._filter_file != "":
+ command.append(self._filter_file)
RunCommand(
- ["tar", "-czf", archive_name] + paths,
- "{} dependency compression failed".format(self.Target),
+ command,
+ "{} dependency compression failed".format(self._target),
)
# Make sure the containing directory exists on the host, for easy cleanup.
- RunCommand(["ssh", host, "mkdir -p {}".format(self.Name)],
- "Failed to create directory on host for {}".format(self.Target))
+ RunCommand(["ssh", host, "mkdir -p {}".format(self._name)],
+ "Failed to create directory on host for {}".format(self._target))
# Transfer the test deps to the host.
RunCommand(
- ["scp", archive_name, "{}:{}/{}".format(host, self.Name, archive_name)],
- "{} dependency transfer failed".format(self.Target),
+ [
+ "scp", archive_name, "{}:{}/{}".format(host, self._name,
+ archive_name)
+ ],
+ "{} dependency transfer failed".format(self._target),
)
# Decompress the dependencies once they're on the host.
RunCommand(
[
"ssh", host, "tar -xzf {0}/{1} -C {0}".format(
- self.Name, archive_name)
+ self._name, archive_name)
],
- "{} dependency decompression failed".format(self.Target),
+ "{} dependency decompression failed".format(self._target),
)
# Clean up the local copy of the archive that is no longer needed.
RunCommand(
["rm", archive_name],
- "{} dependency archive cleanup failed".format(self.Target),
+ "{} dependency archive cleanup failed".format(self._target),
)
-def ExtractParts(string: str) -> (str, float, str):
- """This function accepts lines like the one that follow this sentence, and
- attempts to extract all of the relevant pieces of information from it.
-
- task: 1_threads_scheduling_to_io_pump= .47606626678091973 us/task
-
- The above line would be split into chunks as follows:
-
- info=data units
-
- info and units can be any string, and data must be a valid float. data and
- units must be separated by a space, and info and data must be separated by
- at least an '='
- """
- pieces = string.split("=")
- info = pieces[0].strip()
- measure = pieces[1].strip().split(" ")
- data = float(measure[0])
- units = measure[1].strip()
- return info, data, units
-
-
-class ResultLine(object):
- """This class is a single line of the comparison between linux and fuchsia.
- GTests output several lines of important info per test, which are collected,
- and then the pertinent pieces of information are extracted and stored in a
- ResultLine for each line, containing a shared description and unit, as well as
- linux and fuchsia performance scores.
- """
+def RunTest(target: TestTarget, run_locally: bool = False) -> None:
+ linux_out = target.ExecLinux(target_spec.linux_out_dir, run_locally)
+ linux_result = test_results.TargetResultFromStdout(linux_out.splitlines(),
+ target._name)
+ print("Ran Linux")
+ fuchsia_out = target.ExecFuchsia(target_spec.fuchsia_out_dir, run_locally)
+ fuchsia_result = test_results.TargetResultFromStdout(fuchsia_out.splitlines(),
+ target._name)
+ print("Ran Fuchsia")
+ outname = "{}.{}.json".format(target._name, time.time())
+ linux_result.WriteToJson("{}/{}".format(target_spec.raw_linux_dir, outname))
+ fuchsia_result.WriteToJson("{}/{}".format(target_spec.raw_fuchsia_dir,
+ outname))
+ print("Wrote result files")
- def __init__(self, linux_line: str, fuchsia_line: str) -> None:
- linux_info, linux_val, linux_unit = ExtractParts(linux_line)
- fuchsia_info, fuchsia_val, fuchsia_unit = ExtractParts(fuchsia_line)
-
- if linux_info != fuchsia_info:
- print("Info mismatch! fuchsia was: {}".format(fuchsia_info))
- if linux_unit != fuchsia_unit:
- print("Unit mismatch! fuchsia was: {}".format(fuchsia_unit))
-
- self.desc = linux_info
- self.linux = linux_val
- self.fuchsia = fuchsia_val
- self.unit = fuchsia_unit
-
- def comparison(self) -> float:
- return (self.fuchsia / self.linux) * 100.0
-
- def ToCsvFormat(self) -> str:
- return ",".join([
- self.desc.replace(",", ";"),
- str(self.linux),
- str(self.fuchsia),
- str(self.comparison()),
- self.unit,
- ])
-
- def __format__(self, format_spec: str) -> str:
- return "{} in {}: linux:{}, fuchsia:{}, ratio:{}".format(
- self.desc, self.unit, self.linux, self.fuchsia, self.comparison())
-
-
-class TestComparison(object):
- """This class represents a single test target, and all of its informative
- lines of output for each test case, extracted into statistical comparisons of
- this run on linux v fuchsia.
- """
-
- def __init__(self, name: str, tests: Dict[str, List[ResultLine]]) -> None:
- self.suite_name = name
- self.tests = tests
-
- def MakeCsvFormat(self) -> str:
- lines = []
- for test_name, lines in self.tests.items():
- for line in lines:
- lines.append("{},{},{}".format(self.suite_name, test_name,
- line.MakeCsvFormat()))
- return "\n".join(lines)
-
- def __format__(self, format_spec: str) -> str:
- lines = [self.suite_name]
- for test_case, lines in self.tests.items():
- lines.append(" {}".format(test_case))
- for line in lines:
- lines.append(" {}".format(line))
- return "\n".join(lines)
-
-
-def ExtractCases(out_lines: List[str]) -> Dict[str, List[str]]:
- """ExtractCases attempts to associate GTest names to the lines of output that
- they produce. Given a list of input like the following:
-
- [==========] Running 24 tests from 10 test cases.
- [----------] Global test environment set-up.
- [----------] 9 tests from ScheduleWorkTest
- [ RUN ] ScheduleWorkTest.ThreadTimeToIOFromOneThread
- *RESULT task: 1_threads_scheduling_to_io_pump= .47606626678091973 us/task
- RESULT task_min_batch_time: 1_threads_scheduling_to_io_pump= .335 us/task
- RESULT task_max_batch_time: 1_threads_scheduling_to_io_pump= 5.071 us/task
- *RESULT task_thread_time: 1_threads_scheduling_to_io_pump= .3908787013 us/task
- [ OK ] ScheduleWorkTest.ThreadTimeToIOFromOneThread (5352 ms)
- [ RUN ] ScheduleWorkTest.ThreadTimeToIOFromTwoThreads
- *RESULT task: 2_threads_scheduling_to_io_pump= 6.216794903666874 us/task
- RESULT task_min_batch_time: 2_threads_scheduling_to_io_pump= 2.523 us/task
- RESULT task_max_batch_time: 2_threads_scheduling_to_io_pump= 142.989 us/task
- *RESULT task_thread_time: 2_threads_scheduling_to_io_pump= 2.02621823 us/task
- [ OK ] ScheduleWorkTest.ThreadTimeToIOFromTwoThreads (5022 ms)
- [ RUN ] ScheduleWorkTest.ThreadTimeToIOFromFourThreads
-
- It will first skip all lines which do not contain either RUN or RESULT.
- Then, each 'RUN' line is stripped of the bracketed portion, down to just the
- name of the test, and then placed into a dictionary that maps it to all the
- lines beneath it, up to the next RUN line. The RESULT lines all have their
- RESULT portions chopped out as well, and only the piece following RESULT is
- kept
-
- {'ScheduleWorkTest.ThreadTimeToIOFromOneThread':[
- 'task: 1_threads_scheduling_to_io_pump= .47606626678091973 us/task',
- 'task_min_batch_time: 1_threads_scheduling_to_io_pump= .335 us/task',
- 'task_max_batch_time: 1_threads_scheduling_to_io_pump= 5.071 us/task',
- 'task_thread_time: 1_threads_scheduling_to_io_pump= .390834314 us/task'],
- 'ScheduleWorkTest.ThreadTimeToIOFromTwoThreads':[
- 'task: 2_threads_scheduling_to_io_pump= 6.216794903666874 us/task',
- 'task_min_batch_time: 2_threads_scheduling_to_io_pump= 2.523 us/task',
- 'task_max_batch_time: 2_threads_scheduling_to_io_pump= 142.989 us/task',
- 'task_thread_time: 2_threads_scheduling_to_io_pump= 2.02620013 us/task'],
- 'ScheduleWorkTest.ThreadTimeToIOFromFourThreads':[]}
- """
- lines = []
- for line in out_lines:
- if "RUN" in line or "RESULT" in line:
- lines.append(line)
- cases = {}
- name = ""
- case_lines = []
- for line in lines:
- # We've hit a new test suite, write the old accumulators and start new
- # ones. The name variable is checked to make sure this isn't the first one
- # in the list of lines
- if "RUN" in line:
- if name != "":
- cases[name] = case_lines
- case_lines = []
- name = line.split("]")[-1] # Get the actual name of the test case.
- else:
- if "RESULT" not in line:
- print("{} did not get filtered!".format(line))
- line_trimmed = line.split("RESULT")[-1].strip()
- case_lines.append(line_trimmed)
- return cases
-
-
-def CollateTests(linux_lines: List[str], fuchsia_lines: List[str],
- test_target: str) -> TestComparison:
- """This function takes the GTest output of a single test target, and matches
- the informational sections of the outputs together, before collapsing them
- down into ResultLines attached to TestComparisons.
- """
-
- linux_cases = ExtractCases(linux_lines)
- fuchsia_cases = ExtractCases(fuchsia_lines)
-
- comparisons = {}
- for case_name, linux_case_lines in linux_cases.items():
- # If fuchsia didn't contain that test case, skip it, but alert the user.
- if not case_name in fuchsia_cases:
- print("Fuchsia is missing test case {}".format(case_name))
- continue
-
- fuchsia_case_lines = fuchsia_cases[case_name]
-
- # Each test case should output its informational lines in the same order, so
- # if tests only produce partial output, any tailing info should be dropped,
- # and only data that was produced by both tests will be compared.
- paired_case_lines = zip(linux_case_lines, fuchsia_case_lines)
- if len(linux_case_lines) != len(fuchsia_case_lines):
- print("Linux and Fuchsia have produced different output lengths for the "
- "test {}!".format(case_name))
- desc_lines = [ResultLine(*pair) for pair in paired_case_lines]
- comparisons[case_name] = desc_lines
-
- for case_name in fuchsia_cases.keys():
- if case_name not in comparisons.keys():
- print("Linux is missing test case {}".format(case_name))
-
- return TestComparison(test_target, comparisons)
-
-
-def RunTest(target: TestTarget, run_locally: bool = False) -> TestComparison:
-
- linux_output = target.ExecLinux(target_spec.linux_out_dir, run_locally)
- fuchsia_output = target.ExecFuchsia(target_spec.fuchsia_out_dir, run_locally)
- return CollateTests(
- linux_output.split("\n"), fuchsia_output.split("\n"), target.Name)
-
-
-def RunGnForDirectory(dir_name: str, target_os: str) -> None:
+def RunGnForDirectory(dir_name: str, target_os: str, is_debug: bool) -> None:
if not os.path.exists(dir_name):
os.makedirs(dir_name)
+
+ debug_str = str(is_debug).lower()
+
with open("{}/{}".format(dir_name, "args.gn"), "w") as args_file:
- args_file.write("is_debug = false\n")
+ args_file.write("is_debug = {}\n".format(debug_str))
args_file.write("dcheck_always_on = false\n")
args_file.write("is_component_build = false\n")
args_file.write("use_goma = true\n")
@@ -343,48 +183,76 @@ def RunGnForDirectory(dir_name: str, target_os: str) -> None:
subprocess.run(["gn", "gen", dir_name]).check_returncode()
-def GenerateTestData() -> List[List[TestComparison]]:
+def GenerateTestData(do_config: bool, do_build: bool, num_reps: int,
+ is_debug: bool):
DIR_SOURCE_ROOT = os.path.abspath(
os.path.join(os.path.dirname(__file__), *([os.pardir] * 3)))
os.chdir(DIR_SOURCE_ROOT)
-
+ os.makedirs(target_spec.results_dir, exist_ok=True)
+ os.makedirs(target_spec.raw_linux_dir, exist_ok=True)
+ os.makedirs(target_spec.raw_fuchsia_dir, exist_ok=True)
# Grab parameters from config file.
linux_dir = target_spec.linux_out_dir
fuchsia_dir = target_spec.fuchsia_out_dir
- test_input = []
- for (test, filters) in target_spec.test_targets.items():
- test_input.append(TestTarget(test, filters))
- print("Test targets collected:\n{}".format("\n".join(
- [test.Target for test in test_input])))
-
- RunGnForDirectory(linux_dir, "linux")
- RunGnForDirectory(fuchsia_dir, "fuchsia")
-
- # Build test targets in both output directories.
- for directory in [linux_dir, fuchsia_dir]:
- build_command = ["autoninja", "-C", directory] \
- + [test.Target for test in test_input]
- RunCommand(
- build_command,
- "Unable to build targets in directory {}".format(directory),
- )
- print("Builds completed.")
+ test_input = [] # type: List[TestTarget]
+ for target in target_spec.test_targets:
+ test_input.append(TestTarget(target))
+ print("Test targets collected:\n{}".format(",".join(
+ [test._target for test in test_input])))
+ if do_config:
+ RunGnForDirectory(linux_dir, "linux", is_debug)
+ RunGnForDirectory(fuchsia_dir, "fuchsia", is_debug)
+ print("Ran GN")
+ elif is_debug:
+ logging.warning("The --is_debug flag is ignored unless --do_config is also \
+ specified")
+
+ if do_build:
+ # Build test targets in both output directories.
+ for directory in [linux_dir, fuchsia_dir]:
+ build_command = ["autoninja", "-C", directory] \
+ + [test._target for test in test_input]
+ RunCommand(build_command,
+ "autoninja failed in directory {}".format(directory))
+ print("Builds completed.")
# Execute the tests, one at a time, per system, and collect their results.
- results = []
- print("Running Tests")
- for test in test_input:
- results.append(RunTest(test))
+ for i in range(0, num_reps):
+ print("Running Test set {}".format(i))
+ for test_target in test_input:
+ print("Running Target {}".format(test_target._name))
+ RunTest(test_target)
+ print("Finished {}".format(test_target._name))
print("Tests Completed")
- with open("comparison_results.csv", "w") as out_file:
- out_file.write(
- "target,test,description,linux,fuchsia,fuchsia/linux,units\n")
- for result in results:
- out_file.write(result.MakeCsvFormat())
- out_file.write("\n")
- return results
+
+
+def main() -> int:
+ cmd_flags = argparse.ArgumentParser(
+ description="Execute tests repeatedly and collect performance data.")
+ cmd_flags.add_argument(
+ "--do-config",
+ action="store_true",
+ help="WARNING: This flag over-writes args.gn in the directories "
+ "configured. GN is executed before running the tests.")
+ cmd_flags.add_argument(
+ "--do-build",
+ action="store_true",
+ help="Build the tests before running them.")
+ cmd_flags.add_argument(
+ "--is-debug",
+ action="store_true",
+ help="This config-and-build cycle is a debug build")
+ cmd_flags.add_argument(
+ "--num-repetitions",
+ type=int,
+ default=1,
+ help="The number of times to execute each test target.")
+ cmd_flags.parse_args()
+ GenerateTestData(cmd_flags.do_config, cmd_flags.do_build,
+ cmd_flags.num_repetitions, cmd_flags.is_debug)
+ return 0
if __name__ == "__main__":
- sys.exit(GenerateTestData())
+ sys.exit(main())
diff --git a/chromium/tools/fuchsia/comparative_tester/generate_perf_report.py b/chromium/tools/fuchsia/comparative_tester/generate_perf_report.py
new file mode 100755
index 00000000000..3a461d03ea6
--- /dev/null
+++ b/chromium/tools/fuchsia/comparative_tester/generate_perf_report.py
@@ -0,0 +1,289 @@
+#!/usr/bin/env python3
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""generate_perf_report.py is to be used after comparative_tester.py has been
+executed and written some test data into the location specified by
+target_spec.py. It writes to results_dir and reads all present test info from
+raw_data_dir. Using this script should just be a matter of invoking it from
+chromium/src while raw test data exists in raw_data_dir."""
+
+import json
+import logging
+import math
+import os
+import sys
+from typing import List, Dict, Set, Tuple, Optional, Any, TypeVar, Callable
+
+import target_spec
+from test_results import (TargetResult, ReadTargetFromJson, TestResult,
+ ResultLine)
+
+
+class LineStats(object):
+
+ def __init__(self, desc: str, unit: str, time_avg: float, time_dev: float,
+ cv: float, samples: int) -> None:
+ self.desc = desc
+ self.time_avg = time_avg
+ self.time_dev = time_dev
+ self.cv = cv
+ self.unit = unit
+ self.sample_num = samples
+
+ def ToString(self) -> str:
+ if self.sample_num > 1:
+ return "{}: {:.5f} σ={:.5f} {} with n={} cv={}".format(
+ self.desc, self.time_avg, self.time_dev, self.unit, self.sample_num,
+ self.cv)
+ else:
+ return "{}: {:.5f} with only one sample".format(self.desc, self.time_avg)
+
+
+def LineFromList(lines: List[ResultLine]) -> Optional[LineStats]:
+ desc = lines[0].desc
+ unit = lines[0].unit
+ times = [line.meas for line in lines]
+ avg, dev, cv = GenStats(times)
+ return LineStats(desc, unit, avg, dev, cv, len(lines))
+
+
+class TestStats(object):
+
+ def __init__(self, name: str, time_avg: float, time_dev: float, cv: float,
+ samples: int, lines: List[LineStats]) -> None:
+ self.name = name
+ self.time_avg = time_avg
+ self.time_dev = time_dev
+ self.cv = cv
+ self.sample_num = samples
+ self.lines = lines
+
+ def ToLines(self) -> List[str]:
+ lines = []
+ if self.sample_num > 1:
+ lines.append("{}: {:.5f} σ={:.5f}ms with n={} cv={}".format(
+ self.name, self.time_avg, self.time_dev, self.sample_num, self.cv))
+ else:
+ lines.append("{}: {:.5f} with only one sample".format(
+ self.name, self.time_avg))
+ for line in self.lines:
+ lines.append(" {}".format(line.ToString()))
+ return lines
+
+
+def TestFromList(tests: List[TestResult]) -> TestStats:
+ name = tests[0].name
+ avg, dev, cv = GenStats([test.time for test in tests])
+ lines = {} # type: Dict[str, List[ResultLine]]
+ for test in tests:
+ assert test.name == name
+ for line in test.lines:
+ if not line.desc in lines:
+ lines[line.desc] = [line]
+ else:
+ lines[line.desc].append(line)
+ test_lines = []
+ for _, line_list in lines.items():
+ stat_line = LineFromList(line_list)
+ if stat_line:
+ test_lines.append(stat_line)
+ return TestStats(name, avg, dev, cv, len(tests), test_lines)
+
+
+class TargetStats(object):
+
+ def __init__(self, name: str, samples: int, tests: List[TestStats]) -> None:
+ self.name = name
+ self.sample_num = samples
+ self.tests = tests
+
+ def ToLines(self) -> List[str]:
+ lines = []
+ if self.sample_num > 1:
+ lines.append("{}: ".format(self.name))
+ else:
+ lines.append("{}: with only one sample".format(self.name))
+ for test in self.tests:
+ for line in test.ToLines():
+ lines.append(" {}".format(line))
+ return lines
+
+ def __format__(self, format_spec):
+ return "\n".join(self.ToLines())
+
+
+def TargetFromList(results: List[TargetResult]) -> TargetStats:
+ name = results[0].name
+ sample_num = len(results)
+ tests = {} # type: Dict[str, List[TestResult]]
+ for result in results:
+ assert result.name == name
+ # This groups tests by name so that they can be considered independently,
+ # so that in the event tests flake out, their average times can
+ # still be accurately calculated
+ for test in result.tests:
+ if not test.name in tests.keys():
+ tests[test.name] = [test]
+ tests[test.name].append(test)
+ test_stats = [TestFromList(test_list) for _, test_list in tests.items()]
+ return TargetStats(name, sample_num, test_stats)
+
+
+def GenStats(corpus: List[float]) -> Tuple[float, float, float]:
+ avg = sum(corpus) / len(corpus)
+ adjusted_sum = 0.0
+ for item in corpus:
+ adjusted = item - avg
+ adjusted_sum += adjusted * adjusted
+
+ dev = math.sqrt(adjusted_sum / len(corpus))
+ cv = dev / avg
+ return avg, dev, cv
+
+
+def DirectoryStats(directory: str) -> List[TargetStats]:
+ resultMap = {} # type: Dict[str, List[TargetResult]]
+ for file in os.listdir(directory):
+ results = ReadTargetFromJson("{}/{}".format(directory, file))
+ if not results.name in resultMap.keys():
+ resultMap[results.name] = [results]
+ else:
+ resultMap[results.name].append(results)
+
+ targets = []
+ for _, resultList in resultMap.items():
+ targets.append(TargetFromList(resultList))
+ return targets
+
+
+def CompareTargets(linux: TargetStats, fuchsia: TargetStats) -> Dict[str, Any]:
+ """Compare takes a corpus of statistics from both Fuchsia and Linux, and then
+ lines up the values, compares them to each other, and writes them into a
+ dictionary that can be JSONified.
+ """
+ assert linux.name == fuchsia.name
+ paired_tests = ZipListsByPredicate(linux.tests, fuchsia.tests,
+ lambda test: test.name)
+
+ paired_tests = MapDictValues(paired_tests, CompareTests)
+ return {"name": linux.name, "tests": paired_tests}
+
+
+def CompareTests(linux: TestStats, fuchsia: TestStats) -> Dict[str, Any]:
+ assert linux != None or fuchsia != None
+ if linux != None and fuchsia != None:
+ assert linux.name == fuchsia.name
+ paired_lines = ZipListsByPredicate(linux.lines, fuchsia.lines,
+ lambda line: line.desc)
+ paired_lines = MapDictValues(paired_lines, CompareLines)
+ result = {"lines": paired_lines, "unit": "ms"} # type: Dict[str, Any]
+
+ if linux:
+ result["name"] = linux.name
+ result["linux_avg"] = linux.time_avg
+ result["linux_dev"] = linux.time_dev
+ result["linux_cv"] = linux.cv
+
+ if fuchsia == None:
+ logging.warning("Fuchsia is missing test case {}".format(linux.name))
+ else:
+ result["name"] = fuchsia.name
+ result["fuchsia_avg"] = fuchsia.time_avg
+ result["fuchsia_dev"] = fuchsia.time_dev
+ result["fuchsia_cv"] = fuchsia.cv
+
+
+def CompareLines(linux: LineStats, fuchsia: LineStats) -> Dict[str, Any]:
+ """CompareLines wraps two LineStats objects up as a JSON-dumpable dict, with
+ missing values written as -1 (which specifically doesn't make sense for time
+ elapsed measurements). It also logs a warning every time a line is given which
+ can't be matched up. If both lines passed are None, or their units or
+ descriptions are not the same(which should never happen) this function fails.
+ """
+ assert linux != None or fuchsia != None
+ result = {} # type: Dict[str, Any]
+ if linux != None and fuchsia != None:
+ assert linux.desc == fuchsia.desc
+ assert linux.unit == fuchsia.unit
+
+ if linux:
+ result["desc"] = linux.desc
+ result["unit"] = linux.unit
+ result["linux_avg"] = linux.time_avg
+ result["linux_dev"] = linux.time_dev
+ result["linux_cv"] = linux.cv
+
+ if fuchsia == None:
+ logging.warning("Fuchsia is missing test line {}".format(linux.desc))
+ else:
+ result["desc"] = fuchsia.desc
+ result["unit"] = fuchsia.unit
+ result["fuchsia_avg"] = fuchsia.time_avg
+ result["fuchsia_dev"] = fuchsia.time_dev
+ result["fuchsia_cv"] = fuchsia.cv
+
+ return result
+
+
+T = TypeVar("T")
+R = TypeVar("R")
+
+
+def ZipListsByPredicate(left: List[T], right: List[T],
+ pred: Callable[[T], R]) -> Dict[R, Tuple[T, T]]:
+ """This function takes two lists, and a predicate. The predicate is applied to
+ the values in both lists to obtain a keying value from them. Each item is then
+ inserted into the returned dictionary using the obtained key. Finally, after
+ all items have been added to the dict, any items that do not have a pair are
+ discarded after warning the user, and the new dictionary is returned. The
+ predicate should not map multiple values from one list to the same key.
+ """
+ paired_items = {} # type: Dict [R, Tuple[T, T]]
+ for item in left:
+ key = pred(item)
+ # the first list shouldn't cause any key collisions
+ assert key not in paired_items.keys()
+ paired_items[key] = item, None
+
+ for item in right:
+ key = pred(item)
+ if key in paired_items.keys():
+ # elem 1 of the tuple is always None if the key exists in the map
+ prev, _ = paired_items[key]
+ paired_items[key] = prev, item
+ else:
+ paired_items[key] = None, item
+
+ return paired_items
+
+
+U = TypeVar("U")
+V = TypeVar("V")
+
+
+def MapDictValues(dct: Dict[T, Tuple[R, U]],
+ predicate: Callable[[R, U], V]) -> Dict[T, V]:
+ """This function applies the predicate to all the values in the dictionary,
+ returning a new dictionary with the new values.
+ """
+ out_dict = {}
+ for key, val in dct.items():
+ out_dict[key] = predicate(*val)
+ return out_dict
+
+
+def main():
+ linux_avgs = DirectoryStats(target_spec.raw_linux_dir)
+ fuchsia_avgs = DirectoryStats(target_spec.raw_fuchsia_dir)
+ paired_targets = ZipListsByPredicate(linux_avgs, fuchsia_avgs,
+ lambda target: target.name)
+ for name, targets in paired_targets.items():
+ comparison_dict = CompareTargets(*targets)
+ with open("{}/{}.json".format(target_spec.results_dir, name),
+ "w") as outfile:
+ json.dump(comparison_dict, outfile, indent=2)
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/chromium/tools/fuchsia/comparative_tester/target_spec.py b/chromium/tools/fuchsia/comparative_tester/target_spec.py
index 0aac16ba1ec..d0122cd4cc7 100644
--- a/chromium/tools/fuchsia/comparative_tester/target_spec.py
+++ b/chromium/tools/fuchsia/comparative_tester/target_spec.py
@@ -3,17 +3,24 @@
# found in the LICENSE file.
# Fields for use when working with a physical linux device connected locally
-linux_device_hostname = "192.168.42.32"
+linux_device_ip = "192.168.42.32"
linux_device_user = "potat"
+fuchsia_device_ip = "192.168.42.64"
+
+# The linux build directory.
linux_out_dir = "out/default"
+# The fuchsia build directory.
fuchsia_out_dir = "out/fuchsia"
+# The location in src that will store final statistical data on perftest results
+results_dir = "results"
+# The location in src that stores the information from each comparative
+# invocation of a perftest
+raw_linux_dir = results_dir + "/linux_raw"
+raw_fuchsia_dir = results_dir + "/fuchsia_raw"
-# A map of test target names to a list of test filters to be passed to
-# --gtest_filter. Stick to *_perftests. Also, whoo implicit string
-# joining!
-test_targets = {
- "base:base_perftests": "-WaitableEventPerfTest.Throughput"
- ":MessageLoopPerfTest.PostTaskRate/1_Posting_Thread",
- "net:net_perftests": "",
-}
+# A list of test targets to deploy to both devices. Stick to *_perftests.
+test_targets = [
+ "base:base_perftests",
+ "net:net_perftests",
+]
diff --git a/chromium/tools/fuchsia/comparative_tester/test_results.py b/chromium/tools/fuchsia/comparative_tester/test_results.py
new file mode 100644
index 00000000000..6bd5dc9336b
--- /dev/null
+++ b/chromium/tools/fuchsia/comparative_tester/test_results.py
@@ -0,0 +1,186 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import json
+import logging
+import os
+
+from typing import Any, Dict, List, Tuple, Optional
+
+
+def UnitStringIsValid(unit: str) -> bool:
+ accepted_units = [
+ "us/hop", "us/task", "ns/sample", "ms", "s", "count", "KB", "MB/s", "us"
+ ]
+ return unit in accepted_units
+
+
+class ResultLine(object):
+ """ResultLine objects are each an individual line of output, complete with a
+ unit, measurement, and descriptive component
+ """
+
+ def __init__(self, desc: str, measure: float, unit: str) -> None:
+ self.desc = desc
+ self.meas = measure
+ self.unit = unit
+
+ def ToJsonDict(self) -> Dict[str, Any]:
+ return {
+ "description": self.desc,
+ "measurement": self.meas,
+ "unit": self.unit,
+ }
+
+
+def ReadResultLineFromJson(dct: Dict[str, Any]):
+ return ResultLine(dct["description"], float(dct["measurement"]), dct["unit"])
+
+
+def ResultLineFromStdout(line: str) -> Optional[ResultLine]:
+ if "pkgsvr" in line:
+ return None
+ chunks = line.split()
+ # There should be 1 chunk for the measure, 1 for the unit, and at least one
+ # for the line description, so at least 3 total
+ if len(chunks) < 3:
+ logging.warning("The line {} contains too few space-separated pieces to be "
+ "parsed as a ResultLine".format(line))
+ return None
+ unit = chunks[-1]
+ if not UnitStringIsValid(unit):
+ logging.warning("The unit string parsed from {} was {}, which was not "
+ "expected".format(line, unit))
+ return None
+ try:
+ measure = float(chunks[-2])
+ desc = " ".join(chunks[:-2])
+ return ResultLine(desc, measure, unit)
+ except ValueError as e:
+ logging.warning("The chunk {} could not be parsed as a valid measurement "
+ "because of {}".format(chunks[-2], str(e)))
+ return None
+
+
+class TestResult(object):
+ """TestResult objects comprise the smallest unit of a GTest target, and
+ contain the name of the individual test run, and the time that the test took
+ to run."""
+
+ def __init__(self, name: str, time: float, lines: List[ResultLine]) -> None:
+ self.name = name
+ self.time = time
+ self.lines = lines
+
+ def ToJsonDict(self) -> Dict[str, Any]:
+ return {
+ "name": self.name,
+ "time_in_ms": self.time,
+ "lines": [line.ToJsonDict() for line in self.lines]
+ }
+
+
+def ReadTestFromJson(obj_dict: Dict[str, Any]) -> TestResult:
+ name = obj_dict["name"]
+ time = obj_dict["time_in_ms"]
+ lines = [ReadResultLineFromJson(line) for line in obj_dict["lines"]]
+ return TestResult(name, time, lines)
+
+
+def ExtractTestInfo(line: str) -> Tuple[str, float]:
+ # Trim off the [ OK ] part of the line
+ trimmed = line.lstrip("[ OK ]").strip()
+ try:
+ test_name, rest = trimmed.split("(") # Isolate the measurement
+ except Exception as e:
+ err_text = "Could not extract the case name from {} because of error {}"\
+ .format(trimmed, str(e))
+ raise Exception(err_text)
+ try:
+ measure, _ = rest.split(")", 1)[0].split()
+ except Exception as e:
+ err_text = "Could not extract measure and units from {}\
+ because of error {}".format(rest, str(e))
+ raise Exception(err_text)
+ return test_name.strip(), float(measure)
+
+
+def TaggedTestFromLines(lines: List[str]) -> TestResult:
+ test_name, time = ExtractTestInfo(lines[-1])
+ res_lines = []
+ for line in lines[:-1]:
+ res_line = ResultLineFromStdout(line)
+ if res_line:
+ res_lines.append(res_line)
+ else:
+ logging.warning("Couldn't parse line {} into a ResultLine".format(line))
+ return TestResult(test_name, time, res_lines)
+
+
+class TargetResult(object):
+ """TargetResult objects contain the entire set of TestSuite objects that are
+ invoked by a single test target, such as base:base_perftests and the like.
+ They also include the name of the target, and the time it took the target to
+ run.
+ """
+
+ def __init__(self, name: str, tests: List[TestResult]) -> None:
+ self.name = name
+ self.tests = tests
+
+ def ToJsonDict(self) -> Dict[str, Any]:
+ return {
+ "name": self.name,
+ "tests": [test.ToJsonDict() for test in self.tests]
+ }
+
+ def WriteToJson(self, path: str) -> None:
+ with open(path, "w") as outfile:
+ json.dump(self.ToJsonDict(), outfile, indent=2)
+
+
+def ReadTargetFromJson(path: str):
+ with open(path, "r") as json_file:
+ dct = json.load(json_file)
+ return TargetResult(
+ dct["name"], [ReadTestFromJson(test_dct) for test_dct in dct["tests"]])
+
+
+def TargetResultFromStdout(lines: List[str], name: str) -> TargetResult:
+ """TargetResultFromStdout attempts to associate GTest names to the lines of
+ output that they produce. Example input looks something like the following:
+
+ [ RUN ] TestNameFoo
+ INFO measurement units
+ ...
+ [ OK ] TestNameFoo (measurement units)
+ ...
+
+ Unfortunately, Because the results of output from perftest targets is not
+ necessarily consistent between test targets, this makes a best-effort to parse
+ as much information from them as possible.
+ """
+ test_line_lists = [] # type: List[List[str]]
+ test_line_accum = [] # type: List[str]
+ read_lines = False
+ for line in lines:
+ # We're starting a test suite
+ if line.startswith("[ RUN ]"):
+ read_lines = True
+ # We have a prior suite that needs to be added
+ if len(test_line_accum) > 0:
+ test_line_lists.append(test_line_accum)
+ test_line_accum = []
+ elif read_lines:
+ # We don't actually care about the data in the RUN line, just its
+ # presence. the OK line contains the same info, as well as the total test
+ # run time
+ test_line_accum.append(line)
+ if line.startswith("[ OK ]"):
+ read_lines = False
+
+ test_cases = [
+ TaggedTestFromLines(test_lines) for test_lines in test_line_lists
+ ]
+ return TargetResult(name, test_cases)
diff --git a/chromium/tools/fuchsia/local-sdk.py b/chromium/tools/fuchsia/local-sdk.py
index 9d9cd6d59d6..6751ba047c2 100755
--- a/chromium/tools/fuchsia/local-sdk.py
+++ b/chromium/tools/fuchsia/local-sdk.py
@@ -56,7 +56,7 @@ def main(args):
tempdir = tempfile.mkdtemp()
sdk_tar = os.path.join(tempdir, 'fuchsia-sdk.tgz')
- Run('go', 'run', 'scripts/makesdk.go', '-output', sdk_tar, '.')
+ Run('go', 'run', 'scripts/sdk/foundation/makesdk.go', '-output', sdk_tar, '.')
# Nuke the SDK from DEPS, put our just-built one there, and set a fake .hash
# file. This means that on next gclient runhooks, we'll restore to the
diff --git a/chromium/tools/gdb/gdbinit b/chromium/tools/gdb/gdbinit
index 44b3195c3c7..039ced9f32c 100644
--- a/chromium/tools/gdb/gdbinit
+++ b/chromium/tools/gdb/gdbinit
@@ -1,5 +1,5 @@
-# This is gdbinit for source level debugging with -fdebug-prefix-map compile
-# option.
+# This is gdbinit for source level debugging with -fdebug-compilation-dir
+# compile option.
python
diff --git a/chromium/tools/gn/BUILD.gn b/chromium/tools/gn/BUILD.gn
deleted file mode 100644
index 1e171fa941c..00000000000
--- a/chromium/tools/gn/BUILD.gn
+++ /dev/null
@@ -1,374 +0,0 @@
-# Copyright (c) 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/jumbo.gni")
-import("//testing/test.gni")
-import("//testing/libfuzzer/fuzzer_test.gni")
-
-jumbo_static_library("gn_lib") {
- configs += [ "//build/config:precompiled_headers" ]
-
- sources = [
- "action_target_generator.cc",
- "action_target_generator.h",
- "action_values.cc",
- "action_values.h",
- "analyzer.cc",
- "analyzer.h",
- "args.cc",
- "args.h",
- "binary_target_generator.cc",
- "binary_target_generator.h",
- "build_settings.cc",
- "build_settings.h",
- "builder.cc",
- "builder.h",
- "builder_record.cc",
- "builder_record.h",
- "bundle_data.cc",
- "bundle_data.h",
- "bundle_data_target_generator.cc",
- "bundle_data_target_generator.h",
- "bundle_file_rule.cc",
- "bundle_file_rule.h",
- "c_include_iterator.cc",
- "c_include_iterator.h",
- "command_analyze.cc",
- "command_args.cc",
- "command_check.cc",
- "command_clean.cc",
- "command_desc.cc",
- "command_format.cc",
- "command_format.h",
- "command_gen.cc",
- "command_help.cc",
- "command_ls.cc",
- "command_path.cc",
- "command_refs.cc",
- "commands.cc",
- "commands.h",
- "config.cc",
- "config.h",
- "config_values.cc",
- "config_values.h",
- "config_values_extractors.cc",
- "config_values_extractors.h",
- "config_values_generator.cc",
- "config_values_generator.h",
- "copy_target_generator.cc",
- "copy_target_generator.h",
- "create_bundle_target_generator.cc",
- "create_bundle_target_generator.h",
- "deps_iterator.cc",
- "deps_iterator.h",
- "desc_builder.cc",
- "desc_builder.h",
- "eclipse_writer.cc",
- "eclipse_writer.h",
- "err.cc",
- "err.h",
- "escape.cc",
- "escape.h",
- "exec_process.cc",
- "exec_process.h",
- "filesystem_utils.cc",
- "filesystem_utils.h",
- "function_exec_script.cc",
- "function_foreach.cc",
- "function_forward_variables_from.cc",
- "function_get_label_info.cc",
- "function_get_path_info.cc",
- "function_get_target_outputs.cc",
- "function_process_file_template.cc",
- "function_read_file.cc",
- "function_rebase_path.cc",
- "function_set_default_toolchain.cc",
- "function_set_defaults.cc",
- "function_template.cc",
- "function_toolchain.cc",
- "function_write_file.cc",
- "functions.cc",
- "functions.h",
- "functions_target.cc",
- "group_target_generator.cc",
- "group_target_generator.h",
- "header_checker.cc",
- "header_checker.h",
- "import_manager.cc",
- "import_manager.h",
- "inherited_libraries.cc",
- "inherited_libraries.h",
- "input_conversion.cc",
- "input_conversion.h",
- "input_file.cc",
- "input_file.h",
- "input_file_manager.cc",
- "input_file_manager.h",
- "item.cc",
- "item.h",
- "json_project_writer.cc",
- "json_project_writer.h",
- "label.cc",
- "label.h",
- "label_pattern.cc",
- "label_pattern.h",
- "label_ptr.h",
- "lib_file.cc",
- "lib_file.h",
- "loader.cc",
- "loader.h",
- "location.cc",
- "location.h",
- "ninja_action_target_writer.cc",
- "ninja_action_target_writer.h",
- "ninja_binary_target_writer.cc",
- "ninja_binary_target_writer.h",
- "ninja_build_writer.cc",
- "ninja_build_writer.h",
- "ninja_bundle_data_target_writer.cc",
- "ninja_bundle_data_target_writer.h",
- "ninja_copy_target_writer.cc",
- "ninja_copy_target_writer.h",
- "ninja_create_bundle_target_writer.cc",
- "ninja_create_bundle_target_writer.h",
- "ninja_group_target_writer.cc",
- "ninja_group_target_writer.h",
- "ninja_target_writer.cc",
- "ninja_target_writer.h",
- "ninja_toolchain_writer.cc",
- "ninja_toolchain_writer.h",
- "ninja_utils.cc",
- "ninja_utils.h",
- "ninja_writer.cc",
- "ninja_writer.h",
- "operators.cc",
- "operators.h",
- "output_file.cc",
- "output_file.h",
- "parse_node_value_adapter.cc",
- "parse_node_value_adapter.h",
- "parse_tree.cc",
- "parse_tree.h",
- "parser.cc",
- "parser.h",
- "path_output.cc",
- "path_output.h",
- "pattern.cc",
- "pattern.h",
- "pool.cc",
- "pool.h",
- "qt_creator_writer.cc",
- "qt_creator_writer.h",
- "runtime_deps.cc",
- "runtime_deps.h",
- "scheduler.cc",
- "scheduler.h",
- "scope.cc",
- "scope.h",
- "scope_per_file_provider.cc",
- "scope_per_file_provider.h",
- "settings.cc",
- "settings.h",
- "setup.cc",
- "setup.h",
- "source_dir.cc",
- "source_dir.h",
- "source_file.cc",
- "source_file.h",
- "source_file_type.cc",
- "source_file_type.h",
- "standard_out.cc",
- "standard_out.h",
- "string_utils.cc",
- "string_utils.h",
- "substitution_list.cc",
- "substitution_list.h",
- "substitution_pattern.cc",
- "substitution_pattern.h",
- "substitution_type.cc",
- "substitution_type.h",
- "substitution_writer.cc",
- "substitution_writer.h",
- "switches.cc",
- "switches.h",
- "target.cc",
- "target.h",
- "target_generator.cc",
- "target_generator.h",
- "template.cc",
- "template.h",
- "token.cc",
- "token.h",
- "tokenizer.cc",
- "tokenizer.h",
- "tool.cc",
- "tool.h",
- "toolchain.cc",
- "toolchain.h",
- "trace.cc",
- "trace.h",
- "unique_vector.h",
- "value.cc",
- "value.h",
- "value_extractors.cc",
- "value_extractors.h",
- "variables.cc",
- "variables.h",
- "visibility.cc",
- "visibility.h",
- "visual_studio_utils.cc",
- "visual_studio_utils.h",
- "visual_studio_writer.cc",
- "visual_studio_writer.h",
- "xcode_object.cc",
- "xcode_object.h",
- "xcode_writer.cc",
- "xcode_writer.h",
- "xml_element_writer.cc",
- "xml_element_writer.h",
- ]
-
- deps = [
- "//base",
- "//base/third_party/dynamic_annotations",
- ]
-}
-
-action("last_commit_position") {
- script = "last_commit_position.py"
-
- # This dependency forces a re-run when the code is synced.
- inputs = [
- "//build/util/LASTCHANGE",
- ]
-
- outfile = "$target_gen_dir/last_commit_position.h"
- outputs = [
- outfile,
- ]
-
- args = [
- rebase_path("//", root_build_dir),
- rebase_path(outfile, root_build_dir),
- "TOOLS_GN_LAST_COMMIT_POSITION_H_",
- ]
-}
-
-# Note for Windows debugging: GN is super-multithreaded and uses a lot of STL.
-# Iterator debugging on Windows does locking for every access, which ends up
-# slowing down debug runtime from 0:36 to 9:40. If you want to run debug builds
-# of GN over the large Chrome build, you will want to set the arg:
-# enable_iterator_debugging = false
-executable("gn") {
- defines = [ "GN_BUILD" ]
- sources = [
- "gn_main.cc",
- ]
-
- deps = [
- ":gn_lib",
- ":last_commit_position",
- "//base",
- "//build/config:exe_and_shlib_deps",
- "//build/win:default_exe_manifest",
- ]
-}
-
-test("gn_unittests") {
- deps = [
- ":gn_unittests_sources",
- ]
-
- data = [
- "format_test_data/",
- ]
-}
-
-jumbo_source_set("gn_unittests_sources") {
- testonly = true
-
- sources = [
- "action_target_generator_unittest.cc",
- "analyzer_unittest.cc",
- "args_unittest.cc",
- "builder_unittest.cc",
- "c_include_iterator_unittest.cc",
- "command_format_unittest.cc",
- "config_unittest.cc",
- "config_values_extractors_unittest.cc",
- "escape_unittest.cc",
- "exec_process_unittest.cc",
- "filesystem_utils_unittest.cc",
- "function_foreach_unittest.cc",
- "function_forward_variables_from_unittest.cc",
- "function_get_label_info_unittest.cc",
- "function_get_path_info_unittest.cc",
- "function_get_target_outputs_unittest.cc",
- "function_process_file_template_unittest.cc",
- "function_rebase_path_unittest.cc",
- "function_template_unittest.cc",
- "function_toolchain_unittest.cc",
- "function_write_file_unittest.cc",
- "functions_target_unittest.cc",
- "functions_unittest.cc",
- "header_checker_unittest.cc",
- "inherited_libraries_unittest.cc",
- "input_conversion_unittest.cc",
- "label_pattern_unittest.cc",
- "label_unittest.cc",
- "loader_unittest.cc",
- "ninja_action_target_writer_unittest.cc",
- "ninja_binary_target_writer_unittest.cc",
- "ninja_build_writer_unittest.cc",
- "ninja_bundle_data_target_writer_unittest.cc",
- "ninja_copy_target_writer_unittest.cc",
- "ninja_create_bundle_target_writer_unittest.cc",
- "ninja_group_target_writer_unittest.cc",
- "ninja_target_writer_unittest.cc",
- "ninja_toolchain_writer_unittest.cc",
- "operators_unittest.cc",
- "parse_tree_unittest.cc",
- "parser_unittest.cc",
- "path_output_unittest.cc",
- "pattern_unittest.cc",
- "runtime_deps_unittest.cc",
- "scope_per_file_provider_unittest.cc",
- "scope_unittest.cc",
- "source_dir_unittest.cc",
- "source_file_unittest.cc",
- "string_utils_unittest.cc",
- "substitution_pattern_unittest.cc",
- "substitution_writer_unittest.cc",
- "target_unittest.cc",
- "template_unittest.cc",
- "test_with_scheduler.cc",
- "test_with_scheduler.h",
- "test_with_scope.cc",
- "test_with_scope.h",
- "tokenizer_unittest.cc",
- "unique_vector_unittest.cc",
- "value_unittest.cc",
- "visibility_unittest.cc",
- "visual_studio_utils_unittest.cc",
- "visual_studio_writer_unittest.cc",
- "xcode_object_unittest.cc",
- "xml_element_writer_unittest.cc",
- ]
-
- public_deps = [
- ":gn_lib",
- "//base/test:run_all_unittests",
- "//base/test:test_support",
- "//testing/gtest",
- ]
-}
-
-fuzzer_test("gn_parser_fuzzer") {
- sources = [
- "parser_fuzzer.cc",
- ]
- deps = [
- ":gn_lib",
- ]
-}
diff --git a/chromium/tools/gn/DEPS b/chromium/tools/gn/DEPS
deleted file mode 100644
index 0de07bbaf08..00000000000
--- a/chromium/tools/gn/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+third_party/re2",
-]
diff --git a/chromium/tools/gn/OWNERS b/chromium/tools/gn/OWNERS
deleted file mode 100644
index 82224cd8517..00000000000
--- a/chromium/tools/gn/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-brettw@chromium.org
-dpranke@chromium.org
-sdefresne@chromium.org
diff --git a/chromium/tools/gn/README.md b/chromium/tools/gn/README.md
index fd0d9c56d6d..b9da9f3d3d0 100644
--- a/chromium/tools/gn/README.md
+++ b/chromium/tools/gn/README.md
@@ -1,18 +1 @@
-# What is GN?
-
-GN is a meta-build system that generates [Ninja](https://ninja-build.org)
-build files so that you can build Chromium with Ninja.
-
-## I want more info on GN!
-
-Read these links:
-
- * [Quick start](docs/quick_start.md)
- * [FAQ](docs/faq.md)
- * [Language and operation details](docs/language.md)
- * [Reference](docs/reference.md): The built-in `gn help` documentation.
- * [Style guide](docs/style_guide.md)
- * [Cross compiling and toolchains](docs/cross_compiles.md)
- * [Hacking on GN itself](docs/hacking.md)
- * [Standaline GN projects](docs/standalone.md)
- * [Pushing new binaries](docs/update_binaries.md)
+gn now lives at https://gn.googlesource.com/
diff --git a/chromium/tools/gn/action_target_generator.cc b/chromium/tools/gn/action_target_generator.cc
deleted file mode 100644
index ca3986eb496..00000000000
--- a/chromium/tools/gn/action_target_generator.cc
+++ /dev/null
@@ -1,221 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/action_target_generator.h"
-
-#include "base/stl_util.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/value.h"
-#include "tools/gn/value_extractors.h"
-#include "tools/gn/variables.h"
-
-ActionTargetGenerator::ActionTargetGenerator(
- Target* target,
- Scope* scope,
- const FunctionCallNode* function_call,
- Target::OutputType type,
- Err* err)
- : TargetGenerator(target, scope, function_call, err),
- output_type_(type) {
-}
-
-ActionTargetGenerator::~ActionTargetGenerator() = default;
-
-void ActionTargetGenerator::DoRun() {
- target_->set_output_type(output_type_);
-
- if (!FillSources())
- return;
- if (output_type_ == Target::ACTION_FOREACH && target_->sources().empty()) {
- // Foreach rules must always have some sources to have an effect.
- *err_ = Err(function_call_, "action_foreach target has no sources.",
- "If you don't specify any sources, there is nothing to run your\n"
- "script over.");
- return;
- }
-
- if (!FillInputs())
- return;
-
- if (!FillScript())
- return;
-
- if (!FillScriptArgs())
- return;
-
- if (!FillResponseFileContents())
- return;
-
- if (!FillOutputs(output_type_ == Target::ACTION_FOREACH))
- return;
-
- if (!FillDepfile())
- return;
-
- if (!FillPool())
- return;
-
- if (!FillCheckIncludes())
- return;
-
- if (!CheckOutputs())
- return;
-
- // Action outputs don't depend on the current toolchain so we can skip adding
- // that dependency.
-
- // response_file_contents and {{response_file_name}} in the args must go
- // together.
- const auto& required_args_substitutions =
- target_->action_values().args().required_types();
- bool has_rsp_file_name = base::ContainsValue(required_args_substitutions,
- SUBSTITUTION_RSP_FILE_NAME);
- if (target_->action_values().uses_rsp_file() && !has_rsp_file_name) {
- *err_ = Err(function_call_, "Missing {{response_file_name}} in args.",
- "This target defines response_file_contents but doesn't use\n"
- "{{response_file_name}} in the args, which means the response file\n"
- "will be unused.");
- return;
- }
- if (!target_->action_values().uses_rsp_file() && has_rsp_file_name) {
- *err_ = Err(function_call_, "Missing response_file_contents definition.",
- "This target uses {{response_file_name}} in the args, but does not\n"
- "define response_file_contents which means the response file\n"
- "will be empty.");
- return;
- }
-}
-
-bool ActionTargetGenerator::FillScript() {
- // If this gets called, the target type requires a script, so error out
- // if it doesn't have one.
- const Value* value = scope_->GetValue(variables::kScript, true);
- if (!value) {
- *err_ = Err(function_call_, "This target type requires a \"script\".");
- return false;
- }
- if (!value->VerifyTypeIs(Value::STRING, err_))
- return false;
-
- SourceFile script_file =
- scope_->GetSourceDir().ResolveRelativeFile(
- *value, err_,
- scope_->settings()->build_settings()->root_path_utf8());
- if (err_->has_error())
- return false;
- target_->action_values().set_script(script_file);
- return true;
-}
-
-bool ActionTargetGenerator::FillScriptArgs() {
- const Value* value = scope_->GetValue(variables::kArgs, true);
- if (!value)
- return true; // Nothing to do.
-
- if (!target_->action_values().args().Parse(*value, err_))
- return false;
- if (!EnsureValidSubstitutions(
- target_->action_values().args().required_types(),
- &IsValidScriptArgsSubstitution,
- value->origin(), err_))
- return false;
-
- return true;
-}
-
-bool ActionTargetGenerator::FillResponseFileContents() {
- const Value* value = scope_->GetValue(variables::kResponseFileContents, true);
- if (!value)
- return true; // Nothing to do.
-
- if (!target_->action_values().rsp_file_contents().Parse(*value, err_))
- return false;
- if (!EnsureValidSubstitutions(
- target_->action_values().rsp_file_contents().required_types(),
- &IsValidSourceSubstitution, value->origin(), err_))
- return false;
-
- return true;
-}
-
-bool ActionTargetGenerator::FillDepfile() {
- const Value* value = scope_->GetValue(variables::kDepfile, true);
- if (!value)
- return true;
-
- SubstitutionPattern depfile;
- if (!depfile.Parse(*value, err_))
- return false;
- if (!EnsureSubstitutionIsInOutputDir(depfile, *value))
- return false;
-
- target_->action_values().set_depfile(depfile);
- return true;
-}
-
-bool ActionTargetGenerator::FillPool() {
- const Value* value = scope_->GetValue(variables::kPool, true);
- if (!value)
- return true;
-
- Label label = Label::Resolve(scope_->GetSourceDir(),
- ToolchainLabelForScope(scope_), *value, err_);
- if (err_->has_error())
- return false;
-
- LabelPtrPair<Pool> pair(label);
- pair.origin = target_->defined_from();
-
- target_->action_values().set_pool(std::move(pair));
- return true;
-}
-
-bool ActionTargetGenerator::CheckOutputs() {
- const SubstitutionList& outputs = target_->action_values().outputs();
- if (outputs.list().empty()) {
- *err_ = Err(function_call_, "Action has no outputs.",
- "If you have no outputs, the build system can not tell when your\n"
- "script needs to be run.");
- return false;
- }
-
- if (output_type_ == Target::ACTION) {
- if (!outputs.required_types().empty()) {
- *err_ = Err(function_call_, "Action has patterns in the output.",
- "An action target should have the outputs completely specified. If\n"
- "you want to provide a mapping from source to output, use an\n"
- "\"action_foreach\" target.");
- return false;
- }
- } else if (output_type_ == Target::ACTION_FOREACH) {
- // A foreach target should always have a pattern in the outputs.
- if (outputs.required_types().empty()) {
- *err_ = Err(function_call_,
- "action_foreach should have a pattern in the output.",
- "An action_foreach target should have a source expansion pattern in\n"
- "it to map source file to unique output file name. Otherwise, the\n"
- "build system can't determine when your script needs to be run.");
- return false;
- }
- }
- return true;
-}
-
-bool ActionTargetGenerator::FillInputs() {
- const Value* value = scope_->GetValue(variables::kInputs, true);
- if (!value)
- return true;
-
- Target::FileList dest_inputs;
- if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
- scope_->GetSourceDir(), &dest_inputs, err_))
- return false;
- target_->config_values().inputs().swap(dest_inputs);
- return true;
-}
diff --git a/chromium/tools/gn/action_target_generator.h b/chromium/tools/gn/action_target_generator.h
deleted file mode 100644
index 0ea3cbbab87..00000000000
--- a/chromium/tools/gn/action_target_generator.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_ACTION_TARGET_GENERATOR_H_
-#define TOOLS_GN_ACTION_TARGET_GENERATOR_H_
-
-#include "base/macros.h"
-#include "tools/gn/target.h"
-#include "tools/gn/target_generator.h"
-
-// Populates a Target with the values from an action[_foreach] rule.
-class ActionTargetGenerator : public TargetGenerator {
- public:
- ActionTargetGenerator(Target* target,
- Scope* scope,
- const FunctionCallNode* function_call,
- Target::OutputType type,
- Err* err);
- ~ActionTargetGenerator() override;
-
- protected:
- void DoRun() override;
-
- private:
- bool FillScript();
- bool FillScriptArgs();
- bool FillResponseFileContents();
- bool FillDepfile();
- bool FillPool();
- bool FillInputs();
-
- // Checks for errors in the outputs variable.
- bool CheckOutputs();
-
- Target::OutputType output_type_;
-
- DISALLOW_COPY_AND_ASSIGN(ActionTargetGenerator);
-};
-
-#endif // TOOLS_GN_ACTION_TARGET_GENERATOR_H_
diff --git a/chromium/tools/gn/action_target_generator_unittest.cc b/chromium/tools/gn/action_target_generator_unittest.cc
deleted file mode 100644
index 254bc9827ad..00000000000
--- a/chromium/tools/gn/action_target_generator_unittest.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/test_with_scheduler.h"
-#include "tools/gn/test_with_scope.h"
-
-using ActionTargetGenerator = TestWithScheduler;
-
-// Tests that actions can't have output substitutions.
-TEST_F(ActionTargetGenerator, ActionOutputSubstitutions) {
- TestWithScope setup;
- Scope::ItemVector items_;
- setup.scope()->set_item_collector(&items_);
-
- // First test one with no substitutions, this should be valid.
- TestParseInput input_good(
- R"(action("foo") {
- script = "//foo.py"
- sources = [ "//bar.txt" ]
- outputs = [ "//out/Debug/one.txt" ]
- })");
- ASSERT_FALSE(input_good.has_error());
-
- // This should run fine.
- Err err;
- input_good.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- // Same thing with a pattern in the output should fail.
- TestParseInput input_bad(
- R"(action("foo") {
- script = "//foo.py"
- sources = [ "//bar.txt" ]
- outputs = [ "//out/Debug/{{source_name_part}}.txt" ]
- })");
- ASSERT_FALSE(input_bad.has_error());
-
- // This should run fine.
- input_bad.parsed()->Execute(setup.scope(), &err);
- ASSERT_TRUE(err.has_error());
-}
-
-// Tests that arg and response file substitutions are validated for
-// action_foreach targets.
-TEST_F(ActionTargetGenerator, ActionForeachSubstitutions) {
- TestWithScope setup;
- Scope::ItemVector items_;
- setup.scope()->set_item_collector(&items_);
-
- // Args listing a response file but missing a response file definition should
- // fail.
- TestParseInput input_missing_resp_file(
- R"(action_foreach("foo") {
- script = "//foo.py"
- sources = [ "//bar.txt" ]
- outputs = [ "//out/Debug/{{source_name_part}}" ]
- args = [ "{{response_file_name}}" ]
- })");
- ASSERT_FALSE(input_missing_resp_file.has_error());
- Err err;
- input_missing_resp_file.parsed()->Execute(setup.scope(), &err);
- ASSERT_TRUE(err.has_error());
-
- // Adding a response file definition should pass.
- err = Err();
- TestParseInput input_resp_file(
- R"(action_foreach("foo") {
- script = "//foo.py"
- sources = [ "//bar.txt" ]
- outputs = [ "//out/Debug/{{source_name_part}}" ]
- args = [ "{{response_file_name}}" ]
- response_file_contents = [ "{{source_name_part}}" ]
- })");
- ASSERT_FALSE(input_resp_file.has_error());
- input_resp_file.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- // Defining a response file but not referencing it should fail.
- err = Err();
- TestParseInput input_missing_rsp_args(
- R"(action_foreach("foo") {
- script = "//foo.py"
- sources = [ "//bar.txt" ]
- outputs = [ "//out/Debug/{{source_name_part}}" ]
- args = [ "{{source_name_part}}" ]
- response_file_contents = [ "{{source_name_part}}" ]
- })");
- ASSERT_FALSE(input_missing_rsp_args.has_error());
- input_missing_rsp_args.parsed()->Execute(setup.scope(), &err);
- ASSERT_TRUE(err.has_error()) << err.message();
-
- // Bad substitutions in args.
- err = Err();
- TestParseInput input_bad_args(
- R"(action_foreach("foo") {
- script = "//foo.py"
- sources = [ "//bar.txt" ]
- outputs = [ "//out/Debug/{{source_name_part}}" ]
- args = [ "{{response_file_name}} {{ldflags}}" ]
- response_file_contents = [ "{{source_name_part}}" ]
- })");
- ASSERT_FALSE(input_bad_args.has_error());
- input_bad_args.parsed()->Execute(setup.scope(), &err);
- ASSERT_TRUE(err.has_error()) << err.message();
-
- // Bad substitutions in response file contents.
- err = Err();
- TestParseInput input_bad_rsp(
- R"(action_foreach("foo") {
- script = "//foo.py"
- sources = [ "//bar.txt" ]
- outputs = [ "//out/Debug/{{source_name_part}}" ]
- args = [ "{{response_file_name}}" ]
- response_file_contents = [ "{{source_name_part}} {{ldflags}}" ]
- })");
- ASSERT_FALSE(input_bad_rsp.has_error());
- input_bad_rsp.parsed()->Execute(setup.scope(), &err);
- ASSERT_TRUE(err.has_error()) << err.message();
-}
diff --git a/chromium/tools/gn/action_values.cc b/chromium/tools/gn/action_values.cc
deleted file mode 100644
index 3290da4396a..00000000000
--- a/chromium/tools/gn/action_values.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/action_values.h"
-
-#include "tools/gn/settings.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/target.h"
-
-ActionValues::ActionValues() = default;
-
-ActionValues::~ActionValues() = default;
-
-void ActionValues::GetOutputsAsSourceFiles(
- const Target* target,
- std::vector<SourceFile>* result) const {
- if (target->output_type() == Target::BUNDLE_DATA) {
- // The bundle_data target has no output, the real output will be generated
- // by the create_bundle target.
- } else if (target->output_type() == Target::COPY_FILES ||
- target->output_type() == Target::ACTION_FOREACH) {
- // Copy and foreach applies the outputs to the sources.
- SubstitutionWriter::ApplyListToSources(
- target, target->settings(), outputs_, target->sources(), result);
- } else {
- // Actions (and anything else that happens to specify an output) just use
- // the output list with no substitution.
- SubstitutionWriter::GetListAsSourceFiles(outputs_, result);
- }
-}
diff --git a/chromium/tools/gn/action_values.h b/chromium/tools/gn/action_values.h
deleted file mode 100644
index 806a39f8c64..00000000000
--- a/chromium/tools/gn/action_values.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_ACTION_VALUES_H_
-#define TOOLS_GN_ACTION_VALUES_H_
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "tools/gn/label_ptr.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/substitution_list.h"
-
-class Pool;
-class Target;
-
-// Holds the values (outputs, args, script name, etc.) for either an action or
-// an action_foreach target.
-class ActionValues {
- public:
- ActionValues();
- ~ActionValues();
-
- // Filename of the script to execute.
- const SourceFile& script() const { return script_; }
- void set_script(const SourceFile& s) { script_ = s; }
-
- // Arguments to the script.
- SubstitutionList& args() { return args_; }
- const SubstitutionList& args() const { return args_; }
-
- // Files created by the script. These are strings rather than SourceFiles
- // since they will often contain {{source expansions}}.
- SubstitutionList& outputs() { return outputs_; }
- const SubstitutionList& outputs() const { return outputs_; }
-
- // Expands the outputs() above to the final SourceFile list.
- void GetOutputsAsSourceFiles(const Target* target,
- std::vector<SourceFile>* result) const;
-
- // Depfile generated by the script.
- const SubstitutionPattern& depfile() const { return depfile_; }
- bool has_depfile() const { return !depfile_.ranges().empty(); }
- void set_depfile(const SubstitutionPattern& depfile) { depfile_ = depfile; }
-
- // Response file contents. Empty means no response file.
- SubstitutionList& rsp_file_contents() { return rsp_file_contents_; }
- const SubstitutionList& rsp_file_contents() const {
- return rsp_file_contents_;
- }
- bool uses_rsp_file() const { return !rsp_file_contents_.list().empty(); }
-
- // Pool option
- const LabelPtrPair<Pool>& pool() const { return pool_; }
- void set_pool(LabelPtrPair<Pool> pool) { pool_ = std::move(pool); }
-
- private:
- SourceFile script_;
- SubstitutionList args_;
- SubstitutionList outputs_;
- SubstitutionPattern depfile_;
- SubstitutionList rsp_file_contents_;
- LabelPtrPair<Pool> pool_;
-
- DISALLOW_COPY_AND_ASSIGN(ActionValues);
-};
-
-#endif // TOOLS_GN_ACTION_VALUES_H_
diff --git a/chromium/tools/gn/analyzer.cc b/chromium/tools/gn/analyzer.cc
deleted file mode 100644
index c5158c5b6fa..00000000000
--- a/chromium/tools/gn/analyzer.cc
+++ /dev/null
@@ -1,486 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/analyzer.h"
-
-#include <algorithm>
-#include <iterator>
-#include <memory>
-#include <set>
-#include <vector>
-
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
-#include "base/strings/string_util.h"
-#include "base/values.h"
-#include "tools/gn/builder.h"
-#include "tools/gn/config.h"
-#include "tools/gn/config_values_extractors.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/loader.h"
-#include "tools/gn/location.h"
-#include "tools/gn/pool.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/target.h"
-
-namespace {
-
-struct Inputs {
- std::vector<SourceFile> source_vec;
- std::vector<Label> compile_vec;
- std::vector<Label> test_vec;
- bool compile_included_all = false;
- std::set<const SourceFile*> source_files;
- std::set<Label> compile_labels;
- std::set<Label> test_labels;
-};
-
-struct Outputs {
- std::string status;
- std::string error;
- bool compile_includes_all = false;
- std::set<Label> compile_labels;
- std::set<Label> test_labels;
- std::set<Label> invalid_labels;
-};
-
-std::set<Label> LabelsFor(const std::set<const Target*>& targets) {
- std::set<Label> labels;
- for (auto* target : targets)
- labels.insert(target->label());
- return labels;
-}
-
-std::set<const Target*> Intersect(const std::set<const Target*>& l,
- const std::set<const Target*>& r) {
- std::set<const Target*> result;
- std::set_intersection(l.begin(), l.end(), r.begin(), r.end(),
- std::inserter(result, result.begin()));
- return result;
-}
-
-std::vector<std::string> GetStringVector(const base::DictionaryValue& dict,
- const std::string& key,
- Err* err) {
- std::vector<std::string> strings;
- const base::ListValue* lst;
- bool ret = dict.GetList(key, &lst);
- if (!ret) {
- *err = Err(Location(), "Input does not have a key named \"" + key +
- "\" with a list value.");
- return strings;
- }
-
- for (size_t i = 0; i < lst->GetSize(); i++) {
- std::string s;
- ret = lst->GetString(i, &s);
- if (!ret) {
- *err = Err(Location(), "Item " + std::to_string(i) + " of \"" + key +
- "\" is not a string.");
- strings.clear();
- return strings;
- }
- strings.push_back(std::move(s));
- }
- *err = Err();
- return strings;
-}
-
-void WriteString(base::DictionaryValue& dict,
- const std::string& key,
- const std::string& value) {
- dict.SetKey(key, base::Value(value));
-};
-
-void WriteLabels(const Label& default_toolchain,
- base::DictionaryValue& dict,
- const std::string& key,
- const std::set<Label>& labels) {
- std::vector<std::string> strings;
- auto value = std::make_unique<base::ListValue>();
- for (const auto l : labels)
- strings.push_back(l.GetUserVisibleName(default_toolchain));
- std::sort(strings.begin(), strings.end());
- value->AppendStrings(strings);
- dict.SetWithoutPathExpansion(key, std::move(value));
-}
-
-Label AbsoluteOrSourceAbsoluteStringToLabel(const Label& default_toolchain,
- const std::string& s, Err* err) {
- if (!IsPathSourceAbsolute(s) && !IsPathAbsolute(s)) {
- *err = Err(Location(),
- "\"" + s + "\" is not a source-absolute or absolute path.");
- return Label();
- }
- return Label::Resolve(SourceDir("//"), default_toolchain, Value(nullptr, s),
- err);
-}
-
-Err JSONToInputs(const Label& default_toolchain,
- const std::string input,
- Inputs* inputs) {
- int error_code_out;
- std::string error_msg_out;
- int error_line_out;
- int error_column_out;
- std::unique_ptr<base::Value> value = base::JSONReader().ReadAndReturnError(
- input, base::JSONParserOptions::JSON_PARSE_RFC, &error_code_out,
- &error_msg_out, &error_line_out, &error_column_out);
- if (!value)
- return Err(Location(), "Input is not valid JSON:" + error_msg_out);
-
- const base::DictionaryValue* dict;
- if (!value->GetAsDictionary(&dict))
- return Err(Location(), "Input is not a dictionary.");
-
- Err err;
- std::vector<std::string> strings;
- strings = GetStringVector(*dict, "files", &err);
- if (err.has_error())
- return err;
- for (auto s : strings) {
- if (!IsPathSourceAbsolute(s) && !IsPathAbsolute(s))
- return Err(Location(),
- "\"" + s + "\" is not a source-absolute or absolute path.");
- inputs->source_vec.push_back(SourceFile(s));
- }
-
- strings = GetStringVector(*dict, "additional_compile_targets", &err);
- if (err.has_error())
- return err;
-
- inputs->compile_included_all = false;
- for (auto& s : strings) {
- if (s == "all") {
- inputs->compile_included_all = true;
- } else {
- inputs->compile_vec.push_back(
- AbsoluteOrSourceAbsoluteStringToLabel(default_toolchain, s, &err));
- if (err.has_error())
- return err;
- }
- }
-
- strings = GetStringVector(*dict, "test_targets", &err);
- if (err.has_error())
- return err;
- for (auto& s : strings) {
- inputs->test_vec.push_back(
- AbsoluteOrSourceAbsoluteStringToLabel(default_toolchain, s, &err));
- if (err.has_error())
- return err;
- }
-
- for (auto& s : inputs->source_vec)
- inputs->source_files.insert(&s);
- for (auto& l : inputs->compile_vec)
- inputs->compile_labels.insert(l);
- for (auto& l : inputs->test_vec)
- inputs->test_labels.insert(l);
- return Err();
-}
-
-std::string OutputsToJSON(const Outputs& outputs,
- const Label& default_toolchain, Err *err) {
- std::string output;
- auto value = std::make_unique<base::DictionaryValue>();
-
- if (outputs.error.size()) {
- WriteString(*value, "error", outputs.error);
- WriteLabels(default_toolchain, *value, "invalid_targets",
- outputs.invalid_labels);
- } else {
- WriteString(*value, "status", outputs.status);
- if (outputs.compile_includes_all) {
- auto compile_targets = std::make_unique<base::ListValue>();
- compile_targets->AppendString("all");
- value->SetWithoutPathExpansion("compile_targets",
- std::move(compile_targets));
- } else {
- WriteLabels(default_toolchain, *value, "compile_targets",
- outputs.compile_labels);
- }
- WriteLabels(default_toolchain, *value, "test_targets", outputs.test_labels);
- }
-
- if (!base::JSONWriter::Write(*value.get(), &output))
- *err = Err(Location(), "Failed to marshal JSON value for output");
- return output;
-}
-
-} // namespace
-
-Analyzer::Analyzer(const Builder& builder,
- const SourceFile& build_config_file,
- const SourceFile& dot_file,
- const std::set<SourceFile>& build_args_dependency_files)
- : all_items_(builder.GetAllResolvedItems()),
- default_toolchain_(builder.loader()->GetDefaultToolchain()),
- build_config_file_(build_config_file),
- dot_file_(dot_file),
- build_args_dependency_files_(build_args_dependency_files) {
- for (const auto* item : all_items_) {
- labels_to_items_[item->label()] = item;
-
- // Fill dep_map_.
- if (item->AsTarget()) {
- for (const auto& dep_target_pair :
- item->AsTarget()->GetDeps(Target::DEPS_ALL))
- dep_map_.insert(std::make_pair(dep_target_pair.ptr, item));
-
- for (const auto& dep_config_pair : item->AsTarget()->configs())
- dep_map_.insert(std::make_pair(dep_config_pair.ptr, item));
-
- dep_map_.insert(std::make_pair(item->AsTarget()->toolchain(), item));
-
- if (item->AsTarget()->output_type() == Target::ACTION ||
- item->AsTarget()->output_type() == Target::ACTION_FOREACH) {
- const LabelPtrPair<Pool>& pool =
- item->AsTarget()->action_values().pool();
- if (pool.ptr)
- dep_map_.insert(std::make_pair(pool.ptr, item));
- }
- } else if (item->AsConfig()) {
- for (const auto& dep_config_pair : item->AsConfig()->configs())
- dep_map_.insert(std::make_pair(dep_config_pair.ptr, item));
- } else if (item->AsToolchain()) {
- for (const auto& dep_pair : item->AsToolchain()->deps())
- dep_map_.insert(std::make_pair(dep_pair.ptr, item));
- } else {
- DCHECK(item->AsPool());
- }
- }
-}
-
-Analyzer::~Analyzer() = default;
-
-std::string Analyzer::Analyze(const std::string& input, Err* err) const {
- Inputs inputs;
- Outputs outputs;
-
- Err local_err = JSONToInputs(default_toolchain_, input, &inputs);
- if (local_err.has_error()) {
- outputs.error = local_err.message();
- return OutputsToJSON(outputs, default_toolchain_, err);
- }
-
- std::set<Label> invalid_labels;
- for (const auto& label : InvalidLabels(inputs.compile_labels))
- invalid_labels.insert(label);
- for (const auto& label : InvalidLabels(inputs.test_labels))
- invalid_labels.insert(label);
- if (!invalid_labels.empty()) {
- outputs.error = "Invalid targets";
- outputs.invalid_labels = invalid_labels;
- return OutputsToJSON(outputs, default_toolchain_, err);
- }
-
- if (WereMainGNFilesModified(inputs.source_files)) {
- outputs.status = "Found dependency (all)";
- if (inputs.compile_included_all) {
- outputs.compile_includes_all = true;
- } else {
- outputs.compile_labels.insert(inputs.compile_labels.begin(),
- inputs.compile_labels.end());
- outputs.compile_labels.insert(inputs.test_labels.begin(),
- inputs.test_labels.end());
- }
- outputs.test_labels = inputs.test_labels;
- return OutputsToJSON(outputs, default_toolchain_, err);
- }
-
- std::set<const Item*> affected_items =
- GetAllAffectedItems(inputs.source_files);
- std::set<const Target*> affected_targets;
- for (const Item* affected_item : affected_items) {
- // Only handles targets in the default toolchain.
- // TODO(crbug.com/667989): Expand analyzer to non-default toolchains when
- // the bug is fixed.
- if (affected_item->AsTarget() &&
- affected_item->label().GetToolchainLabel() == default_toolchain_)
- affected_targets.insert(affected_item->AsTarget());
- }
-
- if (affected_targets.empty()) {
- outputs.status = "No dependency";
- return OutputsToJSON(outputs, default_toolchain_, err);
- }
-
- std::set<const Target*> root_targets;
- for (const auto* item : all_items_) {
- if (item->AsTarget() && dep_map_.find(item) == dep_map_.end())
- root_targets.insert(item->AsTarget());
- }
-
- std::set<const Target*> compile_targets = TargetsFor(inputs.compile_labels);
- if (inputs.compile_included_all) {
- for (auto* root_target : root_targets)
- compile_targets.insert(root_target);
- }
- std::set<const Target*> filtered_targets = Filter(compile_targets);
- outputs.compile_labels =
- LabelsFor(Intersect(filtered_targets, affected_targets));
-
- // If every target is affected, simply compile All instead of listing all
- // the targets to make the output easier to read.
- if (inputs.compile_included_all &&
- outputs.compile_labels.size() == filtered_targets.size())
- outputs.compile_includes_all = true;
-
- std::set<const Target*> test_targets = TargetsFor(inputs.test_labels);
- outputs.test_labels = LabelsFor(Intersect(test_targets, affected_targets));
-
- if (outputs.compile_labels.empty() && outputs.test_labels.empty())
- outputs.status = "No dependency";
- else
- outputs.status = "Found dependency";
- return OutputsToJSON(outputs, default_toolchain_, err);
-}
-
-std::set<const Item*> Analyzer::GetAllAffectedItems(
- const std::set<const SourceFile*>& source_files) const {
- std::set<const Item*> directly_affected_items;
- for (auto* source_file : source_files)
- AddItemsDirectlyReferringToFile(source_file, &directly_affected_items);
-
- std::set<const Item*> all_affected_items;
- for (auto* affected_item : directly_affected_items)
- AddAllItemsReferringToItem(affected_item, &all_affected_items);
-
- return all_affected_items;
-}
-
-std::set<Label> Analyzer::InvalidLabels(const std::set<Label>& labels) const {
- std::set<Label> invalid_labels;
- for (const Label& label : labels) {
- if (labels_to_items_.find(label) == labels_to_items_.end())
- invalid_labels.insert(label);
- }
- return invalid_labels;
-}
-
-std::set<const Target*> Analyzer::TargetsFor(
- const std::set<Label>& labels) const {
- std::set<const Target*> targets;
- for (const auto& label : labels) {
- auto it = labels_to_items_.find(label);
- if (it != labels_to_items_.end()) {
- DCHECK(it->second->AsTarget());
- targets.insert(it->second->AsTarget());
- }
- }
- return targets;
-}
-
-std::set<const Target*> Analyzer::Filter(
- const std::set<const Target*>& targets) const {
- std::set<const Target*> seen;
- std::set<const Target*> filtered;
- for (const auto* target : targets)
- FilterTarget(target, &seen, &filtered);
- return filtered;
-}
-
-void Analyzer::FilterTarget(const Target* target,
- std::set<const Target*>* seen,
- std::set<const Target*>* filtered) const {
- if (seen->find(target) == seen->end()) {
- seen->insert(target);
- if (target->output_type() != Target::GROUP) {
- filtered->insert(target);
- } else {
- for (const auto& pair : target->GetDeps(Target::DEPS_ALL))
- FilterTarget(pair.ptr, seen, filtered);
- }
- }
-}
-
-bool Analyzer::ItemRefersToFile(const Item* item,
- const SourceFile* file) const {
- for (const auto& cur_file : item->build_dependency_files()) {
- if (cur_file == *file)
- return true;
- }
-
- if (!item->AsTarget())
- return false;
-
- const Target* target = item->AsTarget();
- for (const auto& cur_file : target->sources()) {
- if (cur_file == *file)
- return true;
- }
- for (const auto& cur_file : target->public_headers()) {
- if (cur_file == *file)
- return true;
- }
- for (ConfigValuesIterator iter(target); !iter.done(); iter.Next()) {
- for (const auto& cur_file : iter.cur().inputs()) {
- if (cur_file == *file)
- return true;
- }
- }
- for (const auto& cur_file : target->data()) {
- if (cur_file == file->value())
- return true;
- if (cur_file.back() == '/' &&
- base::StartsWith(file->value(), cur_file, base::CompareCase::SENSITIVE))
- return true;
- }
-
- if (target->action_values().script().value() == file->value())
- return true;
-
- std::vector<SourceFile> outputs;
- target->action_values().GetOutputsAsSourceFiles(target, &outputs);
- for (const auto& cur_file : outputs) {
- if (cur_file == *file)
- return true;
- }
- return false;
-}
-
-void Analyzer::AddItemsDirectlyReferringToFile(
- const SourceFile* file,
- std::set<const Item*>* directly_affected_items) const {
- for (const auto* item : all_items_) {
- if (ItemRefersToFile(item, file))
- directly_affected_items->insert(item);
- }
-}
-
-void Analyzer::AddAllItemsReferringToItem(
- const Item* item,
- std::set<const Item*>* all_affected_items) const {
- if (all_affected_items->find(item) != all_affected_items->end())
- return; // Already found this item.
-
- all_affected_items->insert(item);
-
- auto dep_begin = dep_map_.lower_bound(item);
- auto dep_end = dep_map_.upper_bound(item);
- for (auto cur_dep = dep_begin; cur_dep != dep_end; ++cur_dep)
- AddAllItemsReferringToItem(cur_dep->second, all_affected_items);
-}
-
-bool Analyzer::WereMainGNFilesModified(
- const std::set<const SourceFile*>& modified_files) const {
- for (const auto* file : modified_files) {
- if (*file == dot_file_)
- return true;
-
- if (*file == build_config_file_)
- return true;
-
- for (const auto& build_args_dependency_file :
- build_args_dependency_files_) {
- if (*file == build_args_dependency_file)
- return true;
- }
- }
-
- return false;
-}
diff --git a/chromium/tools/gn/analyzer.h b/chromium/tools/gn/analyzer.h
deleted file mode 100644
index 01be0e45552..00000000000
--- a/chromium/tools/gn/analyzer.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_ANALYZER_H_
-#define TOOLS_GN_ANALYZER_H_
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "tools/gn/builder.h"
-#include "tools/gn/item.h"
-#include "tools/gn/label.h"
-#include "tools/gn/source_file.h"
-
-// An Analyzer can answer questions about a build graph. It is used
-// to answer queries for the `refs` and `analyze` commands, where we
-// need to look at the graph in ways that can't easily be determined
-// from just a single Target.
-class Analyzer {
- public:
- Analyzer(const Builder& builder,
- const SourceFile& build_config_file,
- const SourceFile& dot_file,
- const std::set<SourceFile>& build_args_dependency_files);
- ~Analyzer();
-
- // Figures out from a Buider and a JSON-formatted string containing lists
- // of files and targets, which targets would be affected by modifications
- // to the files . See the help text for the analyze command (kAnalyze_Help)
- // for the specification of the input and output string formats and the
- // expected behavior of the method.
- std::string Analyze(const std::string& input, Err* err) const;
-
- private:
- // Returns the set of all items that might be affected, directly or
- // indirectly, by modifications to the given source files.
- std::set<const Item*> GetAllAffectedItems(
- const std::set<const SourceFile*>& source_files) const;
-
- // Returns the set of labels that do not refer to objects in the graph.
- std::set<Label> InvalidLabels(const std::set<Label>& labels) const;
-
- // Returns the set of all targets that have a label in the given set.
- // Invalid (or missing) labels will be ignored.
- std::set<const Target*> TargetsFor(const std::set<Label>& labels) const;
-
- // Returns a filtered set of the given targets, meaning that for each of the
- // given targets,
- // - if the target is not a group, add it to the set
- // - if the target is a group, recursively filter each dependency and add
- // its filtered results to the set.
- //
- // For example, if we had:
- //
- // group("foobar") { deps = [ ":foo", ":bar" ] }
- // group("bar") { deps = [ ":baz", ":quux" ] }
- // executable("foo") { ... }
- // executable("baz") { ... }
- // executable("quux") { ... }
- //
- // Then the filtered version of {"foobar"} would be {":foo", ":baz",
- // ":quux"}. This is used by the analyze command in order to only build
- // the affected dependencies of a group (and not also build the unaffected
- // ones).
- //
- // This filtering behavior is also known as "pruning" the list of targets.
- std::set<const Target*> Filter(const std::set<const Target*>& targets) const;
-
- // Filter an individual target and adds the results to filtered
- // (see Filter(), above).
- void FilterTarget(const Target*,
- std::set<const Target*>* seen,
- std::set<const Target*>* filtered) const;
-
- bool ItemRefersToFile(const Item* item, const SourceFile* file) const;
-
- void AddItemsDirectlyReferringToFile(
- const SourceFile* file,
- std::set<const Item*>* affected_items) const;
-
- void AddAllItemsReferringToItem(const Item* item,
- std::set<const Item*>* affected_items) const;
-
- // Main GN files stand for files whose context are used globally to execute
- // every other build files, this list includes dot file, build config file,
- // build args files etc.
- bool WereMainGNFilesModified(
- const std::set<const SourceFile*>& modified_files) const;
-
- std::vector<const Item*> all_items_;
- std::map<Label, const Item*> labels_to_items_;
- Label default_toolchain_;
-
- // Maps items to the list of items that depend on them.
- std::multimap<const Item*, const Item*> dep_map_;
-
- const SourceFile build_config_file_;
- const SourceFile dot_file_;
- const std::set<SourceFile> build_args_dependency_files_;
-};
-
-#endif // TOOLS_GN_ANALYZER_H_
diff --git a/chromium/tools/gn/analyzer_unittest.cc b/chromium/tools/gn/analyzer_unittest.cc
deleted file mode 100644
index b8188d84f59..00000000000
--- a/chromium/tools/gn/analyzer_unittest.cc
+++ /dev/null
@@ -1,594 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/analyzer.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/builder.h"
-#include "tools/gn/config.h"
-#include "tools/gn/loader.h"
-#include "tools/gn/pool.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/substitution_list.h"
-#include "tools/gn/target.h"
-#include "tools/gn/tool.h"
-#include "tools/gn/toolchain.h"
-
-namespace gn_analyzer_unittest {
-
-class MockLoader : public Loader {
- public:
- MockLoader() = default;
-
- void Load(const SourceFile& file,
- const LocationRange& origin,
- const Label& toolchain_name) override {}
- void ToolchainLoaded(const Toolchain* toolchain) override {}
- Label GetDefaultToolchain() const override {
- return Label(SourceDir("//tc/"), "default");
- }
- const Settings* GetToolchainSettings(const Label& label) const override {
- return nullptr;
- }
-
- private:
- ~MockLoader() override = default;
-};
-
-class AnalyzerTest : public testing::Test {
- public:
- AnalyzerTest()
- : loader_(new MockLoader),
- builder_(loader_.get()),
- settings_(&build_settings_, std::string()) {
- build_settings_.SetBuildDir(SourceDir("//out/"));
- settings_.set_toolchain_label(Label(SourceDir("//tc/"), "default"));
- settings_.set_default_toolchain_label(settings_.toolchain_label());
- tc_dir_ = settings_.toolchain_label().dir();
- tc_name_ = settings_.toolchain_label().name();
- }
-
- // Ownership of the target will be transfered to the builder, so no leaks.
- Target* MakeTarget(const std::string& dir, const std::string& name) {
- Label label(SourceDir(dir), name, tc_dir_, tc_name_);
- Target* target = new Target(&settings_, label);
-
- return target;
- }
-
- // Ownership of the config will be transfered to the builder, so no leaks.
- Config* MakeConfig(const std::string& dir, const std::string& name) {
- Label label(SourceDir(dir), name, tc_dir_, tc_name_);
- Config* config = new Config(&settings_, label);
-
- return config;
- }
-
- // Ownership of the pool will be transfered to the builder, so no leaks.
- Pool* MakePool(const std::string& dir, const std::string& name) {
- Label label(SourceDir(dir), name, tc_dir_, tc_name_);
- Pool* pool = new Pool(&settings_, label);
-
- return pool;
- }
-
- void RunAnalyzerTest(const std::string& input,
- const std::string& expected_output) {
- Analyzer analyzer(builder_, SourceFile("//build/config/BUILDCONFIG.gn"),
- SourceFile("//.gn"),
- {SourceFile("//out/debug/args.gn"),
- SourceFile("//build/default_args.gn")});
- Err err;
- std::string actual_output = analyzer.Analyze(input, &err);
- EXPECT_EQ(err.has_error(), false);
- EXPECT_EQ(expected_output, actual_output);
- }
-
- protected:
- scoped_refptr<MockLoader> loader_;
- Builder builder_;
- BuildSettings build_settings_;
- Settings settings_;
- SourceDir tc_dir_;
- std::string tc_name_;
-};
-
-// Tests that a target is marked as affected if its sources are modified.
-TEST_F(AnalyzerTest, TargetRefersToSources) {
- Target* t = MakeTarget("//dir", "target_name");
- builder_.ItemDefined(std::unique_ptr<Item>(t));
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/file_name.cc" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":[],)"
- R"/("status":"No dependency",)/"
- R"("test_targets":[])"
- "}");
-
- t->sources().push_back(SourceFile("//dir/file_name.cc"));
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/file_name.cc" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":["all"],)"
- R"/("status":"Found dependency",)/"
- R"("test_targets":["//dir:target_name"])"
- "}");
-}
-
-// Tests that a target is marked as affected if its public headers are modified.
-TEST_F(AnalyzerTest, TargetRefersToPublicHeaders) {
- Target* t = MakeTarget("//dir", "target_name");
- builder_.ItemDefined(std::unique_ptr<Item>(t));
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/header_name.h" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":[],)"
- R"/("status":"No dependency",)/"
- R"("test_targets":[])"
- "}");
-
- t->public_headers().push_back(SourceFile("//dir/header_name.h"));
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/header_name.h" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":["all"],)"
- R"/("status":"Found dependency",)/"
- R"("test_targets":["//dir:target_name"])"
- "}");
-}
-
-// Tests that a target is marked as affected if its inputs are modified.
-TEST_F(AnalyzerTest, TargetRefersToInputs) {
- Target* t = MakeTarget("//dir", "target_name");
- builder_.ItemDefined(std::unique_ptr<Item>(t));
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/extra_input.cc" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":[],)"
- R"/("status":"No dependency",)/"
- R"("test_targets":[])"
- "}");
-
- SourceFile extra_input(SourceFile("//dir/extra_input.cc"));
- t->config_values().inputs().push_back(extra_input);
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/extra_input.cc" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":["all"],)"
- R"/("status":"Found dependency",)/"
- R"("test_targets":["//dir:target_name"])"
- "}");
-
- t->config_values().inputs().clear();
- Config* c = MakeConfig("//dir", "config_name");
- builder_.ItemDefined(std::unique_ptr<Item>(c));
- c->own_values().inputs().push_back(extra_input);
- t->configs().push_back(LabelConfigPair(c));
-
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/extra_input.cc" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":["all"],)"
- R"/("status":"Found dependency",)/"
- R"("test_targets":["//dir:target_name"])"
- "}");
-}
-
-// Tests that a target is marked as affected if its data are modified.
-TEST_F(AnalyzerTest, TargetRefersToData) {
- Target* t = MakeTarget("//dir", "target_name");
- builder_.ItemDefined(std::unique_ptr<Item>(t));
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/data.html" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":[],)"
- R"/("status":"No dependency",)/"
- R"("test_targets":[])"
- "}");
-
- t->data().push_back("//dir/data.html");
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/data.html" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":["all"],)"
- R"/("status":"Found dependency",)/"
- R"("test_targets":["//dir:target_name"])"
- "}");
-}
-
-// Tests that a target is marked as affected if the target is an action and its
-// action script is modified.
-TEST_F(AnalyzerTest, TargetRefersToActionScript) {
- Target* t = MakeTarget("//dir", "target_name");
- builder_.ItemDefined(std::unique_ptr<Item>(t));
- t->set_output_type(Target::ACTION);
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/script.py" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":[],)"
- R"/("status":"No dependency",)/"
- R"("test_targets":[])"
- "}");
-
- t->action_values().set_script(SourceFile("//dir/script.py"));
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/script.py" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":["all"],)"
- R"/("status":"Found dependency",)/"
- R"("test_targets":["//dir:target_name"])"
- "}");
-}
-
-// Tests that a target is marked as affected if its build dependency files are
-// modified.
-TEST_F(AnalyzerTest, TargetRefersToBuildDependencyFiles) {
- Target* t = MakeTarget("//dir", "target_name");
- builder_.ItemDefined(std::unique_ptr<Item>(t));
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/BUILD.gn" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":[],)"
- R"/("status":"No dependency",)/"
- R"("test_targets":[])"
- "}");
-
- t->build_dependency_files().insert(SourceFile("//dir/BUILD.gn"));
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/BUILD.gn" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":["all"],)"
- R"/("status":"Found dependency",)/"
- R"("test_targets":["//dir:target_name"])"
- "}");
-}
-
-// Tests that if a target is marked as affected, then it propagates to dependent
-// test_targets.
-TEST_F(AnalyzerTest, AffectedTargetpropagatesToDependentTargets) {
- Target* t1 = MakeTarget("//dir", "target_name1");
- Target* t2 = MakeTarget("//dir", "target_name2");
- Target* t3 = MakeTarget("//dir", "target_name3");
- t1->private_deps().push_back(LabelTargetPair(t2));
- t2->private_deps().push_back(LabelTargetPair(t3));
- builder_.ItemDefined(std::unique_ptr<Item>(t1));
- builder_.ItemDefined(std::unique_ptr<Item>(t2));
- builder_.ItemDefined(std::unique_ptr<Item>(t3));
-
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/BUILD.gn" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name1", "//dir:target_name2" ]
- })",
- "{"
- R"("compile_targets":[],)"
- R"/("status":"No dependency",)/"
- R"("test_targets":[])"
- "}");
-
- t3->build_dependency_files().insert(SourceFile("//dir/BUILD.gn"));
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/BUILD.gn" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name1", "//dir:target_name2" ]
- })",
- "{"
- R"("compile_targets":["all"],)"
- R"/("status":"Found dependency",)/"
- R"("test_targets":["//dir:target_name1","//dir:target_name2"])"
- "}");
-}
-
-// Tests that if a config is marked as affected, then it propagates to dependent
-// test_targets.
-TEST_F(AnalyzerTest, AffectedConfigpropagatesToDependentTargets) {
- Config* c = MakeConfig("//dir", "config_name");
- Target* t = MakeTarget("//dir", "target_name");
- t->configs().push_back(LabelConfigPair(c));
- builder_.ItemDefined(std::unique_ptr<Item>(t));
- builder_.ItemDefined(std::unique_ptr<Item>(c));
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/BUILD.gn" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":[],)"
- R"/("status":"No dependency",)/"
- R"("test_targets":[])"
- "}");
-
- c->build_dependency_files().insert(SourceFile("//dir/BUILD.gn"));
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/BUILD.gn" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":["all"],)"
- R"/("status":"Found dependency",)/"
- R"("test_targets":["//dir:target_name"])"
- "}");
-}
-
-// Tests that if toolchain is marked as affected, then it propagates to
-// dependent test_targets.
-TEST_F(AnalyzerTest, AffectedToolchainpropagatesToDependentTargets) {
- Target* target = MakeTarget("//dir", "target_name");
- target->set_output_type(Target::EXECUTABLE);
- Toolchain* toolchain = new Toolchain(&settings_, settings_.toolchain_label());
-
- // The tool is not used anywhere, but is required to construct the dependency
- // between a target and the toolchain.
- std::unique_ptr<Tool> fake_tool(new Tool());
- fake_tool->set_outputs(
- SubstitutionList::MakeForTest("//out/debug/output.txt"));
- toolchain->SetTool(Toolchain::TYPE_LINK, std::move(fake_tool));
- builder_.ItemDefined(std::unique_ptr<Item>(target));
- builder_.ItemDefined(std::unique_ptr<Item>(toolchain));
-
- RunAnalyzerTest(
- R"({
- "files": [ "//tc/BUILD.gn" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":[],)"
- R"/("status":"No dependency",)/"
- R"("test_targets":[])"
- "}");
-
- toolchain->build_dependency_files().insert(SourceFile("//tc/BUILD.gn"));
- RunAnalyzerTest(
- R"({
- "files": [ "//tc/BUILD.gn" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":["all"],)"
- R"/("status":"Found dependency",)/"
- R"("test_targets":["//dir:target_name"])"
- "}");
-}
-
-// Tests that if a pool is marked as affected, then it propagates to dependent
-// targets.
-TEST_F(AnalyzerTest, AffectedPoolpropagatesToDependentTargets) {
- Target* t = MakeTarget("//dir", "target_name");
- t->set_output_type(Target::ACTION);
- Pool* p = MakePool("//dir", "pool_name");
- t->action_values().set_pool(LabelPtrPair<Pool>(p));
-
- builder_.ItemDefined(std::unique_ptr<Item>(t));
- builder_.ItemDefined(std::unique_ptr<Item>(p));
-
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/BUILD.gn" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":[],)"
- R"/("status":"No dependency",)/"
- R"("test_targets":[])"
- "}");
-
- p->build_dependency_files().insert(SourceFile("//dir/BUILD.gn"));
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/BUILD.gn" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":["all"],)"
- R"/("status":"Found dependency",)/"
- R"("test_targets":["//dir:target_name"])"
- "}");
-}
-
-// Tests that when dependency was found, the "compile_targets" in the output is
-// not "all".
-TEST_F(AnalyzerTest, CompileTargetsAllWasPruned) {
- Target* t1 = MakeTarget("//dir", "target_name1");
- Target* t2 = MakeTarget("//dir", "target_name2");
- builder_.ItemDefined(std::unique_ptr<Item>(t1));
- builder_.ItemDefined(std::unique_ptr<Item>(t2));
- t2->build_dependency_files().insert(SourceFile("//dir/BUILD.gn"));
-
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/BUILD.gn" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": []
- })",
- "{"
- R"("compile_targets":["//dir:target_name2"],)"
- R"/("status":"Found dependency",)/"
- R"("test_targets":[])"
- "}");
-}
-
-// Tests that output is "No dependency" when no dependency is found.
-TEST_F(AnalyzerTest, NoDependency) {
- Target* t = MakeTarget("//dir", "target_name");
- builder_.ItemDefined(std::unique_ptr<Item>(t));
-
- RunAnalyzerTest(
- R"({
- "files": [ "//dir/BUILD.gn" ],
- "additional_compile_targets": [ "all" ],
- "test_targets": []
- })",
- "{"
- R"("compile_targets":[],)"
- R"/("status":"No dependency",)/"
- R"("test_targets":[])"
- "}");
-}
-
-// Tests that output is "No dependency" when no files or targets are provided.
-TEST_F(AnalyzerTest, NoFilesNoTargets) {
- RunAnalyzerTest(
- R"({
- "files": [],
- "additional_compile_targets": [],
- "test_targets": []
- })",
- "{"
- R"("compile_targets":[],)"
- R"("status":"No dependency",)"
- R"("test_targets":[])"
- "}");
-}
-
-// Tests that output displays proper error message when given files aren't
-// source-absolute or absolute path.
-TEST_F(AnalyzerTest, FilesArentSourceAbsolute) {
- RunAnalyzerTest(
- R"({
- "files": [ "a.cc" ],
- "additional_compile_targets": [],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("error":)"
- R"("\"a.cc\" is not a source-absolute or absolute path.",)"
- R"("invalid_targets":[])"
- "}");
-}
-
-// Tests that output displays proper error message when input is illy-formed.
-TEST_F(AnalyzerTest, WrongInputFields) {
- RunAnalyzerTest(
- R"({
- "files": [ "//a.cc" ],
- "compile_targets": [],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("error":)"
- R"("Input does not have a key named )"
- R"(\"additional_compile_targets\" with a list value.",)"
- R"("invalid_targets":[])"
- "}");
-}
-
-// Bails out early with "Found dependency (all)" if dot file is modified.
-TEST_F(AnalyzerTest, DotFileWasModified) {
- Target* t = MakeTarget("//dir", "target_name");
- builder_.ItemDefined(std::unique_ptr<Item>(t));
-
- RunAnalyzerTest(
- R"({
- "files": [ "//.gn" ],
- "additional_compile_targets": [],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":["//dir:target_name"],)"
- R"/("status":"Found dependency (all)",)/"
- R"("test_targets":["//dir:target_name"])"
- "}");
-}
-
-// Bails out early with "Found dependency (all)" if master build config file is
-// modified.
-TEST_F(AnalyzerTest, BuildConfigFileWasModified) {
- Target* t = MakeTarget("//dir", "target_name");
- builder_.ItemDefined(std::unique_ptr<Item>(t));
-
- RunAnalyzerTest(
- R"({
- "files": [ "//build/config/BUILDCONFIG.gn" ],
- "additional_compile_targets": [],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":["//dir:target_name"],)"
- R"/("status":"Found dependency (all)",)/"
- R"("test_targets":["//dir:target_name"])"
- "}");
-}
-
-// Bails out early with "Found dependency (all)" if a build args dependency file
-// is modified.
-TEST_F(AnalyzerTest, BuildArgsDependencyFileWasModified) {
- Target* t = MakeTarget("//dir", "target_name");
- builder_.ItemDefined(std::unique_ptr<Item>(t));
-
- RunAnalyzerTest(
- R"({
- "files": [ "//build/default_args.gn" ],
- "additional_compile_targets": [],
- "test_targets": [ "//dir:target_name" ]
- })",
- "{"
- R"("compile_targets":["//dir:target_name"],)"
- R"/("status":"Found dependency (all)",)/"
- R"("test_targets":["//dir:target_name"])"
- "}");
-}
-
-} // namespace gn_analyzer_unittest
diff --git a/chromium/tools/gn/args.cc b/chromium/tools/gn/args.cc
deleted file mode 100644
index a53eb490dab..00000000000
--- a/chromium/tools/gn/args.cc
+++ /dev/null
@@ -1,424 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/args.h"
-
-#include "base/sys_info.h"
-#include "build/build_config.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/string_utils.h"
-#include "tools/gn/variables.h"
-
-const char kBuildArgs_Help[] =
- R"(Build Arguments Overview
-
- Build arguments are variables passed in from outside of the build that build
- files can query to determine how the build works.
-
-How build arguments are set
-
- First, system default arguments are set based on the current system. The
- built-in arguments are:
- - host_cpu
- - host_os
- - current_cpu
- - current_os
- - target_cpu
- - target_os
-
- Next, project-specific overrides are applied. These are specified inside
- the default_args variable of //.gn. See "gn help dotfile" for more.
-
- If specified, arguments from the --args command line flag are used. If that
- flag is not specified, args from previous builds in the build directory will
- be used (this is in the file args.gn in the build directory).
-
- Last, for targets being compiled with a non-default toolchain, the toolchain
- overrides are applied. These are specified in the toolchain_args section of a
- toolchain definition. The use-case for this is that a toolchain may be
- building code for a different platform, and that it may want to always
- specify Posix, for example. See "gn help toolchain" for more.
-
- If you specify an override for a build argument that never appears in a
- "declare_args" call, a nonfatal error will be displayed.
-
-Examples
-
- gn args out/FooBar
- Create the directory out/FooBar and open an editor. You would type
- something like this into that file:
- enable_doom_melon=false
- os="android"
-
- gn gen out/FooBar --args="enable_doom_melon=true os=\"android\""
- This will overwrite the build directory with the given arguments. (Note
- that the quotes inside the args command will usually need to be escaped
- for your shell to pass through strings values.)
-
-How build arguments are used
-
- If you want to use an argument, you use declare_args() and specify default
- values. These default values will apply if none of the steps listed in the
- "How build arguments are set" section above apply to the given argument, but
- the defaults will not override any of these.
-
- Often, the root build config file will declare global arguments that will be
- passed to all buildfiles. Individual build files can also specify arguments
- that apply only to those files. It is also useful to specify build args in an
- "import"-ed file if you want such arguments to apply to multiple buildfiles.
-)";
-
-namespace {
-
-// Removes all entries in |overrides| that are in |declared_overrides|.
-void RemoveDeclaredOverrides(const Scope::KeyValueMap& declared_arguments,
- Scope::KeyValueMap* overrides) {
- for (Scope::KeyValueMap::iterator override = overrides->begin();
- override != overrides->end();) {
- if (declared_arguments.find(override->first) == declared_arguments.end())
- ++override;
- else
- overrides->erase(override++);
- }
-}
-
-} // namespace
-
-Args::ValueWithOverride::ValueWithOverride()
- : default_value(),
- has_override(false),
- override_value() {
-}
-
-Args::ValueWithOverride::ValueWithOverride(const Value& def_val)
- : default_value(def_val),
- has_override(false),
- override_value() {
-}
-
-Args::ValueWithOverride::~ValueWithOverride() = default;
-
-Args::Args() = default;
-
-Args::Args(const Args& other)
- : overrides_(other.overrides_),
- all_overrides_(other.all_overrides_),
- declared_arguments_per_toolchain_(
- other.declared_arguments_per_toolchain_),
- toolchain_overrides_(other.toolchain_overrides_) {
-}
-
-Args::~Args() = default;
-
-void Args::AddArgOverride(const char* name, const Value& value) {
- base::AutoLock lock(lock_);
-
- overrides_[base::StringPiece(name)] = value;
- all_overrides_[base::StringPiece(name)] = value;
-}
-
-void Args::AddArgOverrides(const Scope::KeyValueMap& overrides) {
- base::AutoLock lock(lock_);
-
- for (const auto& cur_override : overrides) {
- overrides_[cur_override.first] = cur_override.second;
- all_overrides_[cur_override.first] = cur_override.second;
- }
-}
-
-void Args::AddDefaultArgOverrides(const Scope::KeyValueMap& overrides) {
- base::AutoLock lock(lock_);
- for (const auto& cur_override : overrides)
- overrides_[cur_override.first] = cur_override.second;
-}
-
-const Value* Args::GetArgOverride(const char* name) const {
- base::AutoLock lock(lock_);
-
- Scope::KeyValueMap::const_iterator found =
- all_overrides_.find(base::StringPiece(name));
- if (found == all_overrides_.end())
- return nullptr;
- return &found->second;
-}
-
-void Args::SetupRootScope(Scope* dest,
- const Scope::KeyValueMap& toolchain_overrides) const {
- base::AutoLock lock(lock_);
-
- SetSystemVarsLocked(dest);
-
- // Apply overrides for already declared args.
- // (i.e. the system vars we set above)
- ApplyOverridesLocked(overrides_, dest);
- ApplyOverridesLocked(toolchain_overrides, dest);
-
- OverridesForToolchainLocked(dest) = toolchain_overrides;
-
- SaveOverrideRecordLocked(toolchain_overrides);
-}
-
-bool Args::DeclareArgs(const Scope::KeyValueMap& args,
- Scope* scope_to_set,
- Err* err) const {
- base::AutoLock lock(lock_);
-
- Scope::KeyValueMap& declared_arguments(
- DeclaredArgumentsForToolchainLocked(scope_to_set));
-
- const Scope::KeyValueMap& toolchain_overrides(
- OverridesForToolchainLocked(scope_to_set));
-
- for (const auto& arg : args) {
- // Verify that the value hasn't already been declared. We want each value
- // to be declared only once.
- //
- // The tricky part is that a buildfile can be interpreted multiple times
- // when used from different toolchains, so we can't just check that we've
- // seen it before. Instead, we check that the location matches.
- Scope::KeyValueMap::iterator previously_declared =
- declared_arguments.find(arg.first);
- if (previously_declared != declared_arguments.end()) {
- if (previously_declared->second.origin() != arg.second.origin()) {
- // Declaration location mismatch.
- *err = Err(arg.second.origin(),
- "Duplicate build argument declaration.",
- "Here you're declaring an argument that was already declared "
- "elsewhere.\nYou can only declare each argument once in the entire "
- "build so there is one\ncanonical place for documentation and the "
- "default value. Either move this\nargument to the build config "
- "file (for visibility everywhere) or to a .gni file\nthat you "
- "\"import\" from the files where you need it (preferred).");
- err->AppendSubErr(Err(previously_declared->second.origin(),
- "Previous declaration.",
- "See also \"gn help buildargs\" for more on how "
- "build arguments work."));
- return false;
- }
- } else {
- declared_arguments.insert(arg);
- }
-
- // In all the cases below, mark the variable used. If a variable is set
- // that's only used in one toolchain, we don't want to report unused
- // variable errors in other toolchains. Also, in some cases it's reasonable
- // for the build file to overwrite the value with a different value based
- // on some other condition without dereferencing the value first.
-
- // Check whether this argument has been overridden on the toolchain level
- // and use the override instead.
- Scope::KeyValueMap::const_iterator toolchain_override =
- toolchain_overrides.find(arg.first);
- if (toolchain_override != toolchain_overrides.end()) {
- scope_to_set->SetValue(toolchain_override->first,
- toolchain_override->second,
- toolchain_override->second.origin());
- scope_to_set->MarkUsed(arg.first);
- continue;
- }
-
- // Check whether this argument has been overridden and use the override
- // instead.
- Scope::KeyValueMap::const_iterator override = overrides_.find(arg.first);
- if (override != overrides_.end()) {
- scope_to_set->SetValue(override->first, override->second,
- override->second.origin());
- scope_to_set->MarkUsed(override->first);
- continue;
- }
-
- scope_to_set->SetValue(arg.first, arg.second, arg.second.origin());
- scope_to_set->MarkUsed(arg.first);
- }
-
- return true;
-}
-
-bool Args::VerifyAllOverridesUsed(Err* err) const {
- base::AutoLock lock(lock_);
- Scope::KeyValueMap unused_overrides(all_overrides_);
- for (const auto& map_pair : declared_arguments_per_toolchain_)
- RemoveDeclaredOverrides(map_pair.second, &unused_overrides);
-
- if (unused_overrides.empty())
- return true;
-
- // Some assignments in args.gn had no effect. Show an error for the first
- // unused assignment.
- base::StringPiece name = unused_overrides.begin()->first;
- const Value& value = unused_overrides.begin()->second;
-
- std::string err_help(
- "The variable \"" + name + "\" was set as a build argument\n"
- "but never appeared in a declare_args() block in any buildfile.\n\n"
- "To view all possible args, run \"gn args --list <out_dir>\"");
-
- // Use all declare_args for a spelling suggestion.
- std::vector<base::StringPiece> candidates;
- for (const auto& map_pair : declared_arguments_per_toolchain_) {
- for (const auto& declared_arg : map_pair.second)
- candidates.push_back(declared_arg.first);
- }
- base::StringPiece suggestion = SpellcheckString(name, candidates);
- if (!suggestion.empty())
- err_help = "Did you mean \"" + suggestion + "\"?\n\n" + err_help;
-
- *err = Err(value.origin(), "Build argument has no effect.", err_help);
- return false;
-}
-
-Args::ValueWithOverrideMap Args::GetAllArguments() const {
- ValueWithOverrideMap result;
-
- base::AutoLock lock(lock_);
-
- // Default values.
- for (const auto& map_pair : declared_arguments_per_toolchain_) {
- for (const auto& arg : map_pair.second)
- result.insert(std::make_pair(arg.first, ValueWithOverride(arg.second)));
- }
-
- // Merge in overrides.
- for (const auto& over : overrides_) {
- auto found = result.find(over.first);
- if (found != result.end()) {
- found->second.has_override = true;
- found->second.override_value = over.second;
- }
- }
-
- return result;
-}
-
-void Args::SetSystemVarsLocked(Scope* dest) const {
- lock_.AssertAcquired();
-
- // Host OS.
- const char* os = nullptr;
-#if defined(OS_WIN)
- os = "win";
-#elif defined(OS_MACOSX)
- os = "mac";
-#elif defined(OS_LINUX)
- os = "linux";
-#elif defined(OS_ANDROID)
- os = "android";
-#elif defined(OS_NETBSD)
- os = "netbsd";
-#elif defined(OS_AIX)
- os = "aix";
-#elif defined(OS_FUCHSIA)
- os = "fuchsia";
-#else
- #error Unknown OS type.
-#endif
- // NOTE: Adding a new port? Please follow
- // https://chromium.googlesource.com/chromium/src/+/master/docs/new_port_policy.md
-
- // Host architecture.
- static const char kX86[] = "x86";
- static const char kX64[] = "x64";
- static const char kArm[] = "arm";
- static const char kArm64[] = "arm64";
- static const char kMips[] = "mipsel";
- static const char kMips64[] = "mips64el";
- static const char kS390X[] = "s390x";
- static const char kPPC64[] = "ppc64";
- const char* arch = nullptr;
-
- // Set the host CPU architecture based on the underlying OS, not
- // whatever the current bit-tedness of the GN binary is.
- std::string os_arch = base::SysInfo::OperatingSystemArchitecture();
- if (os_arch == "x86")
- arch = kX86;
- else if (os_arch == "x86_64")
- arch = kX64;
- else if (os_arch.substr(0, 3) == "arm")
- arch = kArm;
- else if (os_arch == "aarch64")
- arch = kArm64;
- else if (os_arch == "mips")
- arch = kMips;
- else if (os_arch == "mips64")
- arch = kMips64;
- else if (os_arch == "s390x")
- arch = kS390X;
- else if (os_arch == "ppc64" || os_arch == "ppc64le")
- // We handle the endianness inside //build/config/host_byteorder.gni.
- // This allows us to use the same toolchain as ppc64 BE
- // and specific flags are included using the host_byteorder logic.
- arch = kPPC64;
- else
- CHECK(false) << "OS architecture not handled. (" << os_arch << ")";
-
- // Save the OS and architecture as build arguments that are implicitly
- // declared. This is so they can be overridden in a toolchain build args
- // override, and so that they will appear in the "gn args" output.
- Value empty_string(nullptr, std::string());
-
- Value os_val(nullptr, std::string(os));
- dest->SetValue(variables::kHostOs, os_val, nullptr);
- dest->SetValue(variables::kTargetOs, empty_string, nullptr);
- dest->SetValue(variables::kCurrentOs, empty_string, nullptr);
-
- Value arch_val(nullptr, std::string(arch));
- dest->SetValue(variables::kHostCpu, arch_val, nullptr);
- dest->SetValue(variables::kTargetCpu, empty_string, nullptr);
- dest->SetValue(variables::kCurrentCpu, empty_string, nullptr);
-
- Scope::KeyValueMap& declared_arguments(
- DeclaredArgumentsForToolchainLocked(dest));
- declared_arguments[variables::kHostOs] = os_val;
- declared_arguments[variables::kCurrentOs] = empty_string;
- declared_arguments[variables::kTargetOs] = empty_string;
- declared_arguments[variables::kHostCpu] = arch_val;
- declared_arguments[variables::kCurrentCpu] = empty_string;
- declared_arguments[variables::kTargetCpu] = empty_string;
-
- // Mark these variables used so the build config file can override them
- // without geting a warning about overwriting an unused variable.
- dest->MarkUsed(variables::kHostCpu);
- dest->MarkUsed(variables::kCurrentCpu);
- dest->MarkUsed(variables::kTargetCpu);
- dest->MarkUsed(variables::kHostOs);
- dest->MarkUsed(variables::kCurrentOs);
- dest->MarkUsed(variables::kTargetOs);
-}
-
-void Args::ApplyOverridesLocked(const Scope::KeyValueMap& values,
- Scope* scope) const {
- lock_.AssertAcquired();
-
- const Scope::KeyValueMap& declared_arguments(
- DeclaredArgumentsForToolchainLocked(scope));
-
- // Only set a value if it has been declared.
- for (const auto& val : values) {
- Scope::KeyValueMap::const_iterator declared =
- declared_arguments.find(val.first);
-
- if (declared == declared_arguments.end())
- continue;
-
- scope->SetValue(val.first, val.second, val.second.origin());
- }
-}
-
-void Args::SaveOverrideRecordLocked(const Scope::KeyValueMap& values) const {
- lock_.AssertAcquired();
- for (const auto& val : values)
- all_overrides_[val.first] = val.second;
-}
-
-Scope::KeyValueMap& Args::DeclaredArgumentsForToolchainLocked(
- Scope* scope) const {
- lock_.AssertAcquired();
- return declared_arguments_per_toolchain_[scope->settings()];
-}
-
-Scope::KeyValueMap& Args::OverridesForToolchainLocked(
- Scope* scope) const {
- lock_.AssertAcquired();
- return toolchain_overrides_[scope->settings()];
-}
diff --git a/chromium/tools/gn/args.h b/chromium/tools/gn/args.h
deleted file mode 100644
index ee45085e9f3..00000000000
--- a/chromium/tools/gn/args.h
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_ARGS_H_
-#define TOOLS_GN_ARGS_H_
-
-#include <map>
-#include <set>
-
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/synchronization/lock.h"
-#include "tools/gn/scope.h"
-
-class Err;
-class SourceFile;
-
-extern const char kBuildArgs_Help[];
-
-// Manages build arguments. It stores the global arguments specified on the
-// command line, and sets up the root scope with the proper values.
-//
-// This class tracks accesses so we can report errors about unused variables.
-// The use case is if the user specifies an override on the command line, but
-// no buildfile actually uses that variable. We want to be able to report that
-// the argument was unused.
-class Args {
- public:
- struct ValueWithOverride {
- ValueWithOverride();
- ValueWithOverride(const Value& def_val);
- ~ValueWithOverride();
-
- Value default_value; // Default value given in declare_args.
-
- bool has_override; // True indicates override_value is valid.
- Value override_value; // From .gn or the current build's "gn args".
- };
- using ValueWithOverrideMap = std::map<base::StringPiece, ValueWithOverride>;
-
- Args();
- Args(const Args& other);
- ~Args();
-
- // Specifies overrides of the build arguments. These are normally specified
- // on the command line.
- void AddArgOverride(const char* name, const Value& value);
- void AddArgOverrides(const Scope::KeyValueMap& overrides);
-
- // Specifies default overrides of the build arguments. These are normally
- // specified in the .gn file.
- void AddDefaultArgOverrides(const Scope::KeyValueMap& overrides);
-
- // Returns the value corresponding to the given argument name, or NULL if no
- // argument is set.
- const Value* GetArgOverride(const char* name) const;
-
- // Sets up the root scope for a toolchain. This applies the default system
- // flags and saves the toolchain overrides so they can be applied to
- // declare_args blocks that appear when loading files in that toolchain.
- void SetupRootScope(Scope* dest,
- const Scope::KeyValueMap& toolchain_overrides) const;
-
- // Sets up the given scope with arguments passed in.
- //
- // If the values specified in the args are not already set, the values in
- // the args list will be used (which are assumed to be the defaults), but
- // they will not override the system defaults or the current overrides.
- //
- // All args specified in the input will be marked as "used".
- //
- // On failure, the err will be set and it will return false.
- bool DeclareArgs(const Scope::KeyValueMap& args,
- Scope* scope_to_set,
- Err* err) const;
-
- // Checks to see if any of the overrides ever used were never declared as
- // arguments. If there are, this returns false and sets the error.
- bool VerifyAllOverridesUsed(Err* err) const;
-
- // Returns information about all arguments, both defaults and overrides.
- // This is used for the help system which is not performance critical. Use a
- // map instead of a hash map so the arguments are sorted alphabetically.
- ValueWithOverrideMap GetAllArguments() const;
-
- // Returns the set of build files that may affect the build arguments, please
- // refer to Scope for how this is determined.
- const std::set<SourceFile>& build_args_dependency_files() const {
- return build_args_dependency_files_;
- }
-
- void set_build_args_dependency_files(
- const std::set<SourceFile>& build_args_dependency_files) {
- build_args_dependency_files_ = build_args_dependency_files;
- }
-
- private:
- using ArgumentsPerToolchain =
- base::hash_map<const Settings*, Scope::KeyValueMap>;
-
- // Sets the default config based on the current system.
- void SetSystemVarsLocked(Scope* scope) const;
-
- // Sets the given already declared vars on the given scope.
- void ApplyOverridesLocked(const Scope::KeyValueMap& values,
- Scope* scope) const;
-
- void SaveOverrideRecordLocked(const Scope::KeyValueMap& values) const;
-
- // Returns the KeyValueMap used for arguments declared for the specified
- // toolchain.
- Scope::KeyValueMap& DeclaredArgumentsForToolchainLocked(Scope* scope) const;
-
- // Returns the KeyValueMap used for overrides for the specified
- // toolchain.
- Scope::KeyValueMap& OverridesForToolchainLocked(Scope* scope) const;
-
- // Since this is called during setup which we assume is single-threaded,
- // this is not protected by the lock. It should be set only during init.
- Scope::KeyValueMap overrides_;
-
- mutable base::Lock lock_;
-
- // Maintains a list of all overrides we've ever seen. This is the main
- // |overrides_| as well as toolchain overrides. Tracking this allows us to
- // check for overrides that were specified but never used.
- mutable Scope::KeyValueMap all_overrides_;
-
- // Maps from Settings (which corresponds to a toolchain) to the map of
- // declared variables. This is used to tracks all variables declared in any
- // buildfile. This is so we can see if the user set variables on the command
- // line that are not used anywhere. Each map is toolchain specific as each
- // toolchain may define variables in different locations.
- mutable ArgumentsPerToolchain declared_arguments_per_toolchain_;
-
- // Overrides for individual toolchains. This is necessary so we
- // can apply the correct override for the current toolchain, once
- // we see an argument declaration.
- mutable ArgumentsPerToolchain toolchain_overrides_;
-
- std::set<SourceFile> build_args_dependency_files_;
-
- DISALLOW_ASSIGN(Args);
-};
-
-#endif // TOOLS_GN_ARGS_H_
diff --git a/chromium/tools/gn/args_unittest.cc b/chromium/tools/gn/args_unittest.cc
deleted file mode 100644
index cf51036fb66..00000000000
--- a/chromium/tools/gn/args_unittest.cc
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/args.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/test_with_scope.h"
-
-// Assertions for VerifyAllOverridesUsed() and DeclareArgs() with multiple
-// toolchains.
-TEST(ArgsTest, VerifyAllOverridesUsed) {
- TestWithScope setup1, setup2;
- Args args;
- Scope::KeyValueMap key_value_map1;
- Err err;
- LiteralNode assignment1;
-
- setup1.scope()->SetValue("a", Value(nullptr, true), &assignment1);
- setup1.scope()->GetCurrentScopeValues(&key_value_map1);
- EXPECT_TRUE(args.DeclareArgs(key_value_map1, setup1.scope(), &err));
-
- LiteralNode assignment2;
- setup2.scope()->SetValue("b", Value(nullptr, true), &assignment2);
- Scope::KeyValueMap key_value_map2;
- setup2.scope()->GetCurrentScopeValues(&key_value_map2);
- EXPECT_TRUE(args.DeclareArgs(key_value_map2, setup2.scope(), &err));
-
- // Override "a", shouldn't see any errors as "a" was defined.
- args.AddArgOverride("a", Value(nullptr, true));
- EXPECT_TRUE(args.VerifyAllOverridesUsed(&err));
-
- // Override "a", & "b", shouldn't see any errors as both were defined.
- args.AddArgOverride("b", Value(nullptr, true));
- EXPECT_TRUE(args.VerifyAllOverridesUsed(&err));
-
- // Override "a", "b" and "c", should fail as "c" was not defined.
- args.AddArgOverride("c", Value(nullptr, true));
- EXPECT_FALSE(args.VerifyAllOverridesUsed(&err));
-}
-
-// Ensure that arg overrides get only set after the they were declared.
-TEST(ArgsTest, VerifyOverrideScope) {
- TestWithScope setup;
- Args args;
- Err err;
-
- args.AddArgOverride("a", Value(nullptr, "avalue"));
- args.AddArgOverride("current_os", Value(nullptr, "theiros"));
-
- Scope::KeyValueMap toolchain_overrides;
- toolchain_overrides["b"] = Value(nullptr, "bvalue");
- toolchain_overrides["current_os"] = Value(nullptr, "myos");
- args.SetupRootScope(setup.scope(), toolchain_overrides);
-
- // Overrides of arguments not yet declared aren't applied yet.
- EXPECT_EQ(nullptr, setup.scope()->GetValue("a"));
- EXPECT_EQ(nullptr, setup.scope()->GetValue("b"));
-
- // |current_os| is a system var. and already declared.
- // Thus it should have our override value.
- ASSERT_NE(nullptr, setup.scope()->GetValue("current_os"));
- EXPECT_EQ(Value(nullptr, "myos"), *setup.scope()->GetValue("current_os"));
-
- Scope::KeyValueMap key_value_map1;
- key_value_map1["a"] = Value(nullptr, "avalue2");
- key_value_map1["b"] = Value(nullptr, "bvalue2");
- key_value_map1["c"] = Value(nullptr, "cvalue2");
- EXPECT_TRUE(args.DeclareArgs(key_value_map1, setup.scope(), &err));
-
- ASSERT_NE(nullptr, setup.scope()->GetValue("a"));
- EXPECT_EQ(Value(nullptr, "avalue"), *setup.scope()->GetValue("a"));
-
- ASSERT_NE(nullptr, setup.scope()->GetValue("b"));
- EXPECT_EQ(Value(nullptr, "bvalue"), *setup.scope()->GetValue("b"));
-
- // This wasn't overwritten, so it should have the default value.
- ASSERT_NE(nullptr, setup.scope()->GetValue("c"));
- EXPECT_EQ(Value(nullptr, "cvalue2"), *setup.scope()->GetValue("c"));
-}
diff --git a/chromium/tools/gn/bin/compare_test_lists.py b/chromium/tools/gn/bin/compare_test_lists.py
deleted file mode 100644
index 37fb1bf1e26..00000000000
--- a/chromium/tools/gn/bin/compare_test_lists.py
+++ /dev/null
@@ -1,101 +0,0 @@
-# Copyright 2015 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This script compares the gtest test list for two different builds.
-#
-# Usage:
-# compare_test_lists.py <build_dir_1> <build_dir_2> <binary_name>
-#
-# For example, from the "src" directory:
-# python tools/gn/bin/compare_test_lists.py out/Debug out/gnbuild ipc_tests
-#
-# This will compile the given binary in both output directories, then extracts
-# the test lists and prints missing or extra tests between the first and the
-# second build.
-
-import os
-import subprocess
-import sys
-
-def BuildBinary(build_dir, binary_name):
- """Builds the given binary in the given directory with Ninja.
-
- Returns True on success."""
- return subprocess.call(["ninja", "-C", build_dir, binary_name]) == 0
-
-
-def GetTestList(path_to_binary):
- """Returns a set of full test names.
-
- Each test will be of the form "Case.Test". There will be a separate line
- for each combination of Case/Test (there are often multiple tests in each
- case).
-
- Throws an exception on failure."""
- raw_output = subprocess.check_output([path_to_binary, "--gtest_list_tests"])
- input_lines = raw_output.split('\n')
-
- # The format of the gtest_list_tests output is:
- # "Case1."
- # " Test1 # <Optional extra stuff>"
- # " Test2"
- # "Case2."
- # " Test1"
- case_name = '' # Includes trailing dot.
- test_set = set()
- for line in input_lines:
- if len(line) > 1:
- if line[0] == ' ':
- # Indented means a test in previous case.
- test_set.add(case_name + line[:line.find('#')].strip())
- else:
- # New test case.
- case_name = line.strip()
-
- return test_set
-
-
-def PrintSetDiff(a_name, a, b_name, b, binary_name):
- """Prints the test list difference between the given sets a and b.
-
- a_name and b_name will be used to refer to the directories of the two sets,
- and the binary name will be shown as the source of the output."""
-
- a_not_b = list(a - b)
- if len(a_not_b):
- print "\n", binary_name, "tests in", a_name, "but not", b_name
- a_not_b.sort()
- for cur in a_not_b:
- print " ", cur
-
- b_not_a = list(b - a)
- if len(b_not_a):
- print "\n", binary_name, "tests in", b_name, "but not", a_name
- b_not_a.sort()
- for cur in b_not_a:
- print " ", cur
-
- if len(a_not_b) == 0 and len(b_not_a) == 0:
- print "\nTests match!"
-
-
-def Run(a_dir, b_dir, binary_name):
- if not BuildBinary(a_dir, binary_name):
- print "Building", binary_name, "in", a_dir, "failed"
- return 1
- if not BuildBinary(b_dir, binary_name):
- print "Building", binary_name, "in", b_dir, "failed"
- return 1
-
- a_tests = GetTestList(os.path.join(a_dir, binary_name))
- b_tests = GetTestList(os.path.join(b_dir, binary_name))
-
- PrintSetDiff(a_dir, a_tests, b_dir, b_tests, binary_name)
-
-
-if len(sys.argv) != 4:
- print "Usage: compare_test_lists.py <build_dir_1> <build_dir_2> " \
- "<test_binary_name>"
- sys.exit(1)
-sys.exit(Run(sys.argv[1], sys.argv[2], sys.argv[3]))
diff --git a/chromium/tools/gn/bin/gn-format.py b/chromium/tools/gn/bin/gn-format.py
deleted file mode 100644
index 561c76c828a..00000000000
--- a/chromium/tools/gn/bin/gn-format.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-#
-# Based on clang-format.py.
-#
-# This file is a minimal gn format vim-integration. To install:
-# - Change 'binary' if gn is not on the path (see below).
-# - Add to your .vimrc:
-#
-# map <F1> :pyf <path-to-this-file>/gn-format.py<CR>
-#
-# gn format currently formats only a complete file so visual ranges, etc. won't
-# be used. It operates on the current, potentially unsaved buffer and does not
-# create or save any files. To revert a formatting, just undo.
-
-import difflib
-import subprocess
-import sys
-import vim
-
-# Change this to the full path if gn is not on the path.
-binary = 'gn'
-
-def main():
- # Get the current text.
- buf = vim.current.buffer
- text = '\n'.join(buf)
-
- is_win = sys.platform.startswith('win32')
- # Avoid flashing an ugly cmd prompt on Windows when invoking gn.
- startupinfo = None
- if is_win:
- startupinfo = subprocess.STARTUPINFO()
- startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
- startupinfo.wShowWindow = subprocess.SW_HIDE
-
- # Call formatter. Needs shell=True on Windows due to gn.bat in depot_tools.
- p = subprocess.Popen([binary, 'format', '--stdin'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE,
- stdin=subprocess.PIPE, startupinfo=startupinfo,
- shell=is_win, universal_newlines=True)
- stdout, stderr = p.communicate(input=text)
- if p.returncode != 0:
- print 'Formatting failed, please report to gn-dev@chromium.org.'
- print stdout, stderr
- else:
- # Otherwise, replace current buffer.
- lines = stdout.split('\n')
- # Last line should have trailing \n, but we don't want to insert a blank
- # line at the end of the buffer, so remove that.
- if lines[-1] == '':
- lines = lines[:-1]
- sequence = difflib.SequenceMatcher(None, vim.current.buffer, lines)
- for op in reversed(sequence.get_opcodes()):
- if op[0] is not 'equal':
- vim.current.buffer[op[1]:op[2]] = lines[op[3]:op[4]]
-
-main()
diff --git a/chromium/tools/gn/bin/help_as_html.py b/chromium/tools/gn/bin/help_as_html.py
deleted file mode 100755
index f8f1c1bc271..00000000000
--- a/chromium/tools/gn/bin/help_as_html.py
+++ /dev/null
@@ -1,105 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Runs 'gn help' and various subhelps, and spits out html.
-# TODO:
-# - Handle numbered and dashed lists -> <ol> <ul>. (See "os" and "toolchain").
-# - Handle "Arguments:" blocks a bit better (the argument names could be
-# distinguished).
-# - Convert "|blahblah|" to <code>.
-# - Spit out other similar formats like wiki, markdown, whatever.
-
-import cgi
-import subprocess
-import sys
-
-
-def GetOutput(*args):
- try:
- return subprocess.check_output([sys.argv[1]] + list(args))
- except subprocess.CalledProcessError:
- return ''
-
-
-def ParseTopLevel(out):
- commands = []
- output = []
- for line in out.splitlines():
- if line.startswith(' '):
- command, sep, rest = line.partition(':')
- command = command.strip()
- is_option = command.startswith('-')
- output_line = ['<li>']
- if not is_option:
- commands.append(command)
- output_line.append('<a href="#' + cgi.escape(command) + '">')
- output_line.append(cgi.escape(command))
- if not is_option:
- output_line.append('</a>')
- output_line.extend([sep + cgi.escape(rest) + '</li>'])
- output.append(''.join(output_line))
- else:
- output.append('<h2>' + cgi.escape(line) + '</h2>')
- return commands, output
-
-
-def ParseCommand(command, out):
- first_line = True
- got_example = False
- output = []
- for line in out.splitlines():
- if first_line:
- name, sep, rest = line.partition(':')
- name = name.strip()
- output.append('<h3><a name="' + cgi.escape(command) + '">' +
- cgi.escape(name + sep + rest) + '</a></h3>')
- first_line = False
- else:
- if line.startswith('Example'):
- # Special subsection that's pre-formatted.
- if got_example:
- output.append('</pre>')
- got_example = True
- output.append('<h4>Example</h4>')
- output.append('<pre>')
- elif not line.strip():
- output.append('<p>')
- elif not line.startswith(' ') and line.endswith(':'):
- # Subsection.
- output.append('<h4>' + cgi.escape(line[:-1]) + '</h4>')
- else:
- output.append(cgi.escape(line))
- if got_example:
- output.append('</pre>')
- return output
-
-
-def main():
- if len(sys.argv) < 2:
- print 'usage: help_as_html.py <gn_binary>'
- return 1
- header = '''<!DOCTYPE html>
-<html>
- <head>
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <style>
- body { font-family: Arial, sans-serif; font-size: small; }
- pre { font-family: Consolas, monospace; font-size: small; }
- #container { margin: 0 auto; max-width: 48rem; width: 90%; }
- </style>
- </head>
- <body>
- <div id="container"><h1>GN</h1>
-'''
- footer = '</div></body></html>'
- commands, output = ParseTopLevel(GetOutput('help'))
- for command in commands:
- output += ParseCommand(command, GetOutput('help', command))
- print header + '\n'.join(output) + footer
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/chromium/tools/gn/bin/roll_gn.py b/chromium/tools/gn/bin/roll_gn.py
deleted file mode 100755
index cf4c878c242..00000000000
--- a/chromium/tools/gn/bin/roll_gn.py
+++ /dev/null
@@ -1,461 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""An auto-roller for GN binaries into Chromium.
-
-This script is used to update the GN binaries that a Chromium
-checkout uses. In order to update the binaries, one must follow
-four steps in order:
-
-1. Trigger try jobs to build a new GN binary at tip-of-tree and upload
- the newly-built binaries into the right Google CloudStorage bucket.
-2. Wait for the try jobs to complete.
-3. Update the buildtools repo with the .sha1 hashes of the newly built
- binaries.
-4. Update Chromium's DEPS file to the new version of the buildtools repo.
-
-The script has four commands that correspond to the four steps above:
-'build', 'wait', 'roll_buildtools', and 'roll_deps'.
-
-The script has a fifth command, 'roll', that runs the four in order.
-
-If given no arguments, the script will run the 'roll' command.
-
-It can only be run on linux in a clean Chromium checkout; it should
-error out in most cases if something bad happens, but the error checking
-isn't yet foolproof.
-
-"""
-
-from __future__ import print_function
-
-import argparse
-import json
-import os
-import re
-import subprocess
-import sys
-import tempfile
-import time
-import urllib2
-
-
-depot_tools_path = os.path.abspath(os.path.normpath(os.path.join(
- os.path.dirname(__file__), '..', '..', '..', 'third_party', 'depot_tools')))
-if not depot_tools_path in sys.path:
- sys.path.insert(0, depot_tools_path)
-
-
-CHROMIUM_REPO = 'https://chromium.googlesource.com/chromium/src.git'
-
-COMMITISH_DIGITS = 10
-
-UNKNOWN, PENDING, STARTED, SUCCESS = (
- 'unknown', 'pending', 'started', 'success')
-
-class BuildResult(object):
- def __init__(self):
- self.masterName = '-'
- self.builderName = '-'
- self.buildNumber = '-'
- self.state = UNKNOWN
- self.sha1 = '-'
- self.url = '-'
-
-
-class GNRoller(object):
- def __init__(self):
- self.chromium_src_dir = None
- self.buildtools_dir = None
- self.old_gn_commitish = None
- self.new_gn_commitish = None
- self.old_gn_version = None
- self.new_gn_version = None
- self.reviewer = 'dpranke@chromium.org'
- if os.getenv('USER') == 'dpranke':
- self.reviewer = 'brettw@chromium.org'
-
- def Roll(self):
- parser = argparse.ArgumentParser()
- parser.usage = __doc__
- parser.add_argument('command', nargs='?', default='roll',
- help='build|roll|roll_buildtools|roll_deps|wait'
- ' (%(default)s is the default)')
-
- args = parser.parse_args()
- command = args.command
- ret = self.SetUp()
- if not ret and command in ('roll', 'build'):
- ret = self.TriggerBuild()
- if not ret and command in ('roll', 'wait'):
- ret = self.WaitForBuildToFinish()
- if not ret and command in ('roll', 'roll_buildtools'):
- ret = self.RollBuildtools()
- if not ret and command in ('roll', 'roll_deps'):
- ret = self.RollDEPS()
-
- return ret
-
- def SetUp(self):
- if sys.platform not in ('darwin', 'linux2'):
- print('roll_gn is only tested and working on Linux and Mac for now.')
- return 1
-
- ret, out, _ = self.Call('git config --get remote.origin.url')
- origin = out.strip()
- if ret or origin != CHROMIUM_REPO:
- print('Not in a Chromium repo? git config --get remote.origin.url '
- 'returned %d: %s' % (ret, origin))
- return 1
-
- ret, _, _ = self.Call('git diff -q')
- if ret:
- print("Checkout is dirty, exiting")
- return 1
-
- _, out, _ = self.Call('git rev-parse --show-toplevel', cwd=os.getcwd())
- self.chromium_src_dir = out.strip()
- self.buildtools_dir = os.path.join(self.chromium_src_dir, 'buildtools')
-
- self.new_gn_commitish, self.new_gn_version = self.GetNewVersions()
-
- _, out, _ = self.Call('gn --version')
- self.old_gn_version = out.strip()
-
- _, out, _ = self.Call('git crrev-parse %s' % self.old_gn_version)
- self.old_gn_commitish = out.strip()
- return 0
-
- def GetNewVersions(self):
- _, out, _ = self.Call('git log -1 --grep Cr-Commit-Position')
- commit_msg = out.splitlines()
- first_line = commit_msg[0]
- new_gn_commitish = first_line.split()[1]
-
- last_line = commit_msg[-1]
- new_gn_version = re.sub('.*master@{#(\d+)}', '\\1', last_line)
-
- return new_gn_commitish, new_gn_version
-
- def TriggerBuild(self):
- ret, _, _ = self.Call('git new-branch build_gn_%s' % self.new_gn_version)
- if ret:
- print('Failed to create a new branch for build_gn_%s' %
- self.new_gn_version)
- return 1
-
- self.MakeDummyDepsChange()
-
- ret, out, err = self.Call('git commit -a -m "Build gn at %s"' %
- self.new_gn_version)
- if ret:
- print('git commit failed: %s' % out + err)
- return 1
-
- print('Uploading CL to build GN at {#%s} - %s' %
- (self.new_gn_version, self.new_gn_commitish))
- ret, out, err = self.Call('git cl upload -f')
- if ret:
- print('git-cl upload failed: %s' % out + err)
- return 1
-
- print('Starting try jobs')
- self.Call('git-cl try -m tryserver.chromium.linux '
- '-b linux_chromium_gn_upload -r %s' % self.new_gn_commitish)
- self.Call('git-cl try -m tryserver.chromium.mac '
- '-b mac_chromium_gn_upload -r %s' % self.new_gn_commitish)
- self.Call('git-cl try -m tryserver.chromium.win '
- '-b win_chromium_gn_upload -r %s' % self.new_gn_commitish)
-
- return 0
-
- def MakeDummyDepsChange(self):
- with open('DEPS') as fp:
- deps_content = fp.read()
- new_deps = deps_content.replace("'buildtools_revision':",
- "'buildtools_revision': ")
-
- with open('DEPS', 'w') as fp:
- fp.write(new_deps)
-
- def WaitForBuildToFinish(self):
- ret = self.CheckoutBuildBranch()
- if ret:
- return ret
-
- print('Checking build')
- results = self.CheckBuild()
- while (any(r.state in (PENDING, STARTED) for r in results.values())):
- print()
- print('Sleeping for 30 seconds')
- time.sleep(30)
- print('Checking build')
- results = self.CheckBuild()
-
- ret = 0 if all(r.state == SUCCESS for r in results.values()) else 1
- if ret:
- print('Build failed.')
- else:
- print('Builds ready.')
-
- # Close the build CL and move off of the build branch back to whatever
- # we were on before.
- self.Call('git-cl set-close')
- self.MoveToLastHead()
-
- return ret
-
- def CheckoutBuildBranch(self):
- ret, out, err = self.Call('git checkout build_gn_%s' % self.new_gn_version)
- if ret:
- print('Failed to check out build_gn_%s' % self.new_gn_version)
- if out:
- print(out)
- if err:
- print(err, file=sys.stderr)
- return ret
-
- def CheckBuild(self):
- _, out, _ = self.Call('git-cl try-results')
-
- builders = {
- 'linux_chromium_gn_upload': 'linux64',
- 'mac_chromium_gn_upload': 'mac',
- 'win_chromium_gn_upload': 'win'
- }
-
- results = {}
- for platform in ('linux64', 'mac', 'win'):
- results[platform] = BuildResult()
-
- state = PENDING
- for line in out.splitlines():
- fields = line.strip().split()
- if fields[0] == 'Started:':
- state = STARTED
- if fields[0] == 'Successes:':
- state = SUCCESS
- elif fields[0] == 'Total':
- pass
- elif fields[0] in builders:
- builder = fields[0]
- platform = builders[builder]
- result = results[platform]
- result.masterName = ('tryserver.chromium.%s' %
- platform.replace('linux64', 'linux'))
- result.builderName = builder
- result.url = fields[1]
- if result.url.startswith('id'):
- result.state = PENDING
- else:
- result.state = state
- result.buildNumber = int(result.url[result.url.rfind('/')+1:])
-
- for result in results.values():
- if result.state == SUCCESS:
- url = 'https://luci-milo.appspot.com/prpc/milo.BuildInfo/Get'
- data = json.dumps({"buildbot": {
- 'masterName': result.masterName,
- 'builderName': result.builderName,
- 'buildNumber': result.buildNumber,
- }})
- headers = {
- 'content-type': 'application/json',
- 'accept': 'application/json',
- }
-
- req = urllib2.Request(url, data, headers)
- resp = urllib2.urlopen(req)
- data = resp.read()
- resp.close()
-
- # The first line of the response is garbage; skip it.
- js = json.loads(data.splitlines()[1])
-
- sha1_step_name = 'gn sha1'
- for step in js['step']['substep']:
- if step['step']['name'] == sha1_step_name:
- sha1 = step['step']['text'][-1]
-
- result.sha1 = sha1
-
- for platform, r in results.items():
- print(platform)
- print(' sha1: %s' % r.sha1)
- print(' state: %s' % r.state)
- print(' build: %s' % r.buildNumber)
- print(' url: %s' % r.url)
- print()
-
- return results
-
- def RollBuildtools(self):
- ret = self.CheckoutBuildBranch()
- if ret:
- return ret
-
- results = self.CheckBuild()
- if (len(results) < 3 or
- not all(r.state == SUCCESS for r in results.values()) or
- not all(r.sha1 != '-' for r in results.values())):
- print("Roll isn't done or didn't succeed, exiting:")
- return 1
-
- desc = self.GetBuildtoolsDesc()
-
- self.Call('git new-branch roll_buildtools_gn_%s' % self.new_gn_version,
- cwd=self.buildtools_dir)
-
- for platform in results:
- fname = 'gn.exe.sha1' if platform == 'win' else 'gn.sha1'
- path = os.path.join(self.buildtools_dir, platform, fname)
- with open(path, 'w') as fp:
- fp.write('%s\n' % results[platform].sha1)
-
- desc_file = tempfile.NamedTemporaryFile(delete=False)
- try:
- desc_file.write(desc)
- desc_file.close()
- self.Call('git commit -a -F %s' % desc_file.name,
- cwd=self.buildtools_dir)
- self.Call('git-cl upload -f --send-mail',
- cwd=self.buildtools_dir)
- finally:
- os.remove(desc_file.name)
-
- ret, out, err = self.Call('git cl land', cwd=self.buildtools_dir)
- if ret:
- print("buildtools git cl land failed: %d" % ret)
- if out:
- print(out)
- if err:
- print(err)
- return ret
-
- # Fetch the revision we just committed so that RollDEPS will find it.
- self.Call('git fetch', cwd=self.buildtools_dir)
-
- # Reset buildtools to the new commit so that we're not still on the
- # merged branch.
- self.Call('git checkout origin/master', cwd=self.buildtools_dir)
-
- _, out, _ = self.Call('git rev-parse origin/master',
- cwd=self.buildtools_dir)
- new_buildtools_commitish = out.strip()
- print('Ready to roll buildtools to %s in DEPS' % new_buildtools_commitish)
-
- return 0
-
- def RollDEPS(self):
- ret, _, _ = self.Call('git new-branch roll_gn_%s' % self.new_gn_version)
- if ret:
- print('Failed to create a new branch for roll_gn_%s' %
- self.new_gn_version)
- return 1
-
- _, out, _ = self.Call('git rev-parse origin/master',
- cwd=self.buildtools_dir)
- new_buildtools_commitish = out.strip()
-
- new_deps_lines = []
- old_buildtools_commitish = ''
- with open(os.path.join(self.chromium_src_dir, 'DEPS')) as fp:
- for l in fp.readlines():
- m = re.match(".*'buildtools_revision':.*'(.+)',", l)
- if m:
- old_buildtools_commitish = m.group(1)
- new_deps_lines.append(" 'buildtools_revision': '%s',\n" %
- new_buildtools_commitish)
- else:
- new_deps_lines.append(l)
-
- if not old_buildtools_commitish:
- print('Could not update DEPS properly, exiting')
- return 1
-
- with open('DEPS', 'w') as fp:
- fp.write(''.join(new_deps_lines))
-
- desc = self.GetDEPSRollDesc(old_buildtools_commitish,
- new_buildtools_commitish)
- desc_file = tempfile.NamedTemporaryFile(delete=False)
- try:
- desc_file.write(desc)
- desc_file.close()
- self.Call('git commit -a -F %s' % desc_file.name)
- self.Call('git-cl upload -f --send-mail --use-commit-queue')
- finally:
- os.remove(desc_file.name)
-
- # Move off of the roll branch onto whatever we were on before.
- # Do not explicitly close the roll CL issue, however; the CQ
- # will close it when the roll lands, assuming it does so.
- self.MoveToLastHead()
-
- return 0
-
- def MoveToLastHead(self):
- # When this is called, there will be a commit + a checkout as
- # the two most recent entries in the reflog, assuming nothing as
- # modified the repo while this script has been running.
- _, out, _ = self.Call('git reflog -2')
- m = re.search('moving from ([^\s]+)', out)
- last_head = m.group(1)
- self.Call('git checkout %s' % last_head)
-
- def GetBuildtoolsDesc(self):
- gn_changes = self.GetGNChanges()
- return (
- 'Roll gn %s..%s (r%s:r%s)\n'
- '\n'
- '%s'
- '\n'
- 'TBR=%s\n' % (
- self.old_gn_commitish[:COMMITISH_DIGITS],
- self.new_gn_commitish[:COMMITISH_DIGITS],
- self.old_gn_version,
- self.new_gn_version,
- gn_changes,
- self.reviewer,
- ))
-
- def GetDEPSRollDesc(self, old_buildtools_commitish, new_buildtools_commitish):
- gn_changes = self.GetGNChanges()
-
- return (
- 'Roll buildtools %s..%s\n'
- '\n'
- ' In order to roll GN %s..%s (r%s:r%s) and pick up\n'
- ' the following changes:\n'
- '\n'
- '%s'
- '\n'
- 'TBR=%s\n' % (
- old_buildtools_commitish[:COMMITISH_DIGITS],
- new_buildtools_commitish[:COMMITISH_DIGITS],
- self.old_gn_commitish[:COMMITISH_DIGITS],
- self.new_gn_commitish[:COMMITISH_DIGITS],
- self.old_gn_version,
- self.new_gn_version,
- gn_changes,
- self.reviewer,
- ))
-
- def GetGNChanges(self):
- _, out, _ = self.Call(
- "git log --pretty=' %h %s' " +
- "%s..%s tools/gn" % (self.old_gn_commitish, self.new_gn_commitish))
- return out
-
- def Call(self, cmd, cwd=None):
- proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True,
- cwd=(cwd or self.chromium_src_dir))
- out, err = proc.communicate()
- return proc.returncode, out or '', err or ''
-
-
-if __name__ == '__main__':
- roller = GNRoller()
- sys.exit(roller.Roll())
diff --git a/chromium/tools/gn/binary_target_generator.cc b/chromium/tools/gn/binary_target_generator.cc
deleted file mode 100644
index 4ff9366524c..00000000000
--- a/chromium/tools/gn/binary_target_generator.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/binary_target_generator.h"
-
-#include "tools/gn/config_values_generator.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/value_extractors.h"
-#include "tools/gn/variables.h"
-
-BinaryTargetGenerator::BinaryTargetGenerator(
- Target* target,
- Scope* scope,
- const FunctionCallNode* function_call,
- Target::OutputType type,
- Err* err)
- : TargetGenerator(target, scope, function_call, err),
- output_type_(type) {
-}
-
-BinaryTargetGenerator::~BinaryTargetGenerator() = default;
-
-void BinaryTargetGenerator::DoRun() {
- target_->set_output_type(output_type_);
-
- if (!FillOutputName())
- return;
-
- if (!FillOutputPrefixOverride())
- return;
-
- if (!FillOutputDir())
- return;
-
- if (!FillOutputExtension())
- return;
-
- if (!FillSources())
- return;
-
- if (!FillPublic())
- return;
-
- if (!FillFriends())
- return;
-
- if (!FillCheckIncludes())
- return;
-
- if (!FillConfigs())
- return;
-
- if (!FillAllowCircularIncludesFrom())
- return;
-
- if (!FillCompleteStaticLib())
- return;
-
- // Config values (compiler flags, etc.) set directly on this target.
- ConfigValuesGenerator gen(&target_->config_values(), scope_,
- scope_->GetSourceDir(), err_);
- gen.Run();
- if (err_->has_error())
- return;
-}
-
-bool BinaryTargetGenerator::FillCompleteStaticLib() {
- if (target_->output_type() == Target::STATIC_LIBRARY) {
- const Value* value = scope_->GetValue(variables::kCompleteStaticLib, true);
- if (!value)
- return true;
- if (!value->VerifyTypeIs(Value::BOOLEAN, err_))
- return false;
- target_->set_complete_static_lib(value->boolean_value());
- }
- return true;
-}
-
-bool BinaryTargetGenerator::FillFriends() {
- const Value* value = scope_->GetValue(variables::kFriend, true);
- if (value) {
- return ExtractListOfLabelPatterns(*value, scope_->GetSourceDir(),
- &target_->friends(), err_);
- }
- return true;
-}
-
-bool BinaryTargetGenerator::FillOutputName() {
- const Value* value = scope_->GetValue(variables::kOutputName, true);
- if (!value)
- return true;
- if (!value->VerifyTypeIs(Value::STRING, err_))
- return false;
- target_->set_output_name(value->string_value());
- return true;
-}
-
-bool BinaryTargetGenerator::FillOutputPrefixOverride() {
- const Value* value = scope_->GetValue(variables::kOutputPrefixOverride, true);
- if (!value)
- return true;
- if (!value->VerifyTypeIs(Value::BOOLEAN, err_))
- return false;
- target_->set_output_prefix_override(value->boolean_value());
- return true;
-}
-
-bool BinaryTargetGenerator::FillOutputDir() {
- const Value* value = scope_->GetValue(variables::kOutputDir, true);
- if (!value)
- return true;
- if (!value->VerifyTypeIs(Value::STRING, err_))
- return false;
-
- if (value->string_value().empty())
- return true; // Treat empty string as the default and do nothing.
-
- const BuildSettings* build_settings = scope_->settings()->build_settings();
- SourceDir dir = scope_->GetSourceDir().ResolveRelativeDir(
- *value, err_, build_settings->root_path_utf8());
- if (err_->has_error())
- return false;
-
- if (!EnsureStringIsInOutputDir(build_settings->build_dir(),
- dir.value(), value->origin(), err_))
- return false;
- target_->set_output_dir(dir);
- return true;
-}
-
-bool BinaryTargetGenerator::FillOutputExtension() {
- const Value* value = scope_->GetValue(variables::kOutputExtension, true);
- if (!value)
- return true;
- if (!value->VerifyTypeIs(Value::STRING, err_))
- return false;
- target_->set_output_extension(value->string_value());
- return true;
-}
-
-bool BinaryTargetGenerator::FillAllowCircularIncludesFrom() {
- const Value* value = scope_->GetValue(
- variables::kAllowCircularIncludesFrom, true);
- if (!value)
- return true;
-
- UniqueVector<Label> circular;
- ExtractListOfUniqueLabels(*value, scope_->GetSourceDir(),
- ToolchainLabelForScope(scope_), &circular, err_);
- if (err_->has_error())
- return false;
-
- // Validate that all circular includes entries are in the deps.
- for (const auto& cur : circular) {
- bool found_dep = false;
- for (const auto& dep_pair : target_->GetDeps(Target::DEPS_LINKED)) {
- if (dep_pair.label == cur) {
- found_dep = true;
- break;
- }
- }
- if (!found_dep) {
- *err_ = Err(*value, "Label not in deps.",
- "The label \"" + cur.GetUserVisibleName(false) +
- "\"\nwas not in the deps of this target. "
- "allow_circular_includes_from only allows\ntargets present in the "
- "deps.");
- return false;
- }
- }
-
- // Add to the set.
- for (const auto& cur : circular)
- target_->allow_circular_includes_from().insert(cur);
- return true;
-}
diff --git a/chromium/tools/gn/binary_target_generator.h b/chromium/tools/gn/binary_target_generator.h
deleted file mode 100644
index 40fc3141e26..00000000000
--- a/chromium/tools/gn/binary_target_generator.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_BINARY_TARGET_GENERATOR_H_
-#define TOOLS_GN_BINARY_TARGET_GENERATOR_H_
-
-#include "base/macros.h"
-#include "tools/gn/target.h"
-#include "tools/gn/target_generator.h"
-
-// Populates a Target with the values from a binary rule (executable, shared
-// library, or static library).
-class BinaryTargetGenerator : public TargetGenerator {
- public:
- BinaryTargetGenerator(Target* target,
- Scope* scope,
- const FunctionCallNode* function_call,
- Target::OutputType type,
- Err* err);
- ~BinaryTargetGenerator() override;
-
- protected:
- void DoRun() override;
-
- private:
- bool FillCompleteStaticLib();
- bool FillFriends();
- bool FillOutputName();
- bool FillOutputPrefixOverride();
- bool FillOutputDir();
- bool FillOutputExtension();
- bool FillAllowCircularIncludesFrom();
-
- Target::OutputType output_type_;
-
- DISALLOW_COPY_AND_ASSIGN(BinaryTargetGenerator);
-};
-
-#endif // TOOLS_GN_BINARY_TARGET_GENERATOR_H_
diff --git a/chromium/tools/gn/bootstrap/OWNERS b/chromium/tools/gn/bootstrap/OWNERS
index 21aeec2efa8..70300c835d9 100644
--- a/chromium/tools/gn/bootstrap/OWNERS
+++ b/chromium/tools/gn/bootstrap/OWNERS
@@ -1,4 +1,2 @@
-# It's OK to TBR changes to bootstrap.py that edits the file lists to bring
-# them in line with the Chrome build. For more substantial changes, please
-# send a normal review.
-*
+thakis@chormium.org
+thomasanderson@chromium.org
diff --git a/chromium/tools/gn/bootstrap/bootstrap.py b/chromium/tools/gn/bootstrap/bootstrap.py
index 300abacdbca..29f10494b63 100755
--- a/chromium/tools/gn/bootstrap/bootstrap.py
+++ b/chromium/tools/gn/bootstrap/bootstrap.py
@@ -8,1017 +8,88 @@
# to time. If you encounter errors, it's most often due to files in base that
# have been added or moved since somebody last tried this script. Generally
# such errors are easy to diagnose.
+"""Builds gn and generates Chromium's build files.
-"""Bootstraps gn.
-
-It is done by first building it manually in a temporary directory, then building
-it with its own BUILD.gn to the final destination.
+This script should only be run from a Chromium tarball. It will not work in a
+regular git checkout. In a regular git checkout, a gn binary is pulled via
+DEPS. To build gn from source in a regular checkout, see
+https://gn.googlesource.com/gn/
"""
-import contextlib
-import errno
-import logging
+# This script may be removed if/when gn becomes available in the standard
+# repositories for several mainstream Linux distributions.
+
import optparse
import os
-import platform
import shutil
import subprocess
import sys
-import tempfile
BOOTSTRAP_DIR = os.path.dirname(os.path.abspath(__file__))
GN_ROOT = os.path.dirname(BOOTSTRAP_DIR)
SRC_ROOT = os.path.dirname(os.path.dirname(GN_ROOT))
-is_win = sys.platform.startswith('win')
-is_linux = sys.platform.startswith('linux')
-is_mac = sys.platform.startswith('darwin')
-is_aix = sys.platform.startswith('aix')
-is_posix = is_linux or is_mac or is_aix
-
-def check_call(cmd, **kwargs):
- logging.debug('Running: %s', ' '.join(cmd))
-
- subprocess.check_call(cmd, cwd=GN_ROOT, **kwargs)
-
-def check_output(cmd, cwd=GN_ROOT, **kwargs):
- logging.debug('Running: %s', ' '.join(cmd))
-
- return subprocess.check_output(cmd, cwd=cwd, **kwargs)
-
-def mkdir_p(path):
- try:
- os.makedirs(path)
- except OSError as e:
- if e.errno == errno.EEXIST and os.path.isdir(path):
- pass
- else: raise
-
-@contextlib.contextmanager
-def scoped_tempdir():
- path = tempfile.mkdtemp()
- try:
- yield path
- finally:
- shutil.rmtree(path)
-
-
-def run_build(tempdir, options):
- if options.build_path:
- build_rel = options.build_path
- elif options.debug:
- build_rel = os.path.join('out', 'Debug')
- else:
- build_rel = os.path.join('out', 'Release')
- build_root = os.path.join(SRC_ROOT, build_rel)
-
- windows_x64_toolchain = None
- if is_win:
- windows_x64_toolchain = windows_prepare_toolchain(tempdir)
- os.environ["PATH"] = windows_x64_toolchain["paths"]
-
- print 'Building gn manually in a temporary directory for bootstrapping...'
- build_gn_with_ninja_manually(tempdir, options, windows_x64_toolchain)
- temp_gn = os.path.join(tempdir, 'gn')
- out_gn = os.path.join(build_root, 'gn')
-
- if is_win:
- temp_gn += '.exe'
- out_gn += '.exe'
-
- if options.no_rebuild:
- mkdir_p(build_root)
- shutil.copy2(temp_gn, out_gn)
- else:
- print 'Building gn using itself to %s...' % build_rel
- build_gn_with_gn(temp_gn, build_root, options)
-
- if options.output:
- # Preserve the executable permission bit.
- shutil.copy2(out_gn, options.output)
-
-def windows_target_build_arch():
- # Target build architecture set by vcvarsall.bat
- target_arch = os.environ.get('Platform')
- if target_arch in ['x64', 'x86']: return target_arch
-
- if platform.machine().lower() in ['x86_64', 'amd64']: return 'x64'
- return 'x86'
-
-def windows_prepare_toolchain(tempdir):
-
- def CallPythonScopeScript(command, **kwargs):
- response = check_output(command, **kwargs)
-
- _globals = {"__builtins__":None}
- _locals = {}
- exec(response, _globals, _locals)
-
- return _locals
-
- toolchain_paths = CallPythonScopeScript(
- [sys.executable,
- os.path.join(SRC_ROOT, "build", "vs_toolchain.py"),
- "get_toolchain_dir"],
- cwd=tempdir)
-
- windows_x64_toolchain = CallPythonScopeScript(
- [sys.executable,
- os.path.join(SRC_ROOT, "build", "toolchain",
- "win", "setup_toolchain.py"),
- toolchain_paths["vs_path"],
- toolchain_paths["sdk_path"],
- toolchain_paths["runtime_dirs"],
- "win",
- "x64",
- "environment.x64",
- "true"
- ],
- cwd=tempdir)
-
- return windows_x64_toolchain
def main(argv):
parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
- parser.add_option('-d', '--debug', action='store_true',
- help='Do a debug build. Defaults to release build.')
- parser.add_option('-o', '--output',
- help='place output in PATH', metavar='PATH')
- parser.add_option('-s', '--no-rebuild', action='store_true',
- help='Do not rebuild GN with GN.')
- parser.add_option('--no-clean', action='store_true',
- help='Re-used build directory instead of using new '
- 'temporary location each time')
+ parser.add_option(
+ '-d',
+ '--debug',
+ action='store_true',
+ help='Do a debug build. Defaults to release build.')
+ parser.add_option(
+ '-o', '--output', help='place output in PATH', metavar='PATH')
+ parser.add_option('-s', '--no-rebuild', help='ignored')
+ parser.add_option('--no-clean', help='ignored')
parser.add_option('--gn-gen-args', help='Args to pass to gn gen --args')
- parser.add_option('--build-path', help='The directory in which to build gn, '
- 'relative to the src directory. (eg. out/Release)'
- 'In the no-clean mode an absolute path will also force '
- 'the out_bootstrap to be located in the parent directory')
- parser.add_option('-v', '--verbose', action='store_true',
- help='Log more details')
+ parser.add_option(
+ '--build-path',
+ help='The directory in which to build gn, '
+ 'relative to the src directory. (eg. out/Release)')
+ parser.add_option(
+ '--with-sysroot',
+ action='store_true',
+ help='Download and build with the Debian sysroot.')
+ parser.add_option('-v', '--verbose', help='ignored')
options, args = parser.parse_args(argv)
-
if args:
parser.error('Unrecognized command line arguments: %s.' % ', '.join(args))
- logging.basicConfig(level=logging.DEBUG if options.verbose else logging.ERROR)
-
- try:
- if options.no_clean:
- out_bootstrap_dir = SRC_ROOT
- if options.build_path and os.path.isabs(options.build_path):
- out_bootstrap_dir = os.path.dirname(options.build_path)
- build_dir = os.path.join(out_bootstrap_dir, 'out_bootstrap')
- if not os.path.exists(build_dir):
- os.makedirs(build_dir)
- return run_build(build_dir, options)
- else:
- with scoped_tempdir() as tempdir:
- return run_build(tempdir, options)
- except subprocess.CalledProcessError as e:
- print >> sys.stderr, str(e)
- return 1
- return 0
-
-def write_compiled_message(root_gen_dir, source):
- path = os.path.join(root_gen_dir, os.path.dirname(source))
- mkdir_p(path)
- check_call([
- 'mc.exe',
- '-r', path, '-h', path,
- '-u', '-um',
- os.path.join(SRC_ROOT, source),
- ])
-
-def write_buildflag_header_manually(root_gen_dir, header, flags):
- mkdir_p(os.path.join(root_gen_dir, os.path.dirname(header)))
-
- # Don't use tempfile.NamedTemporaryFile() here.
- # It doesn't work correctly on Windows.
- # see: http://bugs.python.org/issue14243
- temp_path = os.path.join(root_gen_dir, header + '.tmp')
- with open(temp_path, 'w') as f:
- f.write('--flags')
- for name,value in flags.items():
- f.write(' ' + name + '=' + value)
-
- check_call([
- sys.executable,
- os.path.join(SRC_ROOT, 'build', 'write_buildflag_header.py'),
- '--output', header,
- '--gen-dir', root_gen_dir,
- '--definitions', temp_path,
- ])
-
- os.remove(temp_path)
-
-def write_build_date_header(root_gen_dir):
- check_call([
- sys.executable,
- os.path.join(SRC_ROOT, 'build', 'write_build_date_header.py'),
- os.path.join(root_gen_dir, 'base/generated_build_date.h'),
- 'default',
- ])
-
-def build_gn_with_ninja_manually(tempdir, options, windows_x64_toolchain):
- root_gen_dir = os.path.join(tempdir, 'gen')
- mkdir_p(root_gen_dir)
-
- write_buildflag_header_manually(
- root_gen_dir,
- 'base/synchronization/synchronization_buildflags.h',
- {'ENABLE_MUTEX_PRIORITY_INHERITANCE': 'false'})
-
- write_buildflag_header_manually(root_gen_dir, 'base/allocator/buildflags.h',
- {'USE_ALLOCATOR_SHIM': 'true' if is_linux else 'false'})
-
- write_buildflag_header_manually(root_gen_dir,
- 'base/debug/debugging_buildflags.h',
- {
- 'ENABLE_LOCATION_SOURCE': 'false',
- 'ENABLE_PROFILING': 'false',
- 'CAN_UNWIND_WITH_FRAME_POINTERS': 'false',
- 'UNSAFE_DEVELOPER_BUILD': 'false',
- 'CAN_UNWIND_WITH_CFI_TABLE': 'false',
- })
-
- write_buildflag_header_manually(root_gen_dir,
- 'base/memory/protected_memory_buildflags.h',
- { 'USE_LLD': 'false' })
-
- write_buildflag_header_manually(root_gen_dir, 'base/cfi_buildflags.h',
- {
- 'CFI_CAST_CHECK': 'false',
- 'CFI_ICALL_CHECK': 'false',
- 'CFI_ENFORCEMENT_TRAP': 'false',
- 'CFI_ENFORCEMENT_DIAGNOSTIC': 'false'
- })
-
- write_build_date_header(root_gen_dir)
-
- if is_mac:
- # //base/build_time.cc needs base/generated_build_date.h,
- # and this file is only included for Mac builds.
- mkdir_p(os.path.join(root_gen_dir, 'base'))
- check_call([
- sys.executable,
- os.path.join(SRC_ROOT, 'build', 'write_build_date_header.py'),
- os.path.join(root_gen_dir, 'base', 'generated_build_date.h'),
- 'default'
- ])
-
- if is_win:
- write_buildflag_header_manually(root_gen_dir,
- 'base/win/base_win_buildflags.h',
- {'SINGLE_MODULE_MODE_HANDLE_VERIFIER': 'true'})
-
- write_compiled_message(root_gen_dir,
- 'base/trace_event/etw_manifest/chrome_events_win.man')
-
- write_buildflag_header_manually(
- root_gen_dir, 'base/android/library_loader.h',
- {'USE_LLD': 'false', 'SUPPORTS_CODE_ORDERING': 'false'})
-
- write_gn_ninja(os.path.join(tempdir, 'build.ninja'),
- root_gen_dir, options, windows_x64_toolchain)
- cmd = ['ninja', '-C', tempdir, '-w', 'dupbuild=err']
- if options.verbose:
- cmd.append('-v')
-
- if is_win:
- cmd.append('gn.exe')
+ if options.build_path:
+ build_rel = options.build_path
+ elif options.debug:
+ build_rel = os.path.join('out', 'Debug')
else:
- cmd.append('gn')
-
- check_call(cmd)
+ build_rel = os.path.join('out', 'Release')
+ out_dir = os.path.join(SRC_ROOT, build_rel)
+ gn_path = options.output or os.path.join(out_dir, 'gn')
+ gn_build_dir = os.path.join(out_dir, 'gn_build')
-def write_generic_ninja(path, static_libraries, executables,
- cc, cxx, ar, ld,
- cflags=[], cflags_cc=[], ldflags=[],
- include_dirs=[], solibs=[]):
- ninja_header_lines = [
- 'cc = ' + cc,
- 'cxx = ' + cxx,
- 'ar = ' + ar,
- 'ld = ' + ld,
- '',
+ cmd = [
+ sys.executable,
+ os.path.join(GN_ROOT, 'build', 'gen.py'),
+ '--no-last-commit-position',
+ '--out-path=' + gn_build_dir,
]
+ if not options.with_sysroot:
+ cmd.append('--no-sysroot')
+ if options.debug:
+ cmd.append('--debug')
+ subprocess.check_call(cmd)
+
+ shutil.copy2(
+ os.path.join(BOOTSTRAP_DIR, 'last_commit_position.h'), gn_build_dir)
+ subprocess.check_call(
+ ['ninja', '-C', gn_build_dir, 'gn', '-w', 'dupbuild=err'])
+ shutil.copy2(os.path.join(gn_build_dir, 'gn'), gn_path)
- if is_win:
- template_filename = 'build_vs.ninja.template'
- elif is_mac:
- template_filename = 'build_mac.ninja.template'
- elif is_aix:
- template_filename = 'build_aix.ninja.template'
- else:
- template_filename = 'build.ninja.template'
-
- with open(os.path.join(GN_ROOT, 'bootstrap', template_filename)) as f:
- ninja_template = f.read()
-
- if is_win:
- executable_ext = '.exe'
- library_ext = '.lib'
- object_ext = '.obj'
- else:
- executable_ext = ''
- library_ext = '.a'
- object_ext = '.o'
-
- def escape_path_ninja(path):
- return path.replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:')
-
- def src_to_obj(path):
- return escape_path_ninja('%s' % os.path.splitext(path)[0] + object_ext)
-
- def library_to_a(library):
- return '%s%s' % (library, library_ext)
-
- ninja_lines = []
- def build_source(src_file, settings):
- ninja_lines.extend([
- 'build %s: %s %s' % (src_to_obj(src_file),
- settings['tool'],
- escape_path_ninja(
- os.path.join(SRC_ROOT, src_file))),
- ' includes = %s' % ' '.join(
- ['-I' + escape_path_ninja(dirname) for dirname in
- include_dirs + settings.get('include_dirs', [])]),
- ' cflags = %s' % ' '.join(cflags + settings.get('cflags', [])),
- ' cflags_cc = %s' %
- ' '.join(cflags_cc + settings.get('cflags_cc', [])),
- ])
-
- for library, settings in static_libraries.iteritems():
- for src_file in settings['sources']:
- build_source(src_file, settings)
-
- ninja_lines.append('build %s: alink_thin %s' % (
- library_to_a(library),
- ' '.join([src_to_obj(src_file) for src_file in settings['sources']])))
-
- for executable, settings in executables.iteritems():
- for src_file in settings['sources']:
- build_source(src_file, settings)
-
- ninja_lines.extend([
- 'build %s%s: link %s | %s' % (
- executable, executable_ext,
- ' '.join([src_to_obj(src_file) for src_file in settings['sources']]),
- ' '.join([library_to_a(library) for library in settings['libs']])),
- ' ldflags = %s' % ' '.join(ldflags),
- ' solibs = %s' % ' '.join(solibs),
- ' libs = %s' % ' '.join(
- [library_to_a(library) for library in settings['libs']]),
- ])
-
- ninja_lines.append('') # Make sure the file ends with a newline.
-
- with open(path, 'w') as f:
- f.write('\n'.join(ninja_header_lines))
- f.write(ninja_template)
- f.write('\n'.join(ninja_lines))
-
-def write_gn_ninja(path, root_gen_dir, options, windows_x64_toolchain):
- if is_win:
- CCPATH = windows_x64_toolchain["vc_bin_dir"]
-
- cc = os.environ.get('CC', os.path.join(CCPATH, 'cl.exe'))
- cxx = os.environ.get('CXX', os.path.join(CCPATH, 'cl.exe'))
- ld = os.environ.get('LD', os.path.join(CCPATH, 'link.exe'))
- ar = os.environ.get('AR', os.path.join(CCPATH, 'lib.exe'))
- elif is_aix:
- cc = os.environ.get('CC', 'gcc')
- cxx = os.environ.get('CXX', 'c++')
- ld = os.environ.get('LD', cxx)
- ar = os.environ.get('AR', 'ar -X64')
- else:
- cc = os.environ.get('CC', 'cc')
- cxx = os.environ.get('CXX', 'c++')
- ld = cxx
- ar = os.environ.get('AR', 'ar')
-
- cflags = os.environ.get('CFLAGS', '').split()
- cflags_cc = os.environ.get('CXXFLAGS', '').split()
- ldflags = os.environ.get('LDFLAGS', '').split()
- include_dirs = [root_gen_dir, SRC_ROOT]
- libs = []
-
- # //base/allocator/allocator_extension.cc needs this macro defined,
- # otherwise there would be link errors.
- cflags.extend(['-DNO_TCMALLOC', '-D__STDC_FORMAT_MACROS'])
-
- if is_posix:
- if options.debug:
- cflags.extend(['-O0', '-g'])
- else:
- # The linux::ppc64 BE binary doesn't "work" when
- # optimization level is set to 2 (0 works fine).
- # Note that the current bootstrap script has no way to detect host_cpu.
- # This can be easily fixed once we start building using a GN binary,
- # as the optimization flag can then just be set using the
- # logic inside //build/toolchain.
- cflags.extend(['-O2', '-g0'])
-
- cflags.extend([
- '-D_FILE_OFFSET_BITS=64',
- '-D__STDC_CONSTANT_MACROS', '-D__STDC_FORMAT_MACROS',
- '-pthread',
- '-pipe',
- '-fno-exceptions'
- ])
- cflags_cc.extend(['-std=c++14', '-Wno-c++11-narrowing'])
- if is_aix:
- cflags.extend(['-maix64'])
- ldflags.extend([ '-maix64 -Wl,-bbigtoc' ])
- elif is_win:
- if not options.debug:
- cflags.extend(['/Ox', '/DNDEBUG', '/GL'])
- ldflags.extend(['/LTCG', '/OPT:REF', '/OPT:ICF'])
-
- cflags.extend([
- '/FS',
- '/Gy',
- '/W3', '/wd4244',
- '/Zi',
- '/DWIN32_LEAN_AND_MEAN', '/DNOMINMAX',
- '/D_CRT_SECURE_NO_DEPRECATE', '/D_SCL_SECURE_NO_DEPRECATE',
- '/D_WIN32_WINNT=0x0A00', '/DWINVER=0x0A00',
- '/DUNICODE', '/D_UNICODE',
- ])
- cflags_cc.extend([
- '/GR-',
- '/D_HAS_EXCEPTIONS=0',
- ])
-
- target_arch = windows_target_build_arch()
- if target_arch == 'x64':
- ldflags.extend(['/MACHINE:x64'])
- else:
- ldflags.extend(['/MACHINE:x86'])
-
- static_libraries = {
- 'base': {'sources': [], 'tool': 'cxx', 'include_dirs': []},
- 'dynamic_annotations': {'sources': [], 'tool': 'cc', 'include_dirs': []},
- 'gn_lib': {'sources': [], 'tool': 'cxx', 'include_dirs': []},
- }
-
- executables = {
- 'gn': {'sources': ['tools/gn/gn_main.cc'],
- 'tool': 'cxx', 'include_dirs': [], 'libs': []},
- }
-
- for name in os.listdir(GN_ROOT):
- if not name.endswith('.cc'):
- continue
- if name.endswith('_unittest.cc'):
- continue
- if name == 'run_all_unittests.cc':
- continue
- if name == 'test_with_scheduler.cc':
- continue
- if name == 'gn_main.cc':
- continue
- full_path = os.path.join(GN_ROOT, name)
- static_libraries['gn_lib']['sources'].append(
- os.path.relpath(full_path, SRC_ROOT))
-
- static_libraries['dynamic_annotations']['sources'].extend([
- 'base/third_party/dynamic_annotations/dynamic_annotations.c',
- 'base/third_party/superfasthash/superfasthash.c',
- ])
- static_libraries['base']['sources'].extend([
- 'base/allocator/allocator_check.cc',
- 'base/allocator/allocator_extension.cc',
- 'base/at_exit.cc',
- 'base/base_paths.cc',
- 'base/base_switches.cc',
- 'base/build_time.cc',
- 'base/callback_helpers.cc',
- 'base/callback_internal.cc',
- 'base/command_line.cc',
- 'base/debug/activity_tracker.cc',
- 'base/debug/alias.cc',
- 'base/debug/crash_logging.cc',
- 'base/debug/dump_without_crashing.cc',
- 'base/debug/stack_trace.cc',
- 'base/debug/task_annotator.cc',
- 'base/debug/thread_heap_usage_tracker.cc',
- 'base/environment.cc',
- 'base/feature_list.cc',
- 'base/files/file.cc',
- 'base/files/file_enumerator.cc',
- 'base/files/file_path.cc',
- 'base/files/file_path_constants.cc',
- 'base/files/file_tracing.cc',
- 'base/files/file_util.cc',
- 'base/files/important_file_writer.cc',
- 'base/files/memory_mapped_file.cc',
- 'base/files/scoped_file.cc',
- 'base/hash.cc',
- 'base/json/json_parser.cc',
- 'base/json/json_reader.cc',
- 'base/json/json_string_value_serializer.cc',
- 'base/json/json_writer.cc',
- 'base/json/string_escape.cc',
- 'base/lazy_instance_helpers.cc',
- 'base/location.cc',
- 'base/logging.cc',
- 'base/md5.cc',
- 'base/memory/platform_shared_memory_region.cc',
- 'base/memory/read_only_shared_memory_region.cc',
- 'base/memory/ref_counted.cc',
- 'base/memory/ref_counted_memory.cc',
- 'base/memory/shared_memory_mapping.cc',
- 'base/memory/shared_memory_handle.cc',
- 'base/memory/shared_memory_tracker.cc',
- 'base/memory/weak_ptr.cc',
- 'base/message_loop/incoming_task_queue.cc',
- 'base/message_loop/message_loop.cc',
- 'base/message_loop/message_loop_current.cc',
- 'base/message_loop/message_loop_task_runner.cc',
- 'base/message_loop/message_pump.cc',
- 'base/message_loop/message_pump_default.cc',
- 'base/message_loop/watchable_io_message_pump_posix.cc',
- 'base/metrics/bucket_ranges.cc',
- 'base/metrics/dummy_histogram.cc',
- 'base/metrics/field_trial.cc',
- 'base/metrics/field_trial_param_associator.cc',
- 'base/metrics/field_trial_params.cc',
- 'base/metrics/histogram.cc',
- 'base/metrics/histogram_base.cc',
- 'base/metrics/histogram_functions.cc',
- 'base/metrics/histogram_samples.cc',
- 'base/metrics/histogram_snapshot_manager.cc',
- 'base/metrics/metrics_hashes.cc',
- 'base/metrics/persistent_histogram_allocator.cc',
- 'base/metrics/persistent_memory_allocator.cc',
- 'base/metrics/persistent_sample_map.cc',
- 'base/metrics/sample_map.cc',
- 'base/metrics/sample_vector.cc',
- 'base/metrics/sparse_histogram.cc',
- 'base/metrics/statistics_recorder.cc',
- 'base/observer_list_threadsafe.cc',
- 'base/path_service.cc',
- 'base/pending_task.cc',
- 'base/pickle.cc',
- 'base/process/kill.cc',
- 'base/process/memory.cc',
- 'base/process/process_handle.cc',
- 'base/process/process_iterator.cc',
- 'base/process/process_metrics.cc',
- 'base/rand_util.cc',
- 'base/run_loop.cc',
- 'base/sequence_token.cc',
- 'base/sequence_checker_impl.cc',
- 'base/sequenced_task_runner.cc',
- 'base/sha1.cc',
- 'base/strings/pattern.cc',
- 'base/strings/string_number_conversions.cc',
- 'base/strings/string_piece.cc',
- 'base/strings/string_split.cc',
- 'base/strings/string_util.cc',
- 'base/strings/string_util_constants.cc',
- 'base/strings/stringprintf.cc',
- 'base/strings/utf_string_conversion_utils.cc',
- 'base/strings/utf_string_conversions.cc',
- 'base/synchronization/atomic_flag.cc',
- 'base/synchronization/lock.cc',
- 'base/sys_info.cc',
- 'base/task_runner.cc',
- 'base/task_scheduler/delayed_task_manager.cc',
- 'base/task_scheduler/environment_config.cc',
- 'base/task_scheduler/post_task.cc',
- 'base/task_scheduler/priority_queue.cc',
- 'base/task_scheduler/scheduler_lock_impl.cc',
- 'base/task_scheduler/scheduler_single_thread_task_runner_manager.cc',
- 'base/task_scheduler/scheduler_worker.cc',
- 'base/task_scheduler/scheduler_worker_pool.cc',
- 'base/task_scheduler/scheduler_worker_pool_impl.cc',
- 'base/task_scheduler/scheduler_worker_pool_params.cc',
- 'base/task_scheduler/scheduler_worker_stack.cc',
- 'base/task_scheduler/scoped_set_task_priority_for_current_thread.cc',
- 'base/task_scheduler/sequence.cc',
- 'base/task_scheduler/sequence_sort_key.cc',
- 'base/task_scheduler/service_thread.cc',
- 'base/task_scheduler/task.cc',
- 'base/task_scheduler/task_scheduler.cc',
- 'base/task_scheduler/task_scheduler_impl.cc',
- 'base/task_scheduler/task_tracker.cc',
- 'base/task_scheduler/task_traits.cc',
- 'base/third_party/dmg_fp/dtoa_wrapper.cc',
- 'base/third_party/dmg_fp/g_fmt.cc',
- 'base/third_party/icu/icu_utf.cc',
- 'base/third_party/nspr/prtime.cc',
- 'base/threading/post_task_and_reply_impl.cc',
- 'base/threading/scoped_blocking_call.cc',
- 'base/threading/sequence_local_storage_map.cc',
- 'base/threading/sequenced_task_runner_handle.cc',
- 'base/threading/simple_thread.cc',
- 'base/threading/thread.cc',
- 'base/threading/thread_checker_impl.cc',
- 'base/threading/thread_collision_warner.cc',
- 'base/threading/thread_id_name_manager.cc',
- 'base/threading/thread_local_storage.cc',
- 'base/threading/thread_restrictions.cc',
- 'base/threading/thread_task_runner_handle.cc',
- 'base/time/clock.cc',
- 'base/time/default_clock.cc',
- 'base/time/default_tick_clock.cc',
- 'base/time/tick_clock.cc',
- 'base/time/time.cc',
- 'base/timer/elapsed_timer.cc',
- 'base/timer/timer.cc',
- 'base/trace_event/category_registry.cc',
- 'base/trace_event/event_name_filter.cc',
- 'base/trace_event/heap_profiler_allocation_context.cc',
- 'base/trace_event/heap_profiler_allocation_context_tracker.cc',
- 'base/trace_event/heap_profiler_event_filter.cc',
- 'base/trace_event/heap_profiler_heap_dump_writer.cc',
- 'base/trace_event/heap_profiler_serialization_state.cc',
- 'base/trace_event/heap_profiler_stack_frame_deduplicator.cc',
- 'base/trace_event/heap_profiler_type_name_deduplicator.cc',
- 'base/trace_event/malloc_dump_provider.cc',
- 'base/trace_event/memory_allocator_dump.cc',
- 'base/trace_event/memory_allocator_dump_guid.cc',
- 'base/trace_event/memory_dump_manager.cc',
- 'base/trace_event/memory_dump_provider_info.cc',
- 'base/trace_event/memory_dump_request_args.cc',
- 'base/trace_event/memory_dump_scheduler.cc',
- 'base/trace_event/memory_infra_background_whitelist.cc',
- 'base/trace_event/memory_peak_detector.cc',
- 'base/trace_event/memory_usage_estimator.cc',
- 'base/trace_event/process_memory_dump.cc',
- 'base/trace_event/trace_buffer.cc',
- 'base/trace_event/trace_config.cc',
- 'base/trace_event/trace_config_category_filter.cc',
- 'base/trace_event/trace_event_argument.cc',
- 'base/trace_event/trace_event_filter.cc',
- 'base/trace_event/trace_event_impl.cc',
- 'base/trace_event/trace_event_memory_overhead.cc',
- 'base/trace_event/trace_log.cc',
- 'base/trace_event/trace_log_constants.cc',
- 'base/trace_event/tracing_agent.cc',
- 'base/unguessable_token.cc',
- 'base/value_iterators.cc',
- 'base/values.cc',
- 'base/vlog.cc',
- ])
-
- if is_win:
- static_libraries['base']['sources'].extend([
- 'base/memory/platform_shared_memory_region_win.cc'
- ])
- elif is_mac:
- static_libraries['base']['sources'].extend([
- 'base/memory/platform_shared_memory_region_mac.cc'
- ])
- elif is_posix:
- static_libraries['base']['sources'].extend([
- 'base/memory/platform_shared_memory_region_posix.cc'
- ])
-
- if is_posix:
- static_libraries['base']['sources'].extend([
- 'base/base_paths_posix.cc',
- 'base/debug/debugger_posix.cc',
- 'base/debug/stack_trace_posix.cc',
- 'base/files/file_enumerator_posix.cc',
- 'base/files/file_descriptor_watcher_posix.cc',
- 'base/files/file_posix.cc',
- 'base/files/file_util_posix.cc',
- 'base/files/memory_mapped_file_posix.cc',
- 'base/memory/shared_memory_helper.cc',
- 'base/message_loop/message_pump_libevent.cc',
- 'base/posix/file_descriptor_shuffle.cc',
- 'base/posix/global_descriptors.cc',
- 'base/posix/safe_strerror.cc',
- 'base/process/kill_posix.cc',
- 'base/process/process_handle_posix.cc',
- 'base/process/process_metrics_posix.cc',
- 'base/process/process_posix.cc',
- 'base/rand_util_posix.cc',
- 'base/strings/string16.cc',
- 'base/synchronization/condition_variable_posix.cc',
- 'base/synchronization/lock_impl_posix.cc',
- 'base/sys_info_posix.cc',
- 'base/task_scheduler/task_tracker_posix.cc',
- 'base/threading/platform_thread_internal_posix.cc',
- 'base/threading/platform_thread_posix.cc',
- 'base/threading/thread_local_storage_posix.cc',
- 'base/time/time_conversion_posix.cc',
- ])
- static_libraries['libevent'] = {
- 'sources': [
- 'base/third_party/libevent/buffer.c',
- 'base/third_party/libevent/evbuffer.c',
- 'base/third_party/libevent/evdns.c',
- 'base/third_party/libevent/event.c',
- 'base/third_party/libevent/event_tagging.c',
- 'base/third_party/libevent/evrpc.c',
- 'base/third_party/libevent/evutil.c',
- 'base/third_party/libevent/http.c',
- 'base/third_party/libevent/log.c',
- 'base/third_party/libevent/poll.c',
- 'base/third_party/libevent/select.c',
- 'base/third_party/libevent/signal.c',
- 'base/third_party/libevent/strlcpy.c',
- ],
- 'tool': 'cc',
- 'include_dirs': [],
- 'cflags': cflags + ['-DHAVE_CONFIG_H'],
- }
-
- if is_linux or is_aix:
- static_libraries['xdg_user_dirs'] = {
- 'sources': [
- 'base/third_party/xdg_user_dirs/xdg_user_dir_lookup.cc',
- ],
- 'tool': 'cxx',
- }
- static_libraries['base']['sources'].extend([
- 'base/memory/shared_memory_handle_posix.cc',
- 'base/memory/shared_memory_posix.cc',
- 'base/nix/xdg_util.cc',
- 'base/process/internal_linux.cc',
- 'base/process/memory_linux.cc',
- 'base/process/process_handle_linux.cc',
- 'base/process/process_info_linux.cc',
- 'base/process/process_iterator_linux.cc',
- 'base/process/process_linux.cc',
- 'base/process/process_metrics_linux.cc',
- 'base/strings/sys_string_conversions_posix.cc',
- 'base/synchronization/waitable_event_posix.cc',
- 'base/sys_info_linux.cc',
- 'base/time/time_exploded_posix.cc',
- 'base/time/time_now_posix.cc',
- 'base/threading/platform_thread_linux.cc',
- ])
- if is_linux:
- libcxx_root = SRC_ROOT + '/buildtools/third_party/libc++/trunk'
- libcxxabi_root = SRC_ROOT + '/buildtools/third_party/libc++abi/trunk'
- cflags_cc.extend([
- '-nostdinc++',
- '-isystem' + libcxx_root + '/include',
- '-isystem' + libcxxabi_root + '/include',
- ])
- ldflags.extend(['-nodefaultlibs'])
- libs.extend([
- '-lc',
- '-lgcc_s',
- '-lm',
- '-lpthread',
- ])
- static_libraries['libc++'] = {
- 'sources': [
- libcxx_root + '/src/algorithm.cpp',
- libcxx_root + '/src/any.cpp',
- libcxx_root + '/src/bind.cpp',
- libcxx_root + '/src/chrono.cpp',
- libcxx_root + '/src/condition_variable.cpp',
- libcxx_root + '/src/debug.cpp',
- libcxx_root + '/src/exception.cpp',
- libcxx_root + '/src/functional.cpp',
- libcxx_root + '/src/future.cpp',
- libcxx_root + '/src/hash.cpp',
- libcxx_root + '/src/ios.cpp',
- libcxx_root + '/src/iostream.cpp',
- libcxx_root + '/src/locale.cpp',
- libcxx_root + '/src/memory.cpp',
- libcxx_root + '/src/mutex.cpp',
- libcxx_root + '/src/new.cpp',
- libcxx_root + '/src/optional.cpp',
- libcxx_root + '/src/random.cpp',
- libcxx_root + '/src/regex.cpp',
- libcxx_root + '/src/shared_mutex.cpp',
- libcxx_root + '/src/stdexcept.cpp',
- libcxx_root + '/src/string.cpp',
- libcxx_root + '/src/strstream.cpp',
- libcxx_root + '/src/system_error.cpp',
- libcxx_root + '/src/thread.cpp',
- libcxx_root + '/src/typeinfo.cpp',
- libcxx_root + '/src/utility.cpp',
- libcxx_root + '/src/valarray.cpp',
- libcxx_root + '/src/variant.cpp',
- libcxx_root + '/src/vector.cpp',
- ],
- 'tool': 'cxx',
- 'cflags': cflags + [
- '-D_LIBCPP_NO_EXCEPTIONS',
- '-D_LIBCPP_BUILDING_LIBRARY',
- '-DLIBCXX_BUILDING_LIBCXXABI',
- ]
- }
- static_libraries['libc++abi'] = {
- 'sources': [
- libcxxabi_root + '/src/abort_message.cpp',
- libcxxabi_root + '/src/cxa_aux_runtime.cpp',
- libcxxabi_root + '/src/cxa_default_handlers.cpp',
- libcxxabi_root + '/src/cxa_demangle.cpp',
- libcxxabi_root + '/src/cxa_exception_storage.cpp',
- libcxxabi_root + '/src/cxa_guard.cpp',
- libcxxabi_root + '/src/cxa_handlers.cpp',
- libcxxabi_root + '/src/cxa_noexception.cpp',
- libcxxabi_root + '/src/cxa_unexpected.cpp',
- libcxxabi_root + '/src/cxa_vector.cpp',
- libcxxabi_root + '/src/cxa_virtual.cpp',
- libcxxabi_root + '/src/fallback_malloc.cpp',
- libcxxabi_root + '/src/private_typeinfo.cpp',
- libcxxabi_root + '/src/stdlib_exception.cpp',
- libcxxabi_root + '/src/stdlib_stdexcept.cpp',
- libcxxabi_root + '/src/stdlib_typeinfo.cpp',
- ],
- 'tool': 'cxx',
- 'cflags': cflags + [
- '-DLIBCXXABI_SILENT_TERMINATE',
- '-D_LIBCXXABI_NO_EXCEPTIONS',
- ]
- }
- static_libraries['base']['sources'].extend([
- 'base/allocator/allocator_shim.cc',
- 'base/allocator/allocator_shim_default_dispatch_to_glibc.cc',
- ])
- libs.extend(['-lrt', '-latomic'])
- static_libraries['libevent']['include_dirs'].extend([
- os.path.join(SRC_ROOT, 'base', 'third_party', 'libevent', 'linux')
- ])
- static_libraries['libevent']['sources'].extend([
- 'base/third_party/libevent/epoll.c',
- ])
- else:
- ldflags.extend(['-pthread'])
- libs.extend(['-lrt'])
- static_libraries['base']['sources'].extend([
- 'base/process/internal_aix.cc'
- ])
- static_libraries['libevent']['include_dirs'].extend([
- os.path.join(SRC_ROOT, 'base', 'third_party', 'libevent', 'aix')
- ])
- static_libraries['libevent']['include_dirs'].extend([
- os.path.join(SRC_ROOT, 'base', 'third_party', 'libevent', 'compat')
- ])
-
- if is_mac:
- static_libraries['base']['sources'].extend([
- 'base/base_paths_mac.mm',
- 'base/files/file_util_mac.mm',
- 'base/mac/bundle_locations.mm',
- 'base/mac/call_with_eh_frame.cc',
- 'base/mac/call_with_eh_frame_asm.S',
- 'base/mac/foundation_util.mm',
- 'base/mac/mach_logging.cc',
- 'base/mac/scoped_mach_port.cc',
- 'base/mac/scoped_mach_vm.cc',
- 'base/mac/scoped_nsautorelease_pool.mm',
- 'base/memory/shared_memory_handle_mac.cc',
- 'base/memory/shared_memory_mac.cc',
- 'base/message_loop/message_pump_mac.mm',
- 'base/process/process_handle_mac.cc',
- 'base/process/process_info_mac.cc',
- 'base/process/process_iterator_mac.cc',
- 'base/process/process_metrics_mac.cc',
- 'base/strings/sys_string_conversions_mac.mm',
- 'base/synchronization/waitable_event_mac.cc',
- 'base/sys_info_mac.mm',
- 'base/time/time_exploded_posix.cc',
- 'base/time/time_mac.cc',
- 'base/threading/platform_thread_mac.mm',
- ])
- static_libraries['libevent']['include_dirs'].extend([
- os.path.join(SRC_ROOT, 'base', 'third_party', 'libevent', 'mac')
- ])
- static_libraries['libevent']['sources'].extend([
- 'base/third_party/libevent/kqueue.c',
- ])
-
- libs.extend([
- '-framework', 'AppKit',
- '-framework', 'CoreFoundation',
- '-framework', 'Foundation',
- '-framework', 'Security',
- ])
-
- if is_win:
- static_libraries['base']['sources'].extend([
- "base/allocator/partition_allocator/address_space_randomization.cc",
- 'base/allocator/partition_allocator/page_allocator.cc',
- "base/allocator/partition_allocator/spin_lock.cc",
- 'base/base_paths_win.cc',
- 'base/cpu.cc',
- 'base/debug/close_handle_hook_win.cc',
- 'base/debug/debugger.cc',
- 'base/debug/debugger_win.cc',
- 'base/debug/profiler.cc',
- 'base/debug/stack_trace_win.cc',
- 'base/file_version_info_win.cc',
- 'base/files/file_enumerator_win.cc',
- 'base/files/file_path_watcher_win.cc',
- 'base/files/file_util_win.cc',
- 'base/files/file_win.cc',
- 'base/files/memory_mapped_file_win.cc',
- 'base/guid.cc',
- 'base/logging_win.cc',
- 'base/memory/memory_pressure_monitor_win.cc',
- 'base/memory/shared_memory_handle_win.cc',
- 'base/memory/shared_memory_win.cc',
- 'base/message_loop/message_pump_win.cc',
- 'base/native_library_win.cc',
- 'base/power_monitor/power_monitor_device_source_win.cc',
- 'base/process/kill_win.cc',
- 'base/process/launch_win.cc',
- 'base/process/memory_win.cc',
- 'base/process/process_handle_win.cc',
- 'base/process/process_info_win.cc',
- 'base/process/process_iterator_win.cc',
- 'base/process/process_metrics_win.cc',
- 'base/process/process_win.cc',
- 'base/profiler/native_stack_sampler_win.cc',
- 'base/profiler/win32_stack_frame_unwinder.cc',
- 'base/rand_util_win.cc',
- 'base/strings/sys_string_conversions_win.cc',
- 'base/sync_socket_win.cc',
- 'base/synchronization/condition_variable_win.cc',
- 'base/synchronization/lock_impl_win.cc',
- 'base/synchronization/waitable_event_watcher_win.cc',
- 'base/synchronization/waitable_event_win.cc',
- 'base/sys_info_win.cc',
- 'base/threading/platform_thread_win.cc',
- 'base/threading/thread_local_storage_win.cc',
- 'base/time/time_win.cc',
- 'base/timer/hi_res_timer_manager_win.cc',
- 'base/trace_event/trace_event_etw_export_win.cc',
- 'base/win/core_winrt_util.cc',
- 'base/win/enum_variant.cc',
- 'base/win/event_trace_controller.cc',
- 'base/win/event_trace_provider.cc',
- 'base/win/i18n.cc',
- 'base/win/iat_patch_function.cc',
- 'base/win/iunknown_impl.cc',
- 'base/win/message_window.cc',
- 'base/win/object_watcher.cc',
- 'base/win/pe_image.cc',
- 'base/win/process_startup_helper.cc',
- 'base/win/registry.cc',
- 'base/win/resource_util.cc',
- 'base/win/scoped_bstr.cc',
- 'base/win/scoped_com_initializer.cc',
- 'base/win/scoped_handle.cc',
- 'base/win/scoped_handle_verifier.cc',
- 'base/win/scoped_process_information.cc',
- 'base/win/scoped_variant.cc',
- 'base/win/scoped_winrt_initializer.cc',
- 'base/win/shortcut.cc',
- 'base/win/startup_information.cc',
- 'base/win/wait_chain.cc',
- 'base/win/win_util.cc',
- 'base/win/windows_version.cc',
- 'base/win/wrapped_window_proc.cc',
- ])
-
- libs.extend([
- 'advapi32.lib',
- 'dbghelp.lib',
- 'kernel32.lib',
- 'ole32.lib',
- 'shell32.lib',
- 'user32.lib',
- 'userenv.lib',
- 'version.lib',
- 'winmm.lib',
- 'ws2_32.lib',
- 'Shlwapi.lib',
- ])
-
- # we just build static libraries that GN needs
- executables['gn']['libs'].extend(static_libraries.keys())
-
- write_generic_ninja(path, static_libraries, executables, cc, cxx, ar, ld,
- cflags, cflags_cc, ldflags, include_dirs, libs)
-
-def build_gn_with_gn(temp_gn, build_dir, options):
gn_gen_args = options.gn_gen_args or ''
if not options.debug:
gn_gen_args += ' is_debug=false'
- cmd = [temp_gn, 'gen', build_dir, '--args=%s' % gn_gen_args,
- "--root="+SRC_ROOT
- ]
- check_call(cmd)
-
- cmd = ['ninja', '-C', build_dir, '-w', 'dupbuild=err']
- if options.verbose:
- cmd.append('-v')
- cmd.append('gn')
- check_call(cmd)
-
- # build.ninja currently refers back to gn from the temporary directory.
- # Regenerate the build files using the gn we just built so that the reference
- # gets updated to "./gn".
- cmd = [os.path.join(build_dir, 'gn'), 'gen', build_dir,
- '--args=%s' % gn_gen_args]
- check_call(cmd)
-
- if not options.debug and not is_win:
- check_call(['strip', os.path.join(build_dir, 'gn')])
+ subprocess.check_call([
+ gn_path, 'gen', out_dir,
+ '--args=%s' % gn_gen_args, "--root=" + SRC_ROOT
+ ])
if __name__ == '__main__':
diff --git a/chromium/tools/gn/bootstrap/build.ninja.template b/chromium/tools/gn/bootstrap/build.ninja.template
deleted file mode 100644
index e59854b189e..00000000000
--- a/chromium/tools/gn/bootstrap/build.ninja.template
+++ /dev/null
@@ -1,19 +0,0 @@
-rule cc
- command = $cc -MMD -MF $out.d $defines $includes $cflags $cflags_c -c $in -o $out
- description = CC $out
- depfile = $out.d
- deps = gcc
-
-rule cxx
- command = $cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc -c $in -o $out
- description = CXX $out
- depfile = $out.d
- deps = gcc
-
-rule alink_thin
- command = rm -f $out && $ar rcsT $out $in
- description = AR $out
-
-rule link
- command = $ld $ldflags -o $out -Wl,--start-group $in $libs -Wl,--end-group $solibs
- description = LINK $out
diff --git a/chromium/tools/gn/bootstrap/build_aix.ninja.template b/chromium/tools/gn/bootstrap/build_aix.ninja.template
deleted file mode 100644
index 5cd36d62c05..00000000000
--- a/chromium/tools/gn/bootstrap/build_aix.ninja.template
+++ /dev/null
@@ -1,19 +0,0 @@
-rule cc
- command = $cc -MMD -MF $out.d $defines $includes $cflags $cflags_c -c $in -o $out
- description = CC $out
- depfile = $out.d
- deps = gcc
-
-rule cxx
- command = $cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc -c $in -o $out
- description = CXX $out
- depfile = $out.d
- deps = gcc
-
-rule alink_thin
- command = rm -f $out && $ar rcsT $out $in
- description = AR $out
-
-rule link
- command = $ld $ldflags -o $out $in $libs $solibs
- description = LINK $out
diff --git a/chromium/tools/gn/bootstrap/build_mac.ninja.template b/chromium/tools/gn/bootstrap/build_mac.ninja.template
deleted file mode 100644
index ff82eb88c1d..00000000000
--- a/chromium/tools/gn/bootstrap/build_mac.ninja.template
+++ /dev/null
@@ -1,19 +0,0 @@
-rule cc
- command = $cc -MMD -MF $out.d $defines $includes $cflags $cflags_c -c $in -o $out
- description = CC $out
- depfile = $out.d
- deps = gcc
-
-rule cxx
- command = $cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc -c $in -o $out
- description = CXX $out
- depfile = $out.d
- deps = gcc
-
-rule alink_thin
- command = rm -f $out && libtool -static -o $out $in
- description = AR $out
-
-rule link
- command = $ld $ldflags -o $out $in $solibs $libs
- description = LINK $out
diff --git a/chromium/tools/gn/bootstrap/build_vs.ninja.template b/chromium/tools/gn/bootstrap/build_vs.ninja.template
deleted file mode 100644
index 88bba37aec9..00000000000
--- a/chromium/tools/gn/bootstrap/build_vs.ninja.template
+++ /dev/null
@@ -1,28 +0,0 @@
-
-arch = environment.x64
-
-rule cc
- command = ninja -t msvc -e $arch -- $cc /nologo /showIncludes /FC @${out}.rsp /c ${in} /Fo${out}
- description = CC ${out}
- rspfile = ${out}.rsp
- rspfile_content = ${defines} ${includes} ${cflags} ${cflags_c}
- deps = msvc
-
-rule cxx
- command = ninja -t msvc -e $arch -- $cxx /nologo /showIncludes /FC @${out}.rsp /c ${in} /Fo${out}
- description = CXX ${out}
- rspfile = ${out}.rsp
- rspfile_content = ${defines} ${includes} ${cflags} ${cflags_cc}
- deps = msvc
-
-rule alink_thin
- command = ninja -t msvc -e $arch -- $ar /nologo /ignore:4221 /OUT:${out} @${out}.rsp
- description = LIB ${out}
- rspfile = ${out}.rsp
- rspfile_content = ${in_newline}
-
-rule link
- command = ninja -t msvc -e $arch -- $ld /nologo /OUT:${out} /PDB:${out}.pdb @${out}.rsp
- description = LINK ${out}
- rspfile = ${out}.rsp
- rspfile_content = ${in_newline} ${libs} ${solibs} ${ldflags}
diff --git a/chromium/tools/gn/build_settings.cc b/chromium/tools/gn/build_settings.cc
deleted file mode 100644
index 79b8365f19e..00000000000
--- a/chromium/tools/gn/build_settings.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/build_settings.h"
-
-#include <utility>
-
-#include "base/files/file_util.h"
-#include "tools/gn/filesystem_utils.h"
-
-BuildSettings::BuildSettings() = default;
-
-BuildSettings::BuildSettings(const BuildSettings& other)
- : root_path_(other.root_path_),
- root_path_utf8_(other.root_path_utf8_),
- secondary_source_path_(other.secondary_source_path_),
- python_path_(other.python_path_),
- build_config_file_(other.build_config_file_),
- arg_file_template_path_(other.arg_file_template_path_),
- build_dir_(other.build_dir_),
- build_args_(other.build_args_) {}
-
-BuildSettings::~BuildSettings() = default;
-
-void BuildSettings::SetRootTargetLabel(const Label& r) {
- root_target_label_ = r;
-}
-
-void BuildSettings::SetRootPath(const base::FilePath& r) {
- DCHECK(r.value()[r.value().size() - 1] != base::FilePath::kSeparators[0]);
- root_path_ = r.NormalizePathSeparatorsTo('/');
- root_path_utf8_ = FilePathToUTF8(root_path_);
-}
-
-void BuildSettings::SetSecondarySourcePath(const SourceDir& d) {
- secondary_source_path_ = GetFullPath(d).NormalizePathSeparatorsTo('/');
-}
-
-void BuildSettings::SetBuildDir(const SourceDir& d) {
- build_dir_ = d;
-}
-
-base::FilePath BuildSettings::GetFullPath(const SourceFile& file) const {
- return file.Resolve(root_path_).NormalizePathSeparatorsTo('/');
-}
-
-base::FilePath BuildSettings::GetFullPath(const SourceDir& dir) const {
- return dir.Resolve(root_path_).NormalizePathSeparatorsTo('/');
-}
-
-base::FilePath BuildSettings::GetFullPath(const std::string& path,
- bool as_file) const {
- return ResolvePath(path, as_file, root_path_).NormalizePathSeparatorsTo('/');
-}
-
-base::FilePath BuildSettings::GetFullPathSecondary(
- const SourceFile& file) const {
- return file.Resolve(secondary_source_path_).NormalizePathSeparatorsTo('/');
-}
-
-base::FilePath BuildSettings::GetFullPathSecondary(
- const SourceDir& dir) const {
- return dir.Resolve(secondary_source_path_).NormalizePathSeparatorsTo('/');
-}
-
-base::FilePath BuildSettings::GetFullPathSecondary(const std::string& path,
- bool as_file) const {
- return ResolvePath(path, as_file, secondary_source_path_)
- .NormalizePathSeparatorsTo('/');
-}
-
-void BuildSettings::ItemDefined(std::unique_ptr<Item> item) const {
- DCHECK(item);
- if (!item_defined_callback_.is_null())
- item_defined_callback_.Run(std::move(item));
-}
diff --git a/chromium/tools/gn/build_settings.h b/chromium/tools/gn/build_settings.h
deleted file mode 100644
index 52f3625a4be..00000000000
--- a/chromium/tools/gn/build_settings.h
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_BUILD_SETTINGS_H_
-#define TOOLS_GN_BUILD_SETTINGS_H_
-
-#include <map>
-#include <memory>
-#include <set>
-#include <utility>
-
-#include "base/callback.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "tools/gn/args.h"
-#include "tools/gn/label.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/source_dir.h"
-#include "tools/gn/source_file.h"
-
-class Item;
-
-// Settings for one build, which is one toplevel output directory. There
-// may be multiple Settings objects that refer to this, one for each toolchain.
-class BuildSettings {
- public:
- typedef base::Callback<void(std::unique_ptr<Item>)> ItemDefinedCallback;
- typedef base::Callback<void(const std::string&)> PrintCallback;
-
- BuildSettings();
- BuildSettings(const BuildSettings& other);
- ~BuildSettings();
-
- // Root target label.
- const Label& root_target_label() const { return root_target_label_; }
- void SetRootTargetLabel(const Label& r);
-
- // Absolute path of the source root on the local system. Everything is
- // relative to this. Does not end in a [back]slash.
- const base::FilePath& root_path() const { return root_path_; }
- const std::string& root_path_utf8() const { return root_path_utf8_; }
- void SetRootPath(const base::FilePath& r);
-
- // When nonempty, specifies a parallel directory higherarchy in which to
- // search for buildfiles if they're not found in the root higherarchy. This
- // allows us to keep buildfiles in a separate tree during development.
- const base::FilePath& secondary_source_path() const {
- return secondary_source_path_;
- }
- void SetSecondarySourcePath(const SourceDir& d);
-
- // Path of the python executable to run scripts with.
- base::FilePath python_path() const { return python_path_; }
- void set_python_path(const base::FilePath& p) { python_path_ = p; }
-
- const SourceFile& build_config_file() const { return build_config_file_; }
- void set_build_config_file(const SourceFile& f) { build_config_file_ = f; }
-
- // Path to a file containing the default text to use when running `gn args`.
- const SourceFile& arg_file_template_path() const {
- return arg_file_template_path_;
- }
- void set_arg_file_template_path(const SourceFile& f) {
- arg_file_template_path_ = f;
- }
-
- // The build directory is the root of all output files. The default toolchain
- // files go into here, and non-default toolchains will have separate
- // toolchain-specific root directories inside this.
- const SourceDir& build_dir() const { return build_dir_; }
- void SetBuildDir(const SourceDir& dir);
-
- // The build args are normally specified on the command-line.
- Args& build_args() { return build_args_; }
- const Args& build_args() const { return build_args_; }
-
- // Returns the full absolute OS path cooresponding to the given file in the
- // root source tree.
- base::FilePath GetFullPath(const SourceFile& file) const;
- base::FilePath GetFullPath(const SourceDir& dir) const;
- // Works the same way as other GetFullPath.
- // Parameter as_file defines whether path should be treated as a
- // SourceFile or SourceDir value.
- base::FilePath GetFullPath(const std::string& path, bool as_file) const;
-
- // Returns the absolute OS path inside the secondary source path. Will return
- // an empty FilePath if the secondary source path is empty. When loading a
- // buildfile, the GetFullPath should always be consulted first.
- base::FilePath GetFullPathSecondary(const SourceFile& file) const;
- base::FilePath GetFullPathSecondary(const SourceDir& dir) const;
- // Works the same way as other GetFullPathSecondary.
- // Parameter as_file defines whether path should be treated as a
- // SourceFile or SourceDir value.
- base::FilePath GetFullPathSecondary(const std::string& path,
- bool as_file) const;
-
- // Called when an item is defined from a background thread.
- void ItemDefined(std::unique_ptr<Item> item) const;
- void set_item_defined_callback(ItemDefinedCallback cb) {
- item_defined_callback_ = cb;
- }
-
- // Defines a callback that will be used to override the behavior of the
- // print function. This is used in tests to collect print output. If the
- // callback is is_null() (the default) the output will be printed to the
- // console.
- const PrintCallback& print_callback() const { return print_callback_; }
- void set_print_callback(const PrintCallback& cb) { print_callback_ = cb; }
-
- // A list of files that can call exec_script(). If the returned pointer is
- // null, exec_script may be called from anywhere.
- const std::set<SourceFile>* exec_script_whitelist() const {
- return exec_script_whitelist_.get();
- }
- void set_exec_script_whitelist(std::unique_ptr<std::set<SourceFile>> list) {
- exec_script_whitelist_ = std::move(list);
- }
-
- private:
- Label root_target_label_;
- base::FilePath root_path_;
- std::string root_path_utf8_;
- base::FilePath secondary_source_path_;
- base::FilePath python_path_;
-
- SourceFile build_config_file_;
- SourceFile arg_file_template_path_;
- SourceDir build_dir_;
- Args build_args_;
-
- ItemDefinedCallback item_defined_callback_;
- PrintCallback print_callback_;
-
- std::unique_ptr<std::set<SourceFile>> exec_script_whitelist_;
-
- DISALLOW_ASSIGN(BuildSettings);
-};
-
-#endif // TOOLS_GN_BUILD_SETTINGS_H_
diff --git a/chromium/tools/gn/builder.cc b/chromium/tools/gn/builder.cc
deleted file mode 100644
index ec45e6c6be3..00000000000
--- a/chromium/tools/gn/builder.cc
+++ /dev/null
@@ -1,604 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/builder.h"
-
-#include <stddef.h>
-#include <utility>
-
-#include "tools/gn/action_values.h"
-#include "tools/gn/config.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/err.h"
-#include "tools/gn/loader.h"
-#include "tools/gn/pool.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/target.h"
-#include "tools/gn/trace.h"
-
-namespace {
-
-typedef BuilderRecord::BuilderRecordSet BuilderRecordSet;
-
-// Recursively looks in the tree for a given node, returning true if it
-// was found in the dependecy graph. This is used to see if a given node
-// participates in a cycle.
-//
-// If this returns true, the cycle will be in *path. This should point to an
-// empty vector for the first call. During computation, the path will contain
-// the full dependency path to the current node.
-//
-// Return false means no cycle was found.
-bool RecursiveFindCycle(const BuilderRecord* search_in,
- std::vector<const BuilderRecord*>* path) {
- path->push_back(search_in);
- for (auto* cur : search_in->unresolved_deps()) {
- std::vector<const BuilderRecord*>::iterator found =
- std::find(path->begin(), path->end(), cur);
- if (found != path->end()) {
- // This item is already in the set, we found the cycle. Everything before
- // the first definition of cur is irrelevant to the cycle.
- path->erase(path->begin(), found);
- path->push_back(cur);
- return true;
- }
-
- if (RecursiveFindCycle(cur, path))
- return true; // Found cycle.
- }
- path->pop_back();
- return false;
-}
-
-} // namespace
-
-Builder::Builder(Loader* loader) : loader_(loader) {
-}
-
-Builder::~Builder() = default;
-
-void Builder::ItemDefined(std::unique_ptr<Item> item) {
- ScopedTrace trace(TraceItem::TRACE_DEFINE_TARGET, item->label());
- trace.SetToolchain(item->settings()->toolchain_label());
-
- BuilderRecord::ItemType type = BuilderRecord::TypeOfItem(item.get());
-
- Err err;
- BuilderRecord* record =
- GetOrCreateRecordOfType(item->label(), item->defined_from(), type, &err);
- if (!record) {
- g_scheduler->FailWithError(err);
- return;
- }
-
- // Check that it's not been already defined.
- if (record->item()) {
- err = Err(item->defined_from(), "Duplicate definition.",
- "The item\n " + item->label().GetUserVisibleName(false) +
- "\nwas already defined.");
- err.AppendSubErr(Err(record->item()->defined_from(),
- "Previous definition:"));
- g_scheduler->FailWithError(err);
- return;
- }
-
- record->set_item(std::move(item));
-
- // Do target-specific dependency setup. This will also schedule dependency
- // loads for targets that are required.
- switch (type) {
- case BuilderRecord::ITEM_TARGET:
- TargetDefined(record, &err);
- break;
- case BuilderRecord::ITEM_CONFIG:
- ConfigDefined(record, &err);
- break;
- case BuilderRecord::ITEM_TOOLCHAIN:
- ToolchainDefined(record, &err);
- break;
- default:
- break;
- }
- if (err.has_error()) {
- g_scheduler->FailWithError(err);
- return;
- }
-
- if (record->can_resolve()) {
- if (!ResolveItem(record, &err)) {
- g_scheduler->FailWithError(err);
- return;
- }
- }
-}
-
-const Item* Builder::GetItem(const Label& label) const {
- const BuilderRecord* record = GetRecord(label);
- if (!record)
- return nullptr;
- return record->item();
-}
-
-const Toolchain* Builder::GetToolchain(const Label& label) const {
- const BuilderRecord* record = GetRecord(label);
- if (!record)
- return nullptr;
- if (!record->item())
- return nullptr;
- return record->item()->AsToolchain();
-}
-
-std::vector<const BuilderRecord*> Builder::GetAllRecords() const {
- std::vector<const BuilderRecord*> result;
- result.reserve(records_.size());
- for (const auto& record : records_)
- result.push_back(record.second.get());
- return result;
-}
-
-std::vector<const Item*> Builder::GetAllResolvedItems() const {
- std::vector<const Item*> result;
- result.reserve(records_.size());
- for (const auto& record : records_) {
- if (record.second->type() != BuilderRecord::ITEM_UNKNOWN &&
- record.second->should_generate() && record.second->item()) {
- result.push_back(record.second->item());
- }
- }
-
- return result;
-}
-
-std::vector<const Target*> Builder::GetAllResolvedTargets() const {
- std::vector<const Target*> result;
- result.reserve(records_.size());
- for (const auto& record : records_) {
- if (record.second->type() == BuilderRecord::ITEM_TARGET &&
- record.second->should_generate() && record.second->item())
- result.push_back(record.second->item()->AsTarget());
- }
- return result;
-}
-
-const BuilderRecord* Builder::GetRecord(const Label& label) const {
- // Forward to the non-const version.
- return const_cast<Builder*>(this)->GetRecord(label);
-}
-
-BuilderRecord* Builder::GetRecord(const Label& label) {
- auto found = records_.find(label);
- return (found != records_.end()) ? found->second.get() : nullptr;
-}
-
-bool Builder::CheckForBadItems(Err* err) const {
- // Look for errors where we find a defined node with an item that refers to
- // an undefined one with no item. There may be other nodes in turn depending
- // on our defined one, but listing those isn't helpful: we want to find the
- // broken link.
- //
- // This finds normal "missing dependency" errors but does not find circular
- // dependencies because in this case all items in the cycle will be GENERATED
- // but none will be resolved. If this happens, we'll check explicitly for
- // that below.
- std::vector<const BuilderRecord*> bad_records;
- std::string depstring;
- for (const auto& record_pair : records_) {
- const BuilderRecord* src = record_pair.second.get();
- if (!src->should_generate())
- continue; // Skip ungenerated nodes.
-
- if (!src->resolved()) {
- bad_records.push_back(src);
-
- // Check dependencies.
- for (auto* dest : src->unresolved_deps()) {
- if (!dest->item()) {
- depstring += src->label().GetUserVisibleName(true) +
- "\n needs " + dest->label().GetUserVisibleName(true) + "\n";
- }
- }
- }
- }
-
- if (!depstring.empty()) {
- *err = Err(Location(), "Unresolved dependencies.", depstring);
- return false;
- }
-
- if (!bad_records.empty()) {
- // Our logic above found a bad node but didn't identify the problem. This
- // normally means a circular dependency.
- depstring = CheckForCircularDependencies(bad_records);
- if (depstring.empty()) {
- // Something's very wrong, just dump out the bad nodes.
- depstring = "I have no idea what went wrong, but these are unresolved, "
- "possibly due to an\ninternal error:";
- for (auto* bad_record : bad_records) {
- depstring += "\n\"" +
- bad_record->label().GetUserVisibleName(false) + "\"";
- }
- *err = Err(Location(), "", depstring);
- } else {
- *err = Err(Location(), "Dependency cycle:", depstring);
- }
- return false;
- }
-
- return true;
-}
-
-bool Builder::TargetDefined(BuilderRecord* record, Err* err) {
- Target* target = record->item()->AsTarget();
-
- if (!AddDeps(record, target->public_deps(), err) ||
- !AddDeps(record, target->private_deps(), err) ||
- !AddDeps(record, target->data_deps(), err) ||
- !AddDeps(record, target->configs().vector(), err) ||
- !AddDeps(record, target->all_dependent_configs(), err) ||
- !AddDeps(record, target->public_configs(), err) ||
- !AddActionValuesDep(record, target->action_values(), err) ||
- !AddToolchainDep(record, target, err))
- return false;
-
- // All targets in the default toolchain get generated by default. We also
- // check if this target was previously marked as "required" and force setting
- // the bit again so the target's dependencies (which we now know) get the
- // required bit pushed to them.
- if (record->should_generate() || target->settings()->is_default())
- RecursiveSetShouldGenerate(record, true);
-
- return true;
-}
-
-bool Builder::ConfigDefined(BuilderRecord* record, Err* err) {
- Config* config = record->item()->AsConfig();
- if (!AddDeps(record, config->configs(), err))
- return false;
-
- // Make sure all deps of this config are scheduled to be loaded. For other
- // item types like targets, the "should generate" flag is propagated around
- // to mark whether this should happen. We could call
- // RecursiveSetShouldGenerate to do this step here, but since configs nor
- // anything they depend on is actually written, the "generate" flag isn't
- // relevant and means extra book keeping. Just force load any deps of this
- // config.
- for (auto* cur : record->all_deps())
- ScheduleItemLoadIfNecessary(cur);
-
- return true;
-}
-
-bool Builder::ToolchainDefined(BuilderRecord* record, Err* err) {
- Toolchain* toolchain = record->item()->AsToolchain();
-
- if (!AddDeps(record, toolchain->deps(), err))
- return false;
-
- for (int i = Toolchain::TYPE_NONE + 1; i < Toolchain::TYPE_NUMTYPES; i++) {
- Toolchain::ToolType tool_type = static_cast<Toolchain::ToolType>(i);
- Tool* tool = toolchain->GetTool(tool_type);
- if (!tool || tool->pool().label.is_null())
- continue;
-
- BuilderRecord* dep_record = GetOrCreateRecordOfType(
- tool->pool().label, tool->pool().origin, BuilderRecord::ITEM_POOL, err);
- if (!dep_record)
- return false;
- record->AddDep(dep_record);
- }
-
- // The default toolchain gets generated by default. Also propogate the
- // generate flag if it depends on items in a non-default toolchain.
- if (record->should_generate() ||
- toolchain->settings()->default_toolchain_label() == toolchain->label())
- RecursiveSetShouldGenerate(record, true);
-
- loader_->ToolchainLoaded(toolchain);
- return true;
-}
-
-BuilderRecord* Builder::GetOrCreateRecordOfType(const Label& label,
- const ParseNode* request_from,
- BuilderRecord::ItemType type,
- Err* err) {
- BuilderRecord* record = GetRecord(label);
- if (!record) {
- // Not seen this record yet, create a new one.
- auto new_record = std::make_unique<BuilderRecord>(type, label);
- new_record->set_originally_referenced_from(request_from);
- record = new_record.get();
- records_[label] = std::move(new_record);
- return record;
- }
-
- // Check types.
- if (record->type() != type) {
- std::string msg =
- "The type of " + label.GetUserVisibleName(false) +
- "\nhere is a " + BuilderRecord::GetNameForType(type) +
- " but was previously seen as a " +
- BuilderRecord::GetNameForType(record->type()) + ".\n\n"
- "The most common cause is that the label of a config was put in the\n"
- "in the deps section of a target (or vice-versa).";
- *err = Err(request_from, "Item type does not match.", msg);
- if (record->originally_referenced_from()) {
- err->AppendSubErr(Err(record->originally_referenced_from(),
- std::string()));
- }
- return nullptr;
- }
-
- return record;
-}
-
-BuilderRecord* Builder::GetResolvedRecordOfType(const Label& label,
- const ParseNode* origin,
- BuilderRecord::ItemType type,
- Err* err) {
- BuilderRecord* record = GetRecord(label);
- if (!record) {
- *err = Err(origin, "Item not found",
- "\"" + label.GetUserVisibleName(false) + "\" doesn't\n"
- "refer to an existent thing.");
- return nullptr;
- }
-
- const Item* item = record->item();
- if (!item) {
- *err = Err(origin, "Item not resolved.",
- "\"" + label.GetUserVisibleName(false) + "\" hasn't been resolved.\n");
- return nullptr;
- }
-
- if (!BuilderRecord::IsItemOfType(item, type)) {
- *err = Err(origin,
- std::string("This is not a ") + BuilderRecord::GetNameForType(type),
- "\"" + label.GetUserVisibleName(false) + "\" refers to a " +
- item->GetItemTypeName() + " instead of a " +
- BuilderRecord::GetNameForType(type) + ".");
- return nullptr;
- }
- return record;
-}
-
-bool Builder::AddDeps(BuilderRecord* record,
- const LabelConfigVector& configs,
- Err* err) {
- for (const auto& config : configs) {
- BuilderRecord* dep_record = GetOrCreateRecordOfType(
- config.label, config.origin, BuilderRecord::ITEM_CONFIG, err);
- if (!dep_record)
- return false;
- record->AddDep(dep_record);
- }
- return true;
-}
-
-bool Builder::AddDeps(BuilderRecord* record,
- const UniqueVector<LabelConfigPair>& configs,
- Err* err) {
- for (const auto& config : configs) {
- BuilderRecord* dep_record = GetOrCreateRecordOfType(
- config.label, config.origin, BuilderRecord::ITEM_CONFIG, err);
- if (!dep_record)
- return false;
- record->AddDep(dep_record);
- }
- return true;
-}
-
-bool Builder::AddDeps(BuilderRecord* record,
- const LabelTargetVector& targets,
- Err* err) {
- for (const auto& target : targets) {
- BuilderRecord* dep_record = GetOrCreateRecordOfType(
- target.label, target.origin, BuilderRecord::ITEM_TARGET, err);
- if (!dep_record)
- return false;
- record->AddDep(dep_record);
- }
- return true;
-}
-
-bool Builder::AddActionValuesDep(BuilderRecord* record,
- const ActionValues& action_values,
- Err* err) {
- if (action_values.pool().label.is_null())
- return true;
-
- BuilderRecord* pool_record = GetOrCreateRecordOfType(
- action_values.pool().label, action_values.pool().origin,
- BuilderRecord::ITEM_POOL, err);
- if (!pool_record)
- return false;
- record->AddDep(pool_record);
-
- return true;
-}
-
-bool Builder::AddToolchainDep(BuilderRecord* record,
- const Target* target,
- Err* err) {
- BuilderRecord* toolchain_record = GetOrCreateRecordOfType(
- target->settings()->toolchain_label(), target->defined_from(),
- BuilderRecord::ITEM_TOOLCHAIN, err);
- if (!toolchain_record)
- return false;
- record->AddDep(toolchain_record);
-
- return true;
-}
-
-void Builder::RecursiveSetShouldGenerate(BuilderRecord* record,
- bool force) {
- if (!record->should_generate()) {
- record->set_should_generate(true);
-
- // This may have caused the item to go into "resolved and generated" state.
- if (record->resolved() && !resolved_and_generated_callback_.is_null())
- resolved_and_generated_callback_.Run(record);
- } else if (!force) {
- return; // Already set and we're not required to iterate dependencies.
- }
-
- for (auto* cur : record->all_deps()) {
- if (!cur->should_generate()) {
- ScheduleItemLoadIfNecessary(cur);
- RecursiveSetShouldGenerate(cur, false);
- }
- }
-}
-
-void Builder::ScheduleItemLoadIfNecessary(BuilderRecord* record) {
- const ParseNode* origin = record->originally_referenced_from();
- loader_->Load(record->label(),
- origin ? origin->GetRange() : LocationRange());
-}
-
-bool Builder::ResolveItem(BuilderRecord* record, Err* err) {
- DCHECK(record->can_resolve() && !record->resolved());
-
- if (record->type() == BuilderRecord::ITEM_TARGET) {
- Target* target = record->item()->AsTarget();
- if (!ResolveDeps(&target->public_deps(), err) ||
- !ResolveDeps(&target->private_deps(), err) ||
- !ResolveDeps(&target->data_deps(), err) ||
- !ResolveConfigs(&target->configs(), err) ||
- !ResolveConfigs(&target->all_dependent_configs(), err) ||
- !ResolveConfigs(&target->public_configs(), err) ||
- !ResolveActionValues(&target->action_values(), err) ||
- !ResolveToolchain(target, err))
- return false;
- } else if (record->type() == BuilderRecord::ITEM_CONFIG) {
- Config* config = record->item()->AsConfig();
- if (!ResolveConfigs(&config->configs(), err))
- return false;
- } else if (record->type() == BuilderRecord::ITEM_TOOLCHAIN) {
- Toolchain* toolchain = record->item()->AsToolchain();
- if (!ResolveDeps(&toolchain->deps(), err))
- return false;
- if (!ResolvePools(toolchain, err))
- return false;
- }
-
- record->set_resolved(true);
-
- if (!record->item()->OnResolved(err))
- return false;
- if (record->should_generate() && !resolved_and_generated_callback_.is_null())
- resolved_and_generated_callback_.Run(record);
-
- // Recursively update everybody waiting on this item to be resolved.
- for (BuilderRecord* waiting : record->waiting_on_resolution()) {
- DCHECK(waiting->unresolved_deps().find(record) !=
- waiting->unresolved_deps().end());
- waiting->unresolved_deps().erase(record);
-
- if (waiting->can_resolve()) {
- if (!ResolveItem(waiting, err))
- return false;
- }
- }
- record->waiting_on_resolution().clear();
- return true;
-}
-
-bool Builder::ResolveDeps(LabelTargetVector* deps, Err* err) {
- for (LabelTargetPair& cur : *deps) {
- DCHECK(!cur.ptr);
-
- BuilderRecord* record = GetResolvedRecordOfType(
- cur.label, cur.origin, BuilderRecord::ITEM_TARGET, err);
- if (!record)
- return false;
- cur.ptr = record->item()->AsTarget();
- }
- return true;
-}
-
-bool Builder::ResolveConfigs(UniqueVector<LabelConfigPair>* configs, Err* err) {
- for (const auto& cur : *configs) {
- DCHECK(!cur.ptr);
-
- BuilderRecord* record = GetResolvedRecordOfType(
- cur.label, cur.origin, BuilderRecord::ITEM_CONFIG, err);
- if (!record)
- return false;
- const_cast<LabelConfigPair&>(cur).ptr = record->item()->AsConfig();
- }
- return true;
-}
-
-bool Builder::ResolveToolchain(Target* target, Err* err) {
- BuilderRecord* record = GetResolvedRecordOfType(
- target->settings()->toolchain_label(), target->defined_from(),
- BuilderRecord::ITEM_TOOLCHAIN, err);
- if (!record) {
- *err = Err(target->defined_from(),
- "Toolchain for target not defined.",
- "I was hoping to find a toolchain " +
- target->settings()->toolchain_label().GetUserVisibleName(false));
- return false;
- }
-
- if (!target->SetToolchain(record->item()->AsToolchain(), err))
- return false;
-
- return true;
-}
-
-bool Builder::ResolveActionValues(ActionValues* action_values, Err* err) {
- if (action_values->pool().label.is_null())
- return true;
-
- BuilderRecord* record = GetResolvedRecordOfType(
- action_values->pool().label, action_values->pool().origin,
- BuilderRecord::ITEM_POOL, err);
- if (!record)
- return false;
- action_values->set_pool(LabelPtrPair<Pool>(record->item()->AsPool()));
-
- return true;
-}
-
-bool Builder::ResolvePools(Toolchain* toolchain, Err* err) {
- for (int i = Toolchain::TYPE_NONE + 1; i < Toolchain::TYPE_NUMTYPES; i++) {
- Toolchain::ToolType tool_type = static_cast<Toolchain::ToolType>(i);
- Tool* tool = toolchain->GetTool(tool_type);
- if (!tool || tool->pool().label.is_null())
- continue;
-
- BuilderRecord* record =
- GetResolvedRecordOfType(tool->pool().label, toolchain->defined_from(),
- BuilderRecord::ITEM_POOL, err);
- if (!record) {
- *err = Err(tool->pool().origin, "Pool for tool not defined.",
- "I was hoping to find a pool " +
- tool->pool().label.GetUserVisibleName(false));
- return false;
- }
-
- tool->set_pool(LabelPtrPair<Pool>(record->item()->AsPool()));
- }
-
- return true;
-}
-
-std::string Builder::CheckForCircularDependencies(
- const std::vector<const BuilderRecord*>& bad_records) const {
- std::vector<const BuilderRecord*> cycle;
- if (!RecursiveFindCycle(bad_records[0], &cycle))
- return std::string(); // Didn't find a cycle, something else is wrong.
-
- std::string ret;
- for (size_t i = 0; i < cycle.size(); i++) {
- ret += " " + cycle[i]->label().GetUserVisibleName(false);
- if (i != cycle.size() - 1)
- ret += " ->";
- ret += "\n";
- }
-
- return ret;
-}
diff --git a/chromium/tools/gn/builder.h b/chromium/tools/gn/builder.h
deleted file mode 100644
index 58ccbada39e..00000000000
--- a/chromium/tools/gn/builder.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_BUILDER_H_
-#define TOOLS_GN_BUILDER_H_
-
-#include <map>
-#include <memory>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "tools/gn/builder_record.h"
-#include "tools/gn/label.h"
-#include "tools/gn/label_ptr.h"
-#include "tools/gn/unique_vector.h"
-
-class ActionValues;
-class Err;
-class Loader;
-class ParseNode;
-
-// The builder assembles the dependency tree. It is not threadsafe and runs on
-// the main thread only. See also BuilderRecord.
-class Builder {
- public:
- typedef base::Callback<void(const BuilderRecord*)> ResolvedGeneratedCallback;
-
- explicit Builder(Loader* loader);
- ~Builder();
-
- // The resolved callback is called when a target has been both resolved and
- // marked generated. This will be executed only on the main thread.
- void set_resolved_and_generated_callback(
- const ResolvedGeneratedCallback& cb) {
- resolved_and_generated_callback_ = cb;
- }
-
- Loader* loader() const { return loader_; }
-
- void ItemDefined(std::unique_ptr<Item> item);
-
- // Returns NULL if there is not a thing with the corresponding label.
- const Item* GetItem(const Label& label) const;
- const Toolchain* GetToolchain(const Label& label) const;
-
- std::vector<const BuilderRecord*> GetAllRecords() const;
-
- // Returns items which should be generated and which are defined.
- std::vector<const Item*> GetAllResolvedItems() const;
-
- // Returns targets which should be generated and which are defined.
- std::vector<const Target*> GetAllResolvedTargets() const;
-
- // Returns the record for the given label, or NULL if it doesn't exist.
- // Mostly used for unit tests.
- const BuilderRecord* GetRecord(const Label& label) const;
- BuilderRecord* GetRecord(const Label& label);
-
- // If there are any undefined references, returns false and sets the error.
- bool CheckForBadItems(Err* err) const;
-
- private:
- bool TargetDefined(BuilderRecord* record, Err* err);
- bool ConfigDefined(BuilderRecord* record, Err* err);
- bool ToolchainDefined(BuilderRecord* record, Err* err);
-
- // Returns the record associated with the given label. This function checks
- // that if we already have references for it, the type matches. If no record
- // exists yet, a new one will be created.
- //
- // If any of the conditions fail, the return value will be null and the error
- // will be set. request_from is used as the source of the error.
- BuilderRecord* GetOrCreateRecordOfType(const Label& label,
- const ParseNode* request_from,
- BuilderRecord::ItemType type,
- Err* err);
-
- // Returns the record associated with the given label. This function checks
- // that it's already been resolved to the correct type.
- //
- // If any of the conditions fail, the return value will be null and the error
- // will be set. request_from is used as the source of the error.
- BuilderRecord* GetResolvedRecordOfType(const Label& label,
- const ParseNode* request_from,
- BuilderRecord::ItemType type,
- Err* err);
-
- bool AddDeps(BuilderRecord* record,
- const LabelConfigVector& configs,
- Err* err);
- bool AddDeps(BuilderRecord* record,
- const UniqueVector<LabelConfigPair>& configs,
- Err* err);
- bool AddDeps(BuilderRecord* record,
- const LabelTargetVector& targets,
- Err* err);
- bool AddActionValuesDep(BuilderRecord* record,
- const ActionValues& action_values,
- Err* err);
- bool AddToolchainDep(BuilderRecord* record,
- const Target* target,
- Err* err);
-
- // Given a target, sets the "should generate" bit and pushes it through the
- // dependency tree. Any time the bit it set, we ensure that the given item is
- // scheduled to be loaded.
- //
- // If the force flag is set, we'll ignore the current state of the record's
- // should_generate flag, and set it on the dependents every time. This is
- // used when defining a target: the "should generate" may have been set
- // before the item was defined (if it is required by something that is
- // required). In this case, we need to re-push the "should generate" flag
- // to the item's dependencies.
- void RecursiveSetShouldGenerate(BuilderRecord* record, bool force);
-
- void ScheduleItemLoadIfNecessary(BuilderRecord* record);
-
- // This takes a BuilderRecord with resolved depdencies, and fills in the
- // target's Label*Vectors with the resolved pointers.
- bool ResolveItem(BuilderRecord* record, Err* err);
-
- // Fills in the pointers in the given vector based on the labels. We assume
- // that everything should be resolved by this point, so will return an error
- // if anything isn't found or if the type doesn't match.
- bool ResolveDeps(LabelTargetVector* deps, Err* err);
- bool ResolveConfigs(UniqueVector<LabelConfigPair>* configs, Err* err);
- bool ResolveActionValues(ActionValues* action_values, Err* err);
- bool ResolveToolchain(Target* target, Err* err);
- bool ResolvePools(Toolchain* toolchain, Err* err);
-
- // Given a list of unresolved records, tries to find any circular
- // dependencies and returns the string describing the problem. If no circular
- // deps were found, returns the empty string.
- std::string CheckForCircularDependencies(
- const std::vector<const BuilderRecord*>& bad_records) const;
-
- // Non owning pointer.
- Loader* loader_;
-
- std::map<Label, std::unique_ptr<BuilderRecord>> records_;
-
- ResolvedGeneratedCallback resolved_and_generated_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(Builder);
-};
-
-#endif // TOOLS_GN_BUILDER_H_
diff --git a/chromium/tools/gn/builder_record.cc b/chromium/tools/gn/builder_record.cc
deleted file mode 100644
index 665baae9ee8..00000000000
--- a/chromium/tools/gn/builder_record.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/builder_record.h"
-
-#include "tools/gn/item.h"
-
-BuilderRecord::BuilderRecord(ItemType type, const Label& label)
- : type_(type),
- label_(label),
- originally_referenced_from_(nullptr),
- should_generate_(false),
- resolved_(false) {
-}
-
-BuilderRecord::~BuilderRecord() = default;
-
-// static
-const char* BuilderRecord::GetNameForType(ItemType type) {
- switch (type) {
- case ITEM_TARGET:
- return "target";
- case ITEM_CONFIG:
- return "config";
- case ITEM_TOOLCHAIN:
- return "toolchain";
- case ITEM_POOL:
- return "pool";
- case ITEM_UNKNOWN:
- default:
- return "unknown";
- }
-}
-
-// static
-bool BuilderRecord::IsItemOfType(const Item* item, ItemType type) {
- switch (type) {
- case ITEM_TARGET:
- return !!item->AsTarget();
- case ITEM_CONFIG:
- return !!item->AsConfig();
- case ITEM_TOOLCHAIN:
- return !!item->AsToolchain();
- case ITEM_POOL:
- return !!item->AsPool();
- case ITEM_UNKNOWN:
- default:
- return false;
- }
-}
-
-// static
-BuilderRecord::ItemType BuilderRecord::TypeOfItem(const Item* item) {
- if (item->AsTarget())
- return ITEM_TARGET;
- if (item->AsConfig())
- return ITEM_CONFIG;
- if (item->AsToolchain())
- return ITEM_TOOLCHAIN;
- if (item->AsPool())
- return ITEM_POOL;
-
- NOTREACHED();
- return ITEM_UNKNOWN;
-}
-
-void BuilderRecord::AddDep(BuilderRecord* record) {
- all_deps_.insert(record);
- if (!record->resolved()) {
- unresolved_deps_.insert(record);
- record->waiting_on_resolution_.insert(this);
- }
-}
diff --git a/chromium/tools/gn/builder_record.h b/chromium/tools/gn/builder_record.h
deleted file mode 100644
index 7643b47affc..00000000000
--- a/chromium/tools/gn/builder_record.h
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_BUILDER_RECORD_H_
-#define TOOLS_GN_BUILDER_RECORD_H_
-
-#include <memory>
-#include <set>
-#include <utility>
-
-#include "base/macros.h"
-#include "tools/gn/item.h"
-#include "tools/gn/location.h"
-
-class ParseNode;
-
-// This class is used by the builder to manage the loading of the dependency
-// tree. It holds a reference to an item and links to other records that the
-// item depends on, both resolved ones, and unresolved ones.
-//
-// If a target depends on another one that hasn't been defined yet, we'll make
-// a placeholder BuilderRecord with no item, and try to load the buildfile
-// associated with the new item. The item will get filled in when we encounter
-// the declaration for the item (or when we're done and realize there are
-// undefined items).
-//
-// You can also have null item pointers when the target is not required for
-// the current build (should_generate is false).
-class BuilderRecord {
- public:
- typedef std::set<BuilderRecord*> BuilderRecordSet;
-
- enum ItemType {
- ITEM_UNKNOWN,
- ITEM_TARGET,
- ITEM_CONFIG,
- ITEM_TOOLCHAIN,
- ITEM_POOL
- };
-
- BuilderRecord(ItemType type, const Label& label);
- ~BuilderRecord();
-
- ItemType type() const { return type_; }
- const Label& label() const { return label_; }
-
- // Returns a user-ready name for the given type. e.g. "target".
- static const char* GetNameForType(ItemType type);
-
- // Returns true if the given item is of the given type.
- static bool IsItemOfType(const Item* item, ItemType type);
-
- // Returns the type enum for the given item.
- static ItemType TypeOfItem(const Item* item);
-
- Item* item() { return item_.get(); }
- const Item* item() const { return item_.get(); }
- void set_item(std::unique_ptr<Item> item) { item_ = std::move(item); }
-
- // Indicates from where this item was originally referenced from that caused
- // it to be loaded. For targets for which we encountered the declaration
- // before a reference, this will be the empty range.
- const ParseNode* originally_referenced_from() const {
- return originally_referenced_from_;
- }
- void set_originally_referenced_from(const ParseNode* pn) {
- originally_referenced_from_ = pn;
- }
-
- bool should_generate() const { return should_generate_; }
- void set_should_generate(bool sg) { should_generate_ = sg; }
-
- bool resolved() const { return resolved_; }
- void set_resolved(bool r) { resolved_ = r; }
-
- bool can_resolve() const {
- return item_ && unresolved_deps_.empty();
- }
-
- // All records this one is depending on.
- BuilderRecordSet& all_deps() { return all_deps_; }
- const BuilderRecordSet& all_deps() const { return all_deps_; }
-
- // Unresolved records this one is depending on. A subset of all... above.
- BuilderRecordSet& unresolved_deps() { return unresolved_deps_; }
- const BuilderRecordSet& unresolved_deps() const { return unresolved_deps_; }
-
- // Records that are waiting on this one to be resolved. This is the other
- // end of the "unresolved deps" arrow.
- BuilderRecordSet& waiting_on_resolution() { return waiting_on_resolution_; }
- const BuilderRecordSet& waiting_on_resolution() const {
- return waiting_on_resolution_;
- }
-
- void AddDep(BuilderRecord* record);
-
- private:
- ItemType type_;
- Label label_;
- std::unique_ptr<Item> item_;
- const ParseNode* originally_referenced_from_;
- bool should_generate_;
- bool resolved_;
-
- BuilderRecordSet all_deps_;
- BuilderRecordSet unresolved_deps_;
- BuilderRecordSet waiting_on_resolution_;
-
- DISALLOW_COPY_AND_ASSIGN(BuilderRecord);
-};
-
-#endif // TOOLS_GN_BUILDER_RECORD_H_
diff --git a/chromium/tools/gn/builder_unittest.cc b/chromium/tools/gn/builder_unittest.cc
deleted file mode 100644
index 3053bca7551..00000000000
--- a/chromium/tools/gn/builder_unittest.cc
+++ /dev/null
@@ -1,248 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/builder.h"
-#include "tools/gn/config.h"
-#include "tools/gn/loader.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scope.h"
-#include "tools/gn/toolchain.h"
-
-namespace gn_builder_unittest {
-
-class MockLoader : public Loader {
- public:
- MockLoader() = default;
-
- // Loader implementation:
- void Load(const SourceFile& file,
- const LocationRange& origin,
- const Label& toolchain_name) override {
- files_.push_back(file);
- }
- void ToolchainLoaded(const Toolchain* toolchain) override {}
- Label GetDefaultToolchain() const override { return Label(); }
- const Settings* GetToolchainSettings(const Label& label) const override {
- return nullptr;
- }
-
- bool HasLoadedNone() const {
- return files_.empty();
- }
-
- // Returns true if one/two loads have been requested and they match the given
- // file(s). This will clear the records so it will be empty for the next call.
- bool HasLoadedOne(const SourceFile& file) {
- if (files_.size() != 1u) {
- files_.clear();
- return false;
- }
- bool match = (files_[0] == file);
- files_.clear();
- return match;
- }
- bool HasLoadedTwo(const SourceFile& a, const SourceFile& b) {
- if (files_.size() != 2u) {
- files_.clear();
- return false;
- }
-
- bool match = (
- (files_[0] == a && files_[1] == b) ||
- (files_[0] == b && files_[1] == a));
- files_.clear();
- return match;
- }
-
- private:
- ~MockLoader() override = default;
-
- std::vector<SourceFile> files_;
-};
-
-class BuilderTest : public testing::Test {
- public:
- BuilderTest()
- : loader_(new MockLoader),
- builder_(loader_.get()),
- settings_(&build_settings_, std::string()),
- scope_(&settings_) {
- build_settings_.SetBuildDir(SourceDir("//out/"));
- settings_.set_toolchain_label(Label(SourceDir("//tc/"), "default"));
- settings_.set_default_toolchain_label(settings_.toolchain_label());
- }
-
- Toolchain* DefineToolchain() {
- Toolchain* tc = new Toolchain(&settings_, settings_.toolchain_label());
- TestWithScope::SetupToolchain(tc);
- builder_.ItemDefined(std::unique_ptr<Item>(tc));
- return tc;
- }
-
- protected:
- scoped_refptr<MockLoader> loader_;
- Builder builder_;
- BuildSettings build_settings_;
- Settings settings_;
- Scope scope_;
-};
-
-TEST_F(BuilderTest, BasicDeps) {
- SourceDir toolchain_dir = settings_.toolchain_label().dir();
- std::string toolchain_name = settings_.toolchain_label().name();
-
- // Construct a dependency chain: A -> B -> C. Define A first with a
- // forward-reference to B, then C, then B to test the different orders that
- // the dependencies are hooked up.
- Label a_label(SourceDir("//a/"), "a", toolchain_dir, toolchain_name);
- Label b_label(SourceDir("//b/"), "b", toolchain_dir, toolchain_name);
- Label c_label(SourceDir("//c/"), "c", toolchain_dir, toolchain_name);
-
- // The builder will take ownership of the pointers.
- Target* a = new Target(&settings_, a_label);
- a->public_deps().push_back(LabelTargetPair(b_label));
- a->set_output_type(Target::EXECUTABLE);
- builder_.ItemDefined(std::unique_ptr<Item>(a));
-
- // Should have requested that B and the toolchain is loaded.
- EXPECT_TRUE(loader_->HasLoadedTwo(SourceFile("//tc/BUILD.gn"),
- SourceFile("//b/BUILD.gn")));
-
- // Define the toolchain.
- DefineToolchain();
- BuilderRecord* toolchain_record =
- builder_.GetRecord(settings_.toolchain_label());
- ASSERT_TRUE(toolchain_record);
- EXPECT_EQ(BuilderRecord::ITEM_TOOLCHAIN, toolchain_record->type());
-
- // A should be unresolved with an item
- BuilderRecord* a_record = builder_.GetRecord(a_label);
- EXPECT_TRUE(a_record->item());
- EXPECT_FALSE(a_record->resolved());
- EXPECT_FALSE(a_record->can_resolve());
-
- // B should be unresolved, have no item, and no deps.
- BuilderRecord* b_record = builder_.GetRecord(b_label);
- EXPECT_FALSE(b_record->item());
- EXPECT_FALSE(b_record->resolved());
- EXPECT_FALSE(b_record->can_resolve());
- EXPECT_TRUE(b_record->all_deps().empty());
-
- // A should have two deps: B and the toolchain. Only B should be unresolved.
- EXPECT_EQ(2u, a_record->all_deps().size());
- EXPECT_EQ(1u, a_record->unresolved_deps().size());
- EXPECT_NE(a_record->all_deps().end(),
- a_record->all_deps().find(toolchain_record));
- EXPECT_NE(a_record->all_deps().end(),
- a_record->all_deps().find(b_record));
- EXPECT_NE(a_record->unresolved_deps().end(),
- a_record->unresolved_deps().find(b_record));
-
- // B should be marked as having A waiting on it.
- EXPECT_EQ(1u, b_record->waiting_on_resolution().size());
- EXPECT_NE(b_record->waiting_on_resolution().end(),
- b_record->waiting_on_resolution().find(a_record));
-
- // Add the C target.
- Target* c = new Target(&settings_, c_label);
- c->set_output_type(Target::STATIC_LIBRARY);
- c->visibility().SetPublic();
- builder_.ItemDefined(std::unique_ptr<Item>(c));
-
- // C only depends on the already-loaded toolchain so we shouldn't have
- // requested anything else.
- EXPECT_TRUE(loader_->HasLoadedNone());
-
- // Add the B target.
- Target* b = new Target(&settings_, b_label);
- a->public_deps().push_back(LabelTargetPair(c_label));
- b->set_output_type(Target::SHARED_LIBRARY);
- b->visibility().SetPublic();
- builder_.ItemDefined(std::unique_ptr<Item>(b));
-
- // B depends only on the already-loaded C and toolchain so we shouldn't have
- // requested anything else.
- EXPECT_TRUE(loader_->HasLoadedNone());
-
- // All targets should now be resolved.
- BuilderRecord* c_record = builder_.GetRecord(c_label);
- EXPECT_TRUE(a_record->resolved());
- EXPECT_TRUE(b_record->resolved());
- EXPECT_TRUE(c_record->resolved());
-
- EXPECT_TRUE(a_record->unresolved_deps().empty());
- EXPECT_TRUE(b_record->unresolved_deps().empty());
- EXPECT_TRUE(c_record->unresolved_deps().empty());
-
- EXPECT_TRUE(a_record->waiting_on_resolution().empty());
- EXPECT_TRUE(b_record->waiting_on_resolution().empty());
- EXPECT_TRUE(c_record->waiting_on_resolution().empty());
-}
-
-// Tests that the "should generate" flag is set and propagated properly.
-TEST_F(BuilderTest, ShouldGenerate) {
- DefineToolchain();
-
- // Define a secondary toolchain.
- Settings settings2(&build_settings_, "secondary/");
- Label toolchain_label2(SourceDir("//tc/"), "secondary");
- settings2.set_toolchain_label(toolchain_label2);
- Toolchain* tc2 = new Toolchain(&settings2, toolchain_label2);
- TestWithScope::SetupToolchain(tc2);
- builder_.ItemDefined(std::unique_ptr<Item>(tc2));
-
- // Construct a dependency chain: A -> B. A is in the default toolchain, B
- // is not.
- Label a_label(SourceDir("//foo/"), "a",
- settings_.toolchain_label().dir(), "a");
- Label b_label(SourceDir("//foo/"), "b",
- toolchain_label2.dir(), toolchain_label2.name());
-
- // First define B.
- Target* b = new Target(&settings2, b_label);
- b->visibility().SetPublic();
- b->set_output_type(Target::EXECUTABLE);
- builder_.ItemDefined(std::unique_ptr<Item>(b));
-
- // B should not be marked generated by default.
- BuilderRecord* b_record = builder_.GetRecord(b_label);
- EXPECT_FALSE(b_record->should_generate());
-
- // Define A with a dependency on B.
- Target* a = new Target(&settings_, a_label);
- a->public_deps().push_back(LabelTargetPair(b_label));
- a->set_output_type(Target::EXECUTABLE);
- builder_.ItemDefined(std::unique_ptr<Item>(a));
-
- // A should have the generate bit set since it's in the default toolchain.
- BuilderRecord* a_record = builder_.GetRecord(a_label);
- EXPECT_TRUE(a_record->should_generate());
-
- // It should have gotten pushed to B.
- EXPECT_TRUE(b_record->should_generate());
-}
-
-// Tests that configs applied to a config get loaded (bug 536844).
-TEST_F(BuilderTest, ConfigLoad) {
- SourceDir toolchain_dir = settings_.toolchain_label().dir();
- std::string toolchain_name = settings_.toolchain_label().name();
-
- // Construct a dependency chain: A -> B -> C. Define A first with a
- // forward-reference to B, then C, then B to test the different orders that
- // the dependencies are hooked up.
- Label a_label(SourceDir("//a/"), "a", toolchain_dir, toolchain_name);
- Label b_label(SourceDir("//b/"), "b", toolchain_dir, toolchain_name);
- Label c_label(SourceDir("//c/"), "c", toolchain_dir, toolchain_name);
-
- // The builder will take ownership of the pointers.
- Config* a = new Config(&settings_, a_label);
- a->configs().push_back(LabelConfigPair(b_label));
- builder_.ItemDefined(std::unique_ptr<Item>(a));
-
- // Should have requested that B is loaded.
- EXPECT_TRUE(loader_->HasLoadedOne(SourceFile("//b/BUILD.gn")));
-}
-
-} // namespace gn_builder_unittest
diff --git a/chromium/tools/gn/bundle_data.cc b/chromium/tools/gn/bundle_data.cc
deleted file mode 100644
index 502769178f8..00000000000
--- a/chromium/tools/gn/bundle_data.cc
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/bundle_data.h"
-
-#include "base/logging.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/label_pattern.h"
-#include "tools/gn/output_file.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/target.h"
-
-namespace {
-
-// Return directory of |path| without the trailing directory separator.
-base::StringPiece FindDirNoTrailingSeparator(base::StringPiece path) {
- base::StringPiece::size_type pos = path.find_last_of("/\\");
- if (pos == base::StringPiece::npos)
- return base::StringPiece();
- return base::StringPiece(path.data(), pos);
-}
-
-bool IsSourceFileFromAssetsCatalog(base::StringPiece source,
- SourceFile* asset_catalog) {
- // Check whether |source| matches one of the following pattern:
- // .*\.xcassets/Contents.json
- // .*\.xcassets/[^/]*\.appiconset/[^/]*
- // .*\.xcassets/[^/]*\.imageset/[^/]*
- // .*\.xcassets/[^/]*\.launchimage/[^/]*
- bool is_file_from_asset_catalog = false;
- base::StringPiece dir = FindDirNoTrailingSeparator(source);
- if (source.ends_with("/Contents.json") && dir.ends_with(".xcassets")) {
- is_file_from_asset_catalog = true;
- } else if (dir.ends_with(".appiconset") || dir.ends_with(".imageset") ||
- dir.ends_with(".launchimage")) {
- dir = FindDirNoTrailingSeparator(dir);
- is_file_from_asset_catalog = dir.ends_with(".xcassets");
- }
- if (is_file_from_asset_catalog && asset_catalog) {
- std::string asset_catalog_path = dir.as_string();
- *asset_catalog = SourceFile(SourceFile::SWAP_IN, &asset_catalog_path);
- }
- return is_file_from_asset_catalog;
-}
-
-} // namespace
-
-BundleData::BundleData() = default;
-
-BundleData::~BundleData() = default;
-
-void BundleData::AddBundleData(const Target* target) {
- DCHECK_EQ(target->output_type(), Target::BUNDLE_DATA);
- for (const auto& pattern : bundle_deps_filter_) {
- if (pattern.Matches(target->label()))
- return;
- }
- bundle_deps_.push_back(target);
-}
-
-void BundleData::OnTargetResolved(Target* owning_target) {
- // Only initialize file_rules_ and assets_catalog_sources for "create_bundle"
- // target (properties are only used by those targets).
- if (owning_target->output_type() != Target::CREATE_BUNDLE)
- return;
-
- UniqueVector<const Target*> assets_catalog_deps;
- UniqueVector<SourceFile> assets_catalog_sources;
-
- for (const Target* target : bundle_deps_) {
- SourceFiles file_rule_sources;
- for (const SourceFile& source_file : target->sources()) {
- SourceFile assets_catalog;
- if (IsSourceFileFromAssetsCatalog(source_file.value(), &assets_catalog)) {
- assets_catalog_sources.push_back(assets_catalog);
- assets_catalog_deps.push_back(target);
- } else {
- file_rule_sources.push_back(source_file);
- }
- }
-
- if (!file_rule_sources.empty()) {
- DCHECK_EQ(target->action_values().outputs().list().size(), 1u);
- file_rules_.push_back(
- BundleFileRule(target, file_rule_sources,
- target->action_values().outputs().list()[0]));
- }
- }
-
- assets_catalog_deps_.insert(assets_catalog_deps_.end(),
- assets_catalog_deps.begin(),
- assets_catalog_deps.end());
- assets_catalog_sources_.insert(assets_catalog_sources_.end(),
- assets_catalog_sources.begin(),
- assets_catalog_sources.end());
-
- GetSourceFiles(&owning_target->sources());
-}
-
-void BundleData::GetSourceFiles(SourceFiles* sources) const {
- for (const BundleFileRule& file_rule : file_rules_) {
- sources->insert(sources->end(), file_rule.sources().begin(),
- file_rule.sources().end());
- }
- sources->insert(sources->end(), assets_catalog_sources_.begin(),
- assets_catalog_sources_.end());
- if (!code_signing_script_.is_null()) {
- sources->insert(sources->end(), code_signing_sources_.begin(),
- code_signing_sources_.end());
- }
-}
-
-void BundleData::GetOutputFiles(const Settings* settings,
- OutputFiles* outputs) const {
- SourceFiles outputs_as_sources;
- GetOutputsAsSourceFiles(settings, &outputs_as_sources);
- for (const SourceFile& source_file : outputs_as_sources)
- outputs->push_back(OutputFile(settings->build_settings(), source_file));
-}
-
-void BundleData::GetOutputsAsSourceFiles(
- const Settings* settings,
- SourceFiles* outputs_as_source) const {
- for (const BundleFileRule& file_rule : file_rules_) {
- for (const SourceFile& source : file_rule.sources()) {
- outputs_as_source->push_back(
- file_rule.ApplyPatternToSource(settings, *this, source));
- }
- }
-
- if (!assets_catalog_sources_.empty())
- outputs_as_source->push_back(GetCompiledAssetCatalogPath());
-
- if (!partial_info_plist_.is_null())
- outputs_as_source->push_back(partial_info_plist_);
-
- if (!code_signing_script_.is_null()) {
- std::vector<SourceFile> code_signing_output_files;
- SubstitutionWriter::GetListAsSourceFiles(code_signing_outputs_,
- &code_signing_output_files);
- outputs_as_source->insert(outputs_as_source->end(),
- code_signing_output_files.begin(),
- code_signing_output_files.end());
- }
-
- if (!root_dir_.is_null())
- outputs_as_source->push_back(GetBundleRootDirOutput(settings));
-}
-
-SourceFile BundleData::GetCompiledAssetCatalogPath() const {
- DCHECK(!assets_catalog_sources_.empty());
- std::string assets_car_path = resources_dir_.value() + "/Assets.car";
- return SourceFile(SourceFile::SWAP_IN, &assets_car_path);
-}
-
-SourceFile BundleData::GetBundleRootDirOutput(const Settings* settings) const {
- std::string root_dir_value = root_dir().value();
- size_t last_separator = root_dir_value.rfind('/');
- if (last_separator != std::string::npos)
- root_dir_value = root_dir_value.substr(0, last_separator);
-
- return SourceFile(SourceFile::SWAP_IN, &root_dir_value);
-}
-
-SourceDir BundleData::GetBundleRootDirOutputAsDir(
- const Settings* settings) const {
- return SourceDir(GetBundleRootDirOutput(settings).value());
-}
diff --git a/chromium/tools/gn/bundle_data.h b/chromium/tools/gn/bundle_data.h
deleted file mode 100644
index 5264b9efae8..00000000000
--- a/chromium/tools/gn/bundle_data.h
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_BUNDLE_DATA_H_
-#define TOOLS_GN_BUNDLE_DATA_H_
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "tools/gn/action_values.h"
-#include "tools/gn/bundle_file_rule.h"
-#include "tools/gn/source_dir.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/substitution_list.h"
-#include "tools/gn/unique_vector.h"
-
-class LabelPattern;
-class OutputFile;
-class Settings;
-class Target;
-
-// BundleData holds the information required by "create_bundle" target.
-class BundleData {
- public:
- using UniqueTargets = UniqueVector<const Target*>;
- using SourceFiles = std::vector<SourceFile>;
- using OutputFiles = std::vector<OutputFile>;
- using BundleFileRules = std::vector<BundleFileRule>;
-
- BundleData();
- ~BundleData();
-
- // Adds a bundle_data target to the recursive collection of all bundle_data
- // that the target depends on.
- void AddBundleData(const Target* target);
-
- // Called upon resolution of the target owning this instance of BundleData.
- // |owning_target| is the owning target.
- void OnTargetResolved(Target* owning_target);
-
- // Returns the list of inputs.
- void GetSourceFiles(SourceFiles* sources) const;
-
- // Returns the list of outputs.
- void GetOutputFiles(const Settings* settings,
- OutputFiles* outputs) const;
-
- // Returns the list of outputs as SourceFile.
- void GetOutputsAsSourceFiles(
- const Settings* settings,
- SourceFiles* outputs_as_source) const;
-
- // Returns the path to the compiled asset catalog. Only valid if
- // assets_catalog_sources() is not empty.
- SourceFile GetCompiledAssetCatalogPath() const;
-
- // Returns the path to the top-level directory of the bundle. This is
- // based on root_dir(), but since that can be Bundle.app/Contents/ or
- // any other subpath, this is just the most top-level directory (e.g.,
- // just Bundle.app/).
- //
- // Note that this is a SourceFile instead of a SourceDir. This is because
- // the output of a create_bundle rule is a single logical unit, even though
- // it is really a directory containing many outputs. This allows other
- // targets to treat the bundle as a single unit, rather than a collection
- // of its contents.
- SourceFile GetBundleRootDirOutput(const Settings* settings) const;
-
- // Performs GetBundleRootDirOutput but returns the result as a directory.
- SourceDir GetBundleRootDirOutputAsDir(const Settings* settings) const;
-
- // Returns the list of inputs for the compilation of the asset catalog.
- SourceFiles& assets_catalog_sources() { return assets_catalog_sources_; }
- const SourceFiles& assets_catalog_sources() const {
- return assets_catalog_sources_;
- }
-
- // Returns the list of dependencies for the compilation of the asset catalog.
- std::vector<const Target*> assets_catalog_deps() const {
- return assets_catalog_deps_;
- }
-
- BundleFileRules& file_rules() { return file_rules_; }
- const BundleFileRules& file_rules() const { return file_rules_; }
-
- SourceDir& root_dir() { return root_dir_; }
- const SourceDir& root_dir() const { return root_dir_; }
-
- SourceDir& contents_dir() { return contents_dir_; }
- const SourceDir& contents_dir() const { return contents_dir_; }
-
- SourceDir& resources_dir() { return resources_dir_; }
- const SourceDir& resources_dir() const { return resources_dir_; }
-
- SourceDir& executable_dir() { return executable_dir_; }
- const SourceDir& executable_dir() const { return executable_dir_; }
-
- SourceDir& plugins_dir() { return plugins_dir_; }
- const SourceDir& plugins_dir() const { return plugins_dir_; }
-
- std::map<std::string, std::string>& xcode_extra_attributes() {
- return xcode_extra_attributes_;
- }
- const std::map<std::string, std::string>& xcode_extra_attributes() const {
- return xcode_extra_attributes_;
- }
-
- std::string& product_type() { return product_type_; }
- const std::string& product_type() const { return product_type_; }
-
- std::string& xcode_test_application_name() {
- return xcode_test_application_name_;
- }
- const std::string& xcode_test_application_name() const {
- return xcode_test_application_name_;
- }
-
- void set_partial_info_plist(const SourceFile& partial_info_plist) {
- partial_info_plist_ = partial_info_plist;
- }
- const SourceFile& partial_info_plist() const { return partial_info_plist_; }
-
- void set_code_signing_script(const SourceFile& script_file) {
- code_signing_script_ = script_file;
- }
- const SourceFile& code_signing_script() const { return code_signing_script_; }
-
- std::vector<SourceFile>& code_signing_sources() {
- return code_signing_sources_;
- }
- const std::vector<SourceFile>& code_signing_sources() const {
- return code_signing_sources_;
- }
-
- SubstitutionList& code_signing_outputs() { return code_signing_outputs_; }
- const SubstitutionList& code_signing_outputs() const {
- return code_signing_outputs_;
- }
-
- SubstitutionList& code_signing_args() { return code_signing_args_; }
- const SubstitutionList& code_signing_args() const {
- return code_signing_args_;
- }
-
- std::vector<LabelPattern>& bundle_deps_filter() {
- return bundle_deps_filter_;
- }
- const std::vector<LabelPattern>& bundle_deps_filter() const {
- return bundle_deps_filter_;
- }
-
- // Recursive collection of all bundle_data that the target depends on.
- const UniqueTargets& bundle_deps() const { return bundle_deps_; }
-
- private:
- SourceFiles assets_catalog_sources_;
- std::vector<const Target*> assets_catalog_deps_;
- BundleFileRules file_rules_;
- UniqueTargets bundle_deps_;
- std::vector<LabelPattern> bundle_deps_filter_;
-
- // All those values are subdirectories relative to root_build_dir, and apart
- // from root_dir_, they are either equal to root_dir_ or subdirectories of it.
- SourceDir root_dir_;
- SourceDir contents_dir_;
- SourceDir resources_dir_;
- SourceDir executable_dir_;
- SourceDir plugins_dir_;
-
- // The specified attributes will append to the build settings of the generated
- // Xcode target.
- std::map<std::string, std::string> xcode_extra_attributes_;
-
- // This is the target type as known to Xcode. This is only used to generate
- // the Xcode project file when using --ide=xcode.
- std::string product_type_;
-
- // Each Xcode unit test or ui test target must have a test application target,
- // and this value corresponds to the target name. This is only used to
- // generate the Xcode project when using --ide=xcode.
- std::string xcode_test_application_name_;
-
- // Path to the partial Info.plist generated by the asset catalog compiler
- // (corresponds to {{bundle_partial_info_plist}} expansion).
- SourceFile partial_info_plist_;
-
- // Holds the values (script name, sources, outputs, script arguments) for the
- // code signing step if defined.
- SourceFile code_signing_script_;
- std::vector<SourceFile> code_signing_sources_;
- SubstitutionList code_signing_outputs_;
- SubstitutionList code_signing_args_;
-
- DISALLOW_COPY_AND_ASSIGN(BundleData);
-};
-
-#endif // TOOLS_GN_BUNDLE_DATA_H_
diff --git a/chromium/tools/gn/bundle_data_target_generator.cc b/chromium/tools/gn/bundle_data_target_generator.cc
deleted file mode 100644
index 32a421a2bb0..00000000000
--- a/chromium/tools/gn/bundle_data_target_generator.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/bundle_data_target_generator.h"
-
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/substitution_type.h"
-#include "tools/gn/target.h"
-#include "tools/gn/value.h"
-#include "tools/gn/variables.h"
-
-BundleDataTargetGenerator::BundleDataTargetGenerator(
- Target* target,
- Scope* scope,
- const FunctionCallNode* function_call,
- Err* err) : TargetGenerator(target, scope, function_call, err) {}
-
-BundleDataTargetGenerator::~BundleDataTargetGenerator() = default;
-
-void BundleDataTargetGenerator::DoRun() {
- target_->set_output_type(Target::BUNDLE_DATA);
-
- if (!FillSources())
- return;
- if (!FillOutputs())
- return;
-
- if (target_->sources().empty()) {
- *err_ = Err(function_call_, "Empty sources for bundle_data target."
- "You have to specify at least one file in the \"sources\".");
- return;
- }
- if (target_->action_values().outputs().list().size() != 1) {
- *err_ = Err(function_call_,
- "Target bundle_data must have exactly one ouput.",
- "You must specify exactly one value in the \"output\" array for the"
- "destination\ninto the generated bundle (see \"gn help bundle_data\"). "
- "If there are multiple\nsources to copy, use source expansion (see "
- "\"gn help source_expansion\").");
- return;
- }
-}
-
-bool BundleDataTargetGenerator::FillOutputs() {
- const Value* value = scope_->GetValue(variables::kOutputs, true);
- if (!value)
- return true;
-
- SubstitutionList& outputs = target_->action_values().outputs();
- if (!outputs.Parse(*value, err_))
- return false;
-
- // Check the substitutions used are valid for this purpose.
- for (SubstitutionType type : outputs.required_types()) {
- if (!IsValidBundleDataSubstitution(type)) {
- *err_ = Err(value->origin(), "Invalid substitution type.",
- "The substitution " + std::string(kSubstitutionNames[type]) +
- " isn't valid for something\n"
- "operating on a bundle_data file such as this.");
- return false;
- }
- }
-
- // Validate that outputs are in the bundle.
- CHECK(outputs.list().size() == value->list_value().size());
- for (size_t i = 0; i < outputs.list().size(); i++) {
- if (!EnsureSubstitutionIsInBundleDir(outputs.list()[i],
- value->list_value()[i]))
- return false;
- }
-
- return true;
-}
-
-bool BundleDataTargetGenerator::EnsureSubstitutionIsInBundleDir(
- const SubstitutionPattern& pattern,
- const Value& original_value) {
- if (pattern.ranges().empty()) {
- // Pattern is empty, error out (this prevents weirdness below).
- *err_ = Err(original_value, "This has an empty value in it.");
- return false;
- }
-
- if (SubstitutionIsInBundleDir(pattern.ranges()[0].type))
- return true;
-
- *err_ = Err(original_value,
- "File is not inside bundle directory.",
- "The given file should be in the output directory. Normally you\n"
- "would specify {{bundle_resources_dir}} or such substitution.");
- return false;
-}
diff --git a/chromium/tools/gn/bundle_data_target_generator.h b/chromium/tools/gn/bundle_data_target_generator.h
deleted file mode 100644
index 49bcc45249f..00000000000
--- a/chromium/tools/gn/bundle_data_target_generator.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_BUNDLE_DATA_TARGET_GENERATOR_H_
-#define TOOLS_GN_BUNDLE_DATA_TARGET_GENERATOR_H_
-
-#include "base/macros.h"
-#include "tools/gn/target_generator.h"
-
-// Populates a Target with the values from a bundle_data rule.
-class BundleDataTargetGenerator : public TargetGenerator {
- public:
- BundleDataTargetGenerator(Target* target,
- Scope* scope,
- const FunctionCallNode* function_call,
- Err* err);
- ~BundleDataTargetGenerator() override;
-
- protected:
- void DoRun() override;
-
- private:
- bool FillOutputs();
-
- bool EnsureSubstitutionIsInBundleDir(
- const SubstitutionPattern& pattern,
- const Value& original_value);
-
- DISALLOW_COPY_AND_ASSIGN(BundleDataTargetGenerator);
-};
-
-#endif // TOOLS_GN_BUNDLE_DATA_TARGET_GENERATOR_H_
diff --git a/chromium/tools/gn/bundle_file_rule.cc b/chromium/tools/gn/bundle_file_rule.cc
deleted file mode 100644
index 4d4ca3a34eb..00000000000
--- a/chromium/tools/gn/bundle_file_rule.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/bundle_file_rule.h"
-
-#include "tools/gn/output_file.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/substitution_pattern.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/target.h"
-
-BundleFileRule::BundleFileRule(const Target* bundle_data_target,
- const std::vector<SourceFile> sources,
- const SubstitutionPattern& pattern)
- : target_(bundle_data_target), sources_(sources), pattern_(pattern) {
- // target_ may be null during testing.
- DCHECK(!target_ || target_->output_type() == Target::BUNDLE_DATA);
-}
-
-BundleFileRule::BundleFileRule(const BundleFileRule& other) = default;
-
-BundleFileRule::~BundleFileRule() = default;
-
-SourceFile BundleFileRule::ApplyPatternToSource(
- const Settings* settings,
- const BundleData& bundle_data,
- const SourceFile& source_file) const {
- std::string output_path;
- for (const auto& subrange : pattern_.ranges()) {
- switch (subrange.type) {
- case SUBSTITUTION_LITERAL:
- output_path.append(subrange.literal);
- break;
- case SUBSTITUTION_BUNDLE_ROOT_DIR:
- output_path.append(bundle_data.root_dir().value());
- break;
- case SUBSTITUTION_BUNDLE_CONTENTS_DIR:
- output_path.append(bundle_data.contents_dir().value());
- break;
- case SUBSTITUTION_BUNDLE_RESOURCES_DIR:
- output_path.append(bundle_data.resources_dir().value());
- break;
- case SUBSTITUTION_BUNDLE_EXECUTABLE_DIR:
- output_path.append(bundle_data.executable_dir().value());
- break;
- case SUBSTITUTION_BUNDLE_PLUGINS_DIR:
- output_path.append(bundle_data.plugins_dir().value());
- break;
- default:
- output_path.append(SubstitutionWriter::GetSourceSubstitution(
- target_, target_->settings(), source_file, subrange.type,
- SubstitutionWriter::OUTPUT_ABSOLUTE, SourceDir()));
- break;
- }
- }
- return SourceFile(SourceFile::SWAP_IN, &output_path);
-}
-
-OutputFile BundleFileRule::ApplyPatternToSourceAsOutputFile(
- const Settings* settings,
- const BundleData& bundle_data,
- const SourceFile& source_file) const {
- return OutputFile(settings->build_settings(),
- ApplyPatternToSource(settings, bundle_data, source_file));
-}
diff --git a/chromium/tools/gn/bundle_file_rule.h b/chromium/tools/gn/bundle_file_rule.h
deleted file mode 100644
index 372e62802c7..00000000000
--- a/chromium/tools/gn/bundle_file_rule.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_BUNDLE_FILE_RULE_H_
-#define TOOLS_GN_BUNDLE_FILE_RULE_H_
-
-#include <vector>
-
-#include "tools/gn/source_file.h"
-#include "tools/gn/substitution_pattern.h"
-
-class BundleData;
-class Settings;
-class SourceFile;
-class Target;
-class OutputFile;
-
-// BundleFileRule contains the information found in a "bundle_data" target.
-class BundleFileRule {
- public:
- BundleFileRule(const Target* bundle_data_target,
- const std::vector<SourceFile> sources,
- const SubstitutionPattern& pattern);
- BundleFileRule(const BundleFileRule& other);
- ~BundleFileRule();
-
- // Applies the substitution pattern to a source file, returning the result
- // as either a SourceFile or an OutputFile.
- SourceFile ApplyPatternToSource(const Settings* settings,
- const BundleData& bundle_data,
- const SourceFile& source_file) const;
- OutputFile ApplyPatternToSourceAsOutputFile(
- const Settings* settings,
- const BundleData& bundle_data,
- const SourceFile& source_file) const;
-
- // Returns the associated target (of type Target::BUNDLE_DATA). May be
- // null during testing.
- const Target* target() const { return target_; }
-
- // Returns the list of SourceFiles.
- const std::vector<SourceFile>& sources() const { return sources_; }
-
- private:
- const Target* target_;
- std::vector<SourceFile> sources_;
- SubstitutionPattern pattern_;
-};
-
-#endif // TOOLS_GN_BUNDLE_FILE_RULE_H_
diff --git a/chromium/tools/gn/c_include_iterator.cc b/chromium/tools/gn/c_include_iterator.cc
deleted file mode 100644
index 29ead0b4662..00000000000
--- a/chromium/tools/gn/c_include_iterator.cc
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/c_include_iterator.h"
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/string_util.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/location.h"
-
-namespace {
-
-enum IncludeType {
- INCLUDE_NONE,
- INCLUDE_SYSTEM, // #include <...>
- INCLUDE_USER // #include "..."
-};
-
-// Returns a new string piece referencing the same buffer as the argument, but
-// with leading space trimmed. This only checks for space and tab characters
-// since we're dealing with lines in C source files.
-base::StringPiece TrimLeadingWhitespace(const base::StringPiece& str) {
- size_t new_begin = 0;
- while (new_begin < str.size() &&
- (str[new_begin] == ' ' || str[new_begin] == '\t'))
- new_begin++;
- return str.substr(new_begin);
-}
-
-// We don't want to count comment lines and preprocessor lines toward our
-// "max lines to look at before giving up" since the beginnings of some files
-// may have a lot of comments.
-//
-// We only handle C-style "//" comments since this is the normal commenting
-// style used in Chrome, and do so pretty stupidly. We don't want to write a
-// full C++ parser here, we're just trying to get a good heuristic for checking
-// the file.
-//
-// We assume the line has leading whitespace trimmed. We also assume that empty
-// lines have already been filtered out.
-bool ShouldCountTowardNonIncludeLines(const base::StringPiece& line) {
- if (base::StartsWith(line, "//", base::CompareCase::SENSITIVE))
- return false; // Don't count comments.
- if (base::StartsWith(line, "/*", base::CompareCase::SENSITIVE) ||
- base::StartsWith(line, " *", base::CompareCase::SENSITIVE))
- return false; // C-style comment blocks with stars along the left side.
- if (base::StartsWith(line, "#", base::CompareCase::SENSITIVE))
- return false; // Don't count preprocessor.
- if (base::ContainsOnlyChars(line, base::kWhitespaceASCII))
- return false; // Don't count whitespace lines.
- return true; // Count everything else.
-}
-
-// Given a line, checks to see if it looks like an include or import and
-// extract the path. The type of include is returned. Returns INCLUDE_NONE on
-// error or if this is not an include line.
-//
-// The 1-based character number on the line that the include was found at
-// will be filled into *begin_char.
-IncludeType ExtractInclude(const base::StringPiece& line,
- base::StringPiece* path,
- int* begin_char) {
- static const char kInclude[] = "#include";
- static const size_t kIncludeLen = arraysize(kInclude) - 1; // No null.
- static const char kImport[] = "#import";
- static const size_t kImportLen = arraysize(kImport) - 1; // No null.
-
- base::StringPiece trimmed = TrimLeadingWhitespace(line);
- if (trimmed.empty())
- return INCLUDE_NONE;
-
- base::StringPiece contents;
- if (base::StartsWith(trimmed, base::StringPiece(kInclude, kIncludeLen),
- base::CompareCase::SENSITIVE))
- contents = TrimLeadingWhitespace(trimmed.substr(kIncludeLen));
- else if (base::StartsWith(trimmed, base::StringPiece(kImport, kImportLen),
- base::CompareCase::SENSITIVE))
- contents = TrimLeadingWhitespace(trimmed.substr(kImportLen));
-
- if (contents.empty())
- return INCLUDE_NONE;
-
- IncludeType type = INCLUDE_NONE;
- char terminating_char = 0;
- if (contents[0] == '"') {
- type = INCLUDE_USER;
- terminating_char = '"';
- } else if (contents[0] == '<') {
- type = INCLUDE_SYSTEM;
- terminating_char = '>';
- } else {
- return INCLUDE_NONE;
- }
-
- // Count everything to next "/> as the contents.
- size_t terminator_index = contents.find(terminating_char, 1);
- if (terminator_index == base::StringPiece::npos)
- return INCLUDE_NONE;
-
- *path = contents.substr(1, terminator_index - 1);
- // Note: one based so we do "+ 1".
- *begin_char = static_cast<int>(path->data() - line.data()) + 1;
- return type;
-}
-
-// Returns true if this line has a "nogncheck" comment associated with it.
-bool HasNoCheckAnnotation(const base::StringPiece& line) {
- return line.find("nogncheck") != base::StringPiece::npos;
-}
-
-} // namespace
-
-const int CIncludeIterator::kMaxNonIncludeLines = 10;
-
-CIncludeIterator::CIncludeIterator(const InputFile* input)
- : input_file_(input),
- file_(input->contents()),
- offset_(0),
- line_number_(0),
- lines_since_last_include_(0) {
-}
-
-CIncludeIterator::~CIncludeIterator() = default;
-
-bool CIncludeIterator::GetNextIncludeString(base::StringPiece* out,
- LocationRange* location) {
- base::StringPiece line;
- int cur_line_number = 0;
- while (lines_since_last_include_ <= kMaxNonIncludeLines &&
- GetNextLine(&line, &cur_line_number)) {
- base::StringPiece include_contents;
- int begin_char;
- IncludeType type = ExtractInclude(line, &include_contents, &begin_char);
- if (type == INCLUDE_USER && !HasNoCheckAnnotation(line)) {
- // Only count user includes for now.
- *out = include_contents;
- *location = LocationRange(
- Location(input_file_,
- cur_line_number,
- begin_char,
- -1 /* TODO(scottmg): Is this important? */),
- Location(input_file_,
- cur_line_number,
- begin_char + static_cast<int>(include_contents.size()),
- -1 /* TODO(scottmg): Is this important? */));
-
- lines_since_last_include_ = 0;
- return true;
- }
-
- if (ShouldCountTowardNonIncludeLines(line))
- lines_since_last_include_++;
- }
- return false;
-}
-
-bool CIncludeIterator::GetNextLine(base::StringPiece* line, int* line_number) {
- if (offset_ == file_.size())
- return false;
-
- size_t begin = offset_;
- while (offset_ < file_.size() && file_[offset_] != '\n')
- offset_++;
- line_number_++;
-
- *line = file_.substr(begin, offset_ - begin);
- *line_number = line_number_;
-
- // If we didn't hit EOF, skip past the newline for the next one.
- if (offset_ < file_.size())
- offset_++;
- return true;
-}
diff --git a/chromium/tools/gn/c_include_iterator.h b/chromium/tools/gn/c_include_iterator.h
deleted file mode 100644
index e81a60c9383..00000000000
--- a/chromium/tools/gn/c_include_iterator.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_C_INCLUDE_ITERATOR_H_
-#define TOOLS_GN_C_INCLUDE_ITERATOR_H_
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-
-class InputFile;
-class LocationRange;
-
-// Iterates through #includes in C source and header files.
-//
-// This only returns includes we want to check, which is user includes with
-// double-quotes: #include "..."
-class CIncludeIterator {
- public:
- // The InputFile pointed to must outlive this class.
- explicit CIncludeIterator(const InputFile* input);
- ~CIncludeIterator();
-
- // Fills in the string with the contents of the next include, and the
- // location with where it came from, and returns true, or returns false if
- // there are no more includes.
- bool GetNextIncludeString(base::StringPiece* out, LocationRange* location);
-
- // Maximum numbef of non-includes we'll tolerate before giving up. This does
- // not count comments or preprocessor.
- static const int kMaxNonIncludeLines;
-
- private:
- // Returns false on EOF, otherwise fills in the given line and the one-based
- // line number into *line_number;
- bool GetNextLine(base::StringPiece* line, int* line_number);
-
- const InputFile* input_file_;
-
- // This just points into input_file_.contents() for convenience.
- base::StringPiece file_;
-
- // 0-based offset into the file.
- size_t offset_;
-
- int line_number_; // One-based. Indicates the last line we read.
-
- // Number of lines we've processed since seeing the last include (or the
- // beginning of the file) with some exceptions.
- int lines_since_last_include_;
-
- DISALLOW_COPY_AND_ASSIGN(CIncludeIterator);
-};
-
-#endif // TOOLS_GN_C_INCLUDE_ITERATOR_H_
diff --git a/chromium/tools/gn/c_include_iterator_unittest.cc b/chromium/tools/gn/c_include_iterator_unittest.cc
deleted file mode 100644
index a4278b21200..00000000000
--- a/chromium/tools/gn/c_include_iterator_unittest.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/c_include_iterator.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/location.h"
-
-namespace {
-
-bool RangeIs(const LocationRange& range,
- int line, int begin_char, int end_char) {
- return range.begin().line_number() == line &&
- range.end().line_number() == line &&
- range.begin().column_number() == begin_char &&
- range.end().column_number() == end_char;
-}
-
-} // namespace
-
-TEST(CIncludeIterator, Basic) {
- std::string buffer;
- buffer.append("// Some comment\n");
- buffer.append("\n");
- buffer.append("#include \"foo/bar.h\"\n");
- buffer.append("\n");
- buffer.append("#include <stdio.h>\n");
- buffer.append("\n");
- buffer.append(" #include \"foo/baz.h\"\n"); // Leading whitespace
- buffer.append("#include \"la/deda.h\"\n");
- // Line annotated with "// nogncheck"
- buffer.append("#include \"should_be_skipped.h\" // nogncheck\n");
- buffer.append("#import \"weird_mac_import.h\"\n");
- buffer.append("\n");
- buffer.append("void SomeCode() {\n");
-
- InputFile file(SourceFile("//foo.cc"));
- file.SetContents(buffer);
-
- CIncludeIterator iter(&file);
-
- base::StringPiece contents;
- LocationRange range;
- EXPECT_TRUE(iter.GetNextIncludeString(&contents, &range));
- EXPECT_EQ("foo/bar.h", contents);
- EXPECT_TRUE(RangeIs(range, 3, 11, 20)) << range.begin().Describe(true);
-
- EXPECT_TRUE(iter.GetNextIncludeString(&contents, &range));
- EXPECT_EQ("foo/baz.h", contents);
- EXPECT_TRUE(RangeIs(range, 7, 12, 21)) << range.begin().Describe(true);
-
- EXPECT_TRUE(iter.GetNextIncludeString(&contents, &range));
- EXPECT_EQ("la/deda.h", contents);
- EXPECT_TRUE(RangeIs(range, 8, 11, 20)) << range.begin().Describe(true);
-
- // The line annotated with "nogncheck" should be skipped.
-
- EXPECT_TRUE(iter.GetNextIncludeString(&contents, &range));
- EXPECT_EQ("weird_mac_import.h", contents);
- EXPECT_TRUE(RangeIs(range, 10, 10, 28)) << range.begin().Describe(true);
-
- EXPECT_FALSE(iter.GetNextIncludeString(&contents, &range));
-}
-
-// Tests that we don't search for includes indefinitely.
-TEST(CIncludeIterator, GiveUp) {
- std::string buffer;
- for (size_t i = 0; i < 1000; i++)
- buffer.append("x\n");
- buffer.append("#include \"foo/bar.h\"\n");
-
- InputFile file(SourceFile("//foo.cc"));
- file.SetContents(buffer);
-
- base::StringPiece contents;
- LocationRange range;
-
- CIncludeIterator iter(&file);
- EXPECT_FALSE(iter.GetNextIncludeString(&contents, &range));
- EXPECT_TRUE(contents.empty());
-}
-
-// Don't count blank lines, comments, and preprocessor when giving up.
-TEST(CIncludeIterator, DontGiveUp) {
- std::string buffer;
- for (size_t i = 0; i < 1000; i++)
- buffer.push_back('\n');
- for (size_t i = 0; i < 1000; i++)
- buffer.append("// comment\n");
- for (size_t i = 0; i < 1000; i++)
- buffer.append("#preproc\n");
- buffer.append("#include \"foo/bar.h\"\n");
-
- InputFile file(SourceFile("//foo.cc"));
- file.SetContents(buffer);
-
- base::StringPiece contents;
- LocationRange range;
-
- CIncludeIterator iter(&file);
- EXPECT_TRUE(iter.GetNextIncludeString(&contents, &range));
- EXPECT_EQ("foo/bar.h", contents);
-}
-
-// Tests that we'll tolerate some small numbers of non-includes interspersed
-// with real includes.
-TEST(CIncludeIterator, TolerateNonIncludes) {
- const size_t kSkip = CIncludeIterator::kMaxNonIncludeLines - 2;
- const size_t kGroupCount = 100;
-
- std::string include("foo/bar.h");
-
- // Allow a series of includes with blanks in between.
- std::string buffer;
- for (size_t group = 0; group < kGroupCount; group++) {
- for (size_t i = 0; i < kSkip; i++)
- buffer.append("foo\n");
- buffer.append("#include \"" + include + "\"\n");
- }
-
- InputFile file(SourceFile("//foo.cc"));
- file.SetContents(buffer);
-
- base::StringPiece contents;
- LocationRange range;
-
- CIncludeIterator iter(&file);
- for (size_t group = 0; group < kGroupCount; group++) {
- EXPECT_TRUE(iter.GetNextIncludeString(&contents, &range));
- EXPECT_EQ(include, contents.as_string());
- }
- EXPECT_FALSE(iter.GetNextIncludeString(&contents, &range));
-}
-
-// Tests that comments of the form
-// /*
-// *
-// */
-// are not counted toward the non-include line count.
-TEST(CIncludeIterator, CStyleComments) {
- std::string buffer("/*");
- for (size_t i = 0; i < 1000; i++)
- buffer.append(" *\n");
- buffer.append(" */\n\n");
- buffer.append("#include \"foo/bar.h\"\n");
-
- InputFile file(SourceFile("//foo.cc"));
- file.SetContents(buffer);
-
- base::StringPiece contents;
- LocationRange range;
-
- CIncludeIterator iter(&file);
- EXPECT_TRUE(iter.GetNextIncludeString(&contents, &range));
- EXPECT_EQ("foo/bar.h", contents);
-}
diff --git a/chromium/tools/gn/command_analyze.cc b/chromium/tools/gn/command_analyze.cc
deleted file mode 100644
index 9aa698b3c15..00000000000
--- a/chromium/tools/gn/command_analyze.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <iterator>
-#include <set>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "tools/gn/analyzer.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/location.h"
-#include "tools/gn/setup.h"
-
-namespace commands {
-
-const char kAnalyze[] = "analyze";
-const char kAnalyze_HelpShort[] =
- "analyze: Analyze which targets are affected by a list of files.";
-const char kAnalyze_Help[] =
- R"(gn analyze <out_dir> <input_path> <output_path>
-
- Analyze which targets are affected by a list of files.
-
- This command takes three arguments:
-
- out_dir is the path to the build directory.
-
- input_path is a path to a file containing a JSON object with three fields:
-
- - "files": A list of the filenames to check.
-
- - "test_targets": A list of the labels for targets that are needed to run
- the tests we wish to run.
-
- - "additional_compile_targets": A list of the labels for targets that we
- wish to rebuild, but aren't necessarily needed for testing. The important
- difference between this field and "test_targets" is that if an item in
- the additional_compile_targets list refers to a group, then any
- dependencies of that group will be returned if they are out of date, but
- the group itself does not need to be. If the dependencies themselves are
- groups, the same filtering is repeated. This filtering can be used to
- avoid rebuilding dependencies of a group that are unaffected by the input
- files. The list may also contain the string "all" to refer to a
- pseudo-group that contains every root target in the build graph.
-
- This filtering behavior is also known as "pruning" the list of compile
- targets.
-
- output_path is a path indicating where the results of the command are to be
- written. The results will be a file containing a JSON object with one or more
- of following fields:
-
- - "compile_targets": A list of the labels derived from the input
- compile_targets list that are affected by the input files. Due to the way
- the filtering works for compile targets as described above, this list may
- contain targets that do not appear in the input list.
-
- - "test_targets": A list of the labels from the input test_targets list that
- are affected by the input files. This list will be a proper subset of the
- input list.
-
- - "invalid_targets": A list of any names from the input that do not exist in
- the build graph. If this list is non-empty, the "error" field will also be
- set to "Invalid targets".
-
- - "status": A string containing one of three values:
-
- - "Found dependency"
- - "No dependency"
- - "Found dependency (all) "
-
- In the first case, the lists returned in compile_targets and test_targets
- should be passed to ninja to build. In the second case, nothing was
- affected and no build is necessary. In the third case, GN could not
- determine the correct answer and returned the input as the output in order
- to be safe.
-
- - "error": This will only be present if an error occurred, and will contain
- a string describing the error. This includes cases where the input file is
- not in the right format, or contains invalid targets.
-
- The command returns 1 if it is unable to read the input file or write the
- output file, or if there is something wrong with the build such that gen
- would also fail, and 0 otherwise. In particular, it returns 0 even if the
- "error" key is non-empty and a non-fatal error occurred. In other words, it
- tries really hard to always write something to the output JSON and convey
- errors that way rather than via return codes.
-)";
-
-int RunAnalyze(const std::vector<std::string>& args) {
- if (args.size() != 3) {
- Err(Location(), "You're holding it wrong.",
- "Usage: \"gn analyze <out_dir> <input_path> <output_path>")
- .PrintToStdout();
- return 1;
- }
-
- std::string input;
- bool ret = base::ReadFileToString(UTF8ToFilePath(args[1]), &input);
- if (!ret) {
- Err(Location(), "Input file " + args[1] + " not found.").PrintToStdout();
- return 1;
- }
-
- Setup* setup = new Setup;
- if (!setup->DoSetup(args[0], false) || !setup->Run())
- return 1;
-
- Err err;
- Analyzer analyzer(
- setup->builder(), setup->build_settings().build_config_file(),
- setup->GetDotFile(),
- setup->build_settings().build_args().build_args_dependency_files());
- std::string output = analyzer.Analyze(input, &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return 1;
- }
-
- WriteFile(UTF8ToFilePath(args[2]), output, &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return 1;
- }
-
- return 0;
-}
-
-} // namespace commands
diff --git a/chromium/tools/gn/command_args.cc b/chromium/tools/gn/command_args.cc
deleted file mode 100644
index 9fbf67bd7f7..00000000000
--- a/chromium/tools/gn/command_args.cc
+++ /dev/null
@@ -1,505 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <map>
-
-#include "base/command_line.h"
-#include "base/environment.h"
-#include "base/files/file_util.h"
-#include "base/json/json_writer.h"
-#include "base/process/launch.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "build/build_config.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/setup.h"
-#include "tools/gn/standard_out.h"
-#include "tools/gn/tokenizer.h"
-#include "tools/gn/trace.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#include <shellapi.h>
-#endif
-
-namespace commands {
-
-namespace {
-
-const char kSwitchList[] = "list";
-const char kSwitchShort[] = "short";
-const char kSwitchOverridesOnly[] = "overrides-only";
-const char kSwitchJson[] = "json";
-
-bool DoesLineBeginWithComment(const base::StringPiece& line) {
- // Skip whitespace.
- size_t i = 0;
- while (i < line.size() && base::IsAsciiWhitespace(line[i]))
- i++;
-
- return i < line.size() && line[i] == '#';
-}
-
-// Returns the offset of the beginning of the line identified by |offset|.
-size_t BackUpToLineBegin(const std::string& data, size_t offset) {
- // Degenerate case of an empty line. Below we'll try to return the
- // character after the newline, but that will be incorrect in this case.
- if (offset == 0 || Tokenizer::IsNewline(data, offset))
- return offset;
-
- size_t cur = offset;
- do {
- cur--;
- if (Tokenizer::IsNewline(data, cur))
- return cur + 1; // Want the first character *after* the newline.
- } while (cur > 0);
- return 0;
-}
-
-// Assumes DoesLineBeginWithComment(), this strips the # character from the
-// beginning and normalizes preceding whitespace.
-std::string StripHashFromLine(const base::StringPiece& line, bool pad) {
- // Replace the # sign and everything before it with 3 spaces, so that a
- // normal comment that has a space after the # will be indented 4 spaces
- // (which makes our formatting come out nicely). If the comment is indented
- // from there, we want to preserve that indenting.
- if (pad)
- return " " + line.substr(line.find('#') + 1).as_string();
- return line.substr(line.find('#') + 1).as_string();
-}
-
-// Tries to find the comment before the setting of the given value.
-void GetContextForValue(const Value& value,
- std::string* location_str,
- int* line_no,
- std::string* comment,
- bool pad_comment=true) {
- Location location = value.origin()->GetRange().begin();
- const InputFile* file = location.file();
- if (!file)
- return;
-
- *location_str = file->name().value();
- *line_no = location.line_number();
-
- const std::string& data = file->contents();
- size_t line_off =
- Tokenizer::ByteOffsetOfNthLine(data, location.line_number());
-
- while (line_off > 1) {
- line_off -= 2; // Back up to end of previous line.
- size_t previous_line_offset = BackUpToLineBegin(data, line_off);
-
- base::StringPiece line(&data[previous_line_offset],
- line_off - previous_line_offset + 1);
- if (!DoesLineBeginWithComment(line))
- break;
-
- comment->insert(0, StripHashFromLine(line, pad_comment) + "\n");
- line_off = previous_line_offset;
- }
-}
-
-// Prints the value and origin for a default value. Default values always list
-// an origin and if there is no origin, print a message about it being
-// internally set. Overrides can't be internally set so the location handling
-// is a bit different.
-//
-// The default value also contains the docstring.
-void PrintDefaultValueInfo(base::StringPiece name, const Value& value) {
- OutputString(value.ToString(true) + "\n");
- if (value.origin()) {
- int line_no;
- std::string location, comment;
- GetContextForValue(value, &location, &line_no, &comment);
- OutputString(" From " + location + ":" + base::IntToString(line_no) +
- "\n");
- if (!comment.empty())
- OutputString("\n" + comment);
- } else {
- OutputString(" (Internally set; try `gn help " + name.as_string() +
- "`.)\n");
- }
-}
-
-// Override value is null if there is no override.
-void PrintArgHelp(const base::StringPiece& name,
- const Args::ValueWithOverride& val) {
- OutputString(name.as_string(), DECORATION_YELLOW);
- OutputString("\n");
-
- if (val.has_override) {
- // Override present, print both it and the default.
- OutputString(" Current value = " + val.override_value.ToString(true) +
- "\n");
- if (val.override_value.origin()) {
- int line_no;
- std::string location, comment;
- GetContextForValue(val.override_value, &location, &line_no, &comment);
- OutputString(" From " + location + ":" + base::IntToString(line_no)
- + "\n");
- }
- OutputString(" Overridden from the default = ");
- PrintDefaultValueInfo(name, val.default_value);
- } else {
- // No override.
- OutputString(" Current value (from the default) = ");
- PrintDefaultValueInfo(name, val.default_value);
- }
-}
-
-void BuildArgJson(base::Value& dict,
- const base::StringPiece& name,
- const Args::ValueWithOverride& arg,
- bool short_only) {
- assert(dict.is_dict());
-
- // Fetch argument name.
- dict.SetKey("name", base::Value(name));
-
- // Fetch overridden value inforrmation (if present).
- if (arg.has_override) {
- base::DictionaryValue override_dict;
- override_dict.SetKey("value",
- base::Value(arg.override_value.ToString(true)));
- if (arg.override_value.origin() && !short_only) {
- int line_no;
- std::string location, comment;
- GetContextForValue(arg.override_value, &location, &line_no, &comment,
- /*pad_comment=*/false);
- // Omit file and line if set with --args (i.e. no file)
- if (!location.empty()) {
- override_dict.SetKey("file", base::Value(location));
- override_dict.SetKey("line", base::Value(line_no));
- }
- }
- dict.SetKey("current", std::move(override_dict));
- }
-
- // Fetch default value information, and comment (if present).
- base::DictionaryValue default_dict;
- std::string comment;
- default_dict.SetKey("value", base::Value(arg.default_value.ToString(true)));
- if (arg.default_value.origin() && !short_only) {
- int line_no;
- std::string location;
- GetContextForValue(arg.default_value, &location, &line_no, &comment,
- /*pad_comment=*/false);
- // Only emit file and line if the value is overridden.
- if (arg.has_override) {
- default_dict.SetKey("file", base::Value(location));
- default_dict.SetKey("line", base::Value(line_no));
- }
- }
- dict.SetKey("default", std::move(default_dict));
- if (!comment.empty() && !short_only)
- dict.SetKey("comment", base::Value(comment));
-}
-
-int ListArgs(const std::string& build_dir) {
- Setup* setup = new Setup;
- if (!setup->DoSetup(build_dir, false) || !setup->Run())
- return 1;
-
- Args::ValueWithOverrideMap args =
- setup->build_settings().build_args().GetAllArguments();
- std::string list_value =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kSwitchList);
- if (!list_value.empty()) {
- // List just the one specified as the parameter to --list.
- auto found = args.find(list_value);
- if (found == args.end()) {
- Err(Location(), "Unknown build argument.",
- "You asked for \"" + list_value + "\" which I didn't find in any "
- "build file\nassociated with this build.").PrintToStdout();
- return 1;
- }
-
- // Delete everything from the map except the one requested.
- Args::ValueWithOverrideMap::value_type preserved = *found;
- args.clear();
- args.insert(preserved);
- }
-
- // Cache this to avoid looking it up for each |arg| in the loops below.
- const bool overrides_only =
- base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchOverridesOnly);
- const bool short_only =
- base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchShort);
-
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchJson)) {
- // Convert all args to JSON, serialize and print them
- auto list = std::make_unique<base::ListValue>();
- for (const auto& arg : args) {
- if (overrides_only && !arg.second.has_override)
- continue;
- list->GetList().emplace_back(base::DictionaryValue());
- BuildArgJson(list->GetList().back(), arg.first, arg.second, short_only);
- }
- std::string s;
- base::JSONWriter::WriteWithOptions(
- *list.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &s);
- OutputString(s);
- return 0;
- }
-
- if (short_only) {
- // Short <key>=<current_value> output.
- for (const auto& arg : args) {
- if (overrides_only && !arg.second.has_override)
- continue;
- OutputString(arg.first.as_string());
- OutputString(" = ");
- if (arg.second.has_override)
- OutputString(arg.second.override_value.ToString(true));
- else
- OutputString(arg.second.default_value.ToString(true));
- OutputString("\n");
- }
- return 0;
- }
-
- // Long output.
- for (const auto& arg : args) {
- if (overrides_only && !arg.second.has_override)
- continue;
- PrintArgHelp(arg.first, arg.second);
- OutputString("\n");
- }
-
- return 0;
-}
-
-#if defined(OS_WIN)
-
-bool RunEditor(const base::FilePath& file_to_edit) {
- SHELLEXECUTEINFO info;
- memset(&info, 0, sizeof(info));
- info.cbSize = sizeof(info);
- info.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_CLASSNAME;
- info.lpFile = file_to_edit.value().c_str();
- info.nShow = SW_SHOW;
- info.lpClass = L".txt";
- if (!::ShellExecuteEx(&info)) {
- Err(Location(), "Couldn't run editor.",
- "Just edit \"" + FilePathToUTF8(file_to_edit) +
- "\" manually instead.").PrintToStdout();
- return false;
- }
-
- if (!info.hProcess) {
- // Windows re-used an existing process.
- OutputString("\"" + FilePathToUTF8(file_to_edit) +
- "\" opened in editor, save it and press <Enter> when done.\n");
- getchar();
- } else {
- OutputString("Waiting for editor on \"" + FilePathToUTF8(file_to_edit) +
- "\"...\n");
- ::WaitForSingleObject(info.hProcess, INFINITE);
- ::CloseHandle(info.hProcess);
- }
- return true;
-}
-
-#else // POSIX
-
-bool RunEditor(const base::FilePath& file_to_edit) {
- const char* editor_ptr = getenv("GN_EDITOR");
- if (!editor_ptr)
- editor_ptr = getenv("VISUAL");
- if (!editor_ptr)
- editor_ptr = getenv("EDITOR");
- if (!editor_ptr)
- editor_ptr = "vi";
-
- std::string cmd(editor_ptr);
- cmd.append(" \"");
-
- // Its impossible to do this properly since we don't know the user's shell,
- // but quoting and escaping internal quotes should handle 99.999% of all
- // cases.
- std::string escaped_name = file_to_edit.value();
- base::ReplaceSubstringsAfterOffset(&escaped_name, 0, "\"", "\\\"");
- cmd.append(escaped_name);
- cmd.push_back('"');
-
- OutputString("Waiting for editor on \"" + file_to_edit.value() +
- "\"...\n");
- return system(cmd.c_str()) == 0;
-}
-
-#endif
-
-int EditArgsFile(const std::string& build_dir) {
- {
- // Scope the setup. We only use it for some basic state. We'll do the
- // "real" build below in the gen command.
- Setup setup;
- // Don't fill build arguments. We're about to edit the file which supplies
- // these in the first place.
- setup.set_fill_arguments(false);
- if (!setup.DoSetup(build_dir, true))
- return 1;
-
- // Ensure the file exists. Need to normalize path separators since on
- // Windows they can come out as forward slashes here, and that confuses some
- // of the commands.
- BuildSettings build_settings = setup.build_settings();
- base::FilePath arg_file =
- build_settings.GetFullPath(setup.GetBuildArgFile())
- .NormalizePathSeparators();
- if (!base::PathExists(arg_file)) {
- std::string argfile_default_contents =
- "# Build arguments go here.\n"
- "# See \"gn args <out_dir> --list\" for available build "
- "arguments.\n";
-
- SourceFile template_path = build_settings.arg_file_template_path();
- if (!template_path.is_null()) {
- base::FilePath full_path =
- build_settings.GetFullPath(template_path).NormalizePathSeparators();
- if (!base::PathExists(full_path)) {
- Err err =
- Err(Location(), std::string("Can't load arg_file_template:\n ") +
- template_path.value());
- err.PrintToStdout();
- return 1;
- }
-
- // Ignore the return code; if the read fails (unlikely), we'll just
- // use the default contents.
- base::ReadFileToString(full_path, &argfile_default_contents);
- }
-#if defined(OS_WIN)
- // Use Windows lineendings for this file since it will often open in
- // Notepad which can't handle Unix ones.
- base::ReplaceSubstringsAfterOffset(
- &argfile_default_contents, 0, "\n", "\r\n");
-#endif
- base::CreateDirectory(arg_file.DirName());
- base::WriteFile(arg_file, argfile_default_contents.c_str(),
- static_cast<int>(argfile_default_contents.size()));
- }
-
- ScopedTrace editor_trace(TraceItem::TRACE_SETUP, "Waiting for editor");
- if (!RunEditor(arg_file))
- return 1;
- }
-
- // Now do a normal "gen" command.
- OutputString("Generating files...\n");
- std::vector<std::string> gen_commands;
- gen_commands.push_back(build_dir);
- return RunGen(gen_commands);
-}
-
-} // namespace
-
-const char kArgs[] = "args";
-const char kArgs_HelpShort[] =
- "args: Display or configure arguments declared by the build.";
-const char kArgs_Help[] =
- R"(gn args <out_dir> [--list] [--short] [--args] [--overrides-only]
-
- See also "gn help buildargs" for a more high-level overview of how
- build arguments work.
-
-Usage
-
- gn args <out_dir>
- Open the arguments for the given build directory in an editor. If the
- given build directory doesn't exist, it will be created and an empty args
- file will be opened in the editor. You would type something like this
- into that file:
- enable_doom_melon=false
- os="android"
-
- To find your editor on Posix, GN will search the environment variables in
- order: GN_EDITOR, VISUAL, and EDITOR. On Windows GN will open the command
- associated with .txt files.
-
- Note: you can edit the build args manually by editing the file "args.gn"
- in the build directory and then running "gn gen <out_dir>".
-
- gn args <out_dir> --list[=<exact_arg>] [--short] [--overrides-only] [--json]
- Lists all build arguments available in the current configuration, or, if
- an exact_arg is specified for the list flag, just that one build
- argument.
-
- The output will list the declaration location, current value for the
- build, default value (if different than the current value), and comment
- preceding the declaration.
-
- If --short is specified, only the names and current values will be
- printed.
-
- If --overrides-only is specified, only the names and current values of
- arguments that have been overridden (i.e. non-default arguments) will
- be printed. Overrides come from the <out_dir>/args.gn file and //.gn
-
- If --json is specified, the output will be emitted in json format.
- JSON schema for output:
- [
- {
- "name": variable_name,
- "current": {
- "value": overridden_value,
- "file": file_name,
- "line": line_no
- },
- "default": {
- "value": default_value,
- "file": file_name,
- "line": line_no
- },
- "comment": comment_string
- },
- ...
- ]
-
-Examples
-
- gn args out/Debug
- Opens an editor with the args for out/Debug.
-
- gn args out/Debug --list --short
- Prints all arguments with their default values for the out/Debug
- build.
-
- gn args out/Debug --list --short --overrides-only
- Prints overridden arguments for the out/Debug build.
-
- gn args out/Debug --list=target_cpu
- Prints information about the "target_cpu" argument for the "
- "out/Debug
- build.
-
- gn args --list --args="os=\"android\" enable_doom_melon=true"
- Prints all arguments with the default values for a build with the
- given arguments set (which may affect the values of other
- arguments).
-)";
-
-int RunArgs(const std::vector<std::string>& args) {
- if (args.size() != 1) {
- Err(Location(), "Exactly one build dir needed.",
- "Usage: \"gn args <out_dir>\"\n"
- "Or see \"gn help args\" for more variants.").PrintToStdout();
- return 1;
- }
-
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchList))
- return ListArgs(args[0]);
- return EditArgsFile(args[0]);
-}
-
-} // namespace commands
diff --git a/chromium/tools/gn/command_check.cc b/chromium/tools/gn/command_check.cc
deleted file mode 100644
index 4efcd45f8ed..00000000000
--- a/chromium/tools/gn/command_check.cc
+++ /dev/null
@@ -1,256 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include "base/command_line.h"
-#include "base/strings/stringprintf.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/header_checker.h"
-#include "tools/gn/setup.h"
-#include "tools/gn/standard_out.h"
-#include "tools/gn/switches.h"
-#include "tools/gn/target.h"
-#include "tools/gn/trace.h"
-
-namespace commands {
-
-const char kNoGnCheck_Help[] =
- R"(nogncheck: Skip an include line from checking.
-
- GN's header checker helps validate that the includes match the build
- dependency graph. Sometimes an include might be conditional or otherwise
- problematic, but you want to specifically allow it. In this case, it can be
- whitelisted.
-
- Include lines containing the substring "nogncheck" will be excluded from
- header checking. The most common case is a conditional include:
-
- #if defined(ENABLE_DOOM_MELON)
- #include "tools/doom_melon/doom_melon.h" // nogncheck
- #endif
-
- If the build file has a conditional dependency on the corresponding target
- that matches the conditional include, everything will always link correctly:
-
- source_set("mytarget") {
- ...
- if (enable_doom_melon) {
- defines = [ "ENABLE_DOOM_MELON" ]
- deps += [ "//tools/doom_melon" ]
- }
-
- But GN's header checker does not understand preprocessor directives, won't
- know it matches the build dependencies, and will flag this include as
- incorrect when the condition is false.
-
-More information
-
- The topic "gn help check" has general information on how checking works and
- advice on fixing problems. Targets can also opt-out of checking, see
- "gn help check_includes".
-)";
-
-const char kCheck[] = "check";
-const char kCheck_HelpShort[] =
- "check: Check header dependencies.";
-const char kCheck_Help[] =
- R"(gn check <out_dir> [<label_pattern>] [--force]
-
- GN's include header checker validates that the includes for C-like source
- files match the build dependency graph.
-
- "gn check" is the same thing as "gn gen" with the "--check" flag except that
- this command does not write out any build files. It's intended to be an easy
- way to manually trigger include file checking.
-
- The <label_pattern> can take exact labels or patterns that match more than
- one (although not general regular expressions). If specified, only those
- matching targets will be checked. See "gn help label_pattern" for details.
-
-Command-specific switches
-
- --force
- Ignores specifications of "check_includes = false" and checks all
- target's files that match the target label.
-
-What gets checked
-
- The .gn file may specify a list of targets to be checked. Only these targets
- will be checked if no label_pattern is specified on the command line.
- Otherwise, the command-line list is used instead. See "gn help dotfile".
-
- Targets can opt-out from checking with "check_includes = false" (see
- "gn help check_includes").
-
- For targets being checked:
-
- - GN opens all C-like source files in the targets to be checked and scans
- the top for includes.
-
- - Includes with a "nogncheck" annotation are skipped (see
- "gn help nogncheck").
-
- - Only includes using "quotes" are checked. <brackets> are assumed to be
- system includes.
-
- - Include paths are assumed to be relative to any of the "include_dirs" for
- the target (including the implicit current dir).
-
- - GN does not run the preprocessor so will not understand conditional
- includes.
-
- - Only includes matching known files in the build are checked: includes
- matching unknown paths are ignored.
-
- For an include to be valid:
-
- - The included file must be in the current target, or there must be a path
- following only public dependencies to a target with the file in it
- ("gn path" is a good way to diagnose problems).
-
- - There can be multiple targets with an included file: only one needs to be
- valid for the include to be allowed.
-
- - If there are only "sources" in a target, all are considered to be public
- and can be included by other targets with a valid public dependency path.
-
- - If a target lists files as "public", only those files are able to be
- included by other targets. Anything in the sources will be considered
- private and will not be includable regardless of dependency paths.
-
- - Outputs from actions are treated like public sources on that target.
-
- - A target can include headers from a target that depends on it if the
- other target is annotated accordingly. See "gn help
- allow_circular_includes_from".
-
-Advice on fixing problems
-
- If you have a third party project that is difficult to fix or doesn't care
- about include checks it's generally best to exclude that target from checking
- altogether via "check_includes = false".
-
- If you have conditional includes, make sure the build conditions and the
- preprocessor conditions match, and annotate the line with "nogncheck" (see
- "gn help nogncheck" for an example).
-
- If two targets are hopelessly intertwined, use the
- "allow_circular_includes_from" annotation. Ideally each should have identical
- dependencies so configs inherited from those dependencies are consistent (see
- "gn help allow_circular_includes_from").
-
- If you have a standalone header file or files that need to be shared between
- a few targets, you can consider making a source_set listing only those
- headers as public sources. With only header files, the source set will be a
- no-op from a build perspective, but will give a central place to refer to
- those headers. That source set's files will still need to pass "gn check" in
- isolation.
-
- In rare cases it makes sense to list a header in more than one target if it
- could be considered conceptually a member of both.
-
-Examples
-
- gn check out/Debug
- Check everything.
-
- gn check out/Default //foo:bar
- Check only the files in the //foo:bar target.
-
- gn check out/Default "//foo/*
- Check only the files in targets in the //foo directory tree.
-)";
-
-int RunCheck(const std::vector<std::string>& args) {
- if (args.size() != 1 && args.size() != 2) {
- Err(Location(), "You're holding it wrong.",
- "Usage: \"gn check <out_dir> [<target_label>]\"").PrintToStdout();
- return 1;
- }
-
- // Deliberately leaked to avoid expensive process teardown.
- Setup* setup = new Setup();
- if (!setup->DoSetup(args[0], false))
- return 1;
- if (!setup->Run())
- return 1;
-
- std::vector<const Target*> all_targets =
- setup->builder().GetAllResolvedTargets();
-
- bool filtered_by_build_config = false;
- std::vector<const Target*> targets_to_check;
- if (args.size() > 1) {
- // Compute the targets to check.
- std::vector<std::string> inputs(args.begin() + 1, args.end());
- UniqueVector<const Target*> target_matches;
- UniqueVector<const Config*> config_matches;
- UniqueVector<const Toolchain*> toolchain_matches;
- UniqueVector<SourceFile> file_matches;
- if (!ResolveFromCommandLineInput(setup, inputs, false,
- &target_matches, &config_matches,
- &toolchain_matches, &file_matches))
- return 1;
-
- if (target_matches.size() == 0) {
- OutputString("No matching targets.\n");
- return 1;
- }
- targets_to_check.insert(targets_to_check.begin(),
- target_matches.begin(), target_matches.end());
- } else {
- // No argument means to check everything allowed by the filter in
- // the build config file.
- if (setup->check_patterns()) {
- FilterTargetsByPatterns(all_targets, *setup->check_patterns(),
- &targets_to_check);
- filtered_by_build_config = targets_to_check.size() != all_targets.size();
- } else {
- // No global filter, check everything.
- targets_to_check = all_targets;
- }
- }
-
- const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
- bool force = cmdline->HasSwitch("force");
-
- if (!CheckPublicHeaders(&setup->build_settings(), all_targets,
- targets_to_check, force))
- return 1;
-
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kQuiet)) {
- if (filtered_by_build_config) {
- // Tell the user about the implicit filtering since this is obscure.
- OutputString(base::StringPrintf(
- "%d targets out of %d checked based on the check_targets defined in"
- " \".gn\".\n",
- static_cast<int>(targets_to_check.size()),
- static_cast<int>(all_targets.size())));
- }
- OutputString("Header dependency check OK\n", DECORATION_GREEN);
- }
- return 0;
-}
-
-bool CheckPublicHeaders(const BuildSettings* build_settings,
- const std::vector<const Target*>& all_targets,
- const std::vector<const Target*>& to_check,
- bool force_check) {
- ScopedTrace trace(TraceItem::TRACE_CHECK_HEADERS, "Check headers");
-
- scoped_refptr<HeaderChecker> header_checker(
- new HeaderChecker(build_settings, all_targets));
-
- std::vector<Err> header_errors;
- header_checker->Run(to_check, force_check, &header_errors);
- for (size_t i = 0; i < header_errors.size(); i++) {
- if (i > 0)
- OutputString("___________________\n", DECORATION_YELLOW);
- header_errors[i].PrintToStdout();
- }
- return header_errors.empty();
-}
-
-} // namespace commands
diff --git a/chromium/tools/gn/command_clean.cc b/chromium/tools/gn/command_clean.cc
deleted file mode 100644
index 8165aaa280b..00000000000
--- a/chromium/tools/gn/command_clean.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/files/file_enumerator.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/strings/string_split.h"
-#include "base/strings/stringprintf.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/setup.h"
-
-namespace {
-
-// Extracts from a build.ninja the commands to run GN.
-//
-// The commands to run GN are the gn rule and build.ninja build step at the top
-// of the build.ninja file. We want to keep these when deleting GN builds since
-// we want to preserve the command-line flags to GN.
-//
-// On error, returns the empty string.
-std::string ExtractGNBuildCommands(const base::FilePath& build_ninja_file) {
- std::string file_contents;
- if (!base::ReadFileToString(build_ninja_file, &file_contents))
- return std::string();
-
- std::vector<base::StringPiece> lines = base::SplitStringPiece(
- file_contents, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
-
- std::string result;
- int num_blank_lines = 0;
- for (const auto& line : lines) {
- line.AppendToString(&result);
- result.push_back('\n');
- if (line.empty())
- ++num_blank_lines;
- if (num_blank_lines == 3)
- break;
- }
-
- return result;
-}
-
-} // namespace
-
-namespace commands {
-
-const char kClean[] = "clean";
-const char kClean_HelpShort[] =
- "clean: Cleans the output directory.";
-const char kClean_Help[] =
- "gn clean <out_dir>\n"
- "\n"
- " Deletes the contents of the output directory except for args.gn and\n"
- " creates a Ninja build environment sufficient to regenerate the build.\n";
-
-int RunClean(const std::vector<std::string>& args) {
- if (args.size() != 1) {
- Err(Location(), "You're holding it wrong.",
- "Usage: \"gn clean <out_dir>\"").PrintToStdout();
- return 1;
- }
-
- Setup* setup = new Setup;
- if (!setup->DoSetup(args[0], false))
- return 1;
-
- base::FilePath build_dir(setup->build_settings().GetFullPath(
- SourceDir(setup->build_settings().build_dir().value())));
-
- // NOTE: Not all GN builds have args.gn file hence we check here
- // if a build.ninja.d files exists instead.
- base::FilePath build_ninja_d_file = build_dir.AppendASCII("build.ninja.d");
- if (!base::PathExists(build_ninja_d_file)) {
- Err(Location(),
- base::StringPrintf(
- "%s does not look like a build directory.\n",
- FilePathToUTF8(build_ninja_d_file.DirName().value()).c_str()))
- .PrintToStdout();
- return 1;
- }
-
- // Erase everything but the args file, and write a dummy build.ninja file that
- // will automatically rerun GN the next time Ninja is run.
- base::FilePath build_ninja_file = build_dir.AppendASCII("build.ninja");
- std::string build_commands = ExtractGNBuildCommands(build_ninja_file);
- if (build_commands.empty()) {
- // Couldn't parse the build.ninja file.
- Err(Location(), "Couldn't read build.ninja in this directory.",
- "Try running \"gn gen\" on it and then re-running \"gn clean\".")
- .PrintToStdout();
- return 1;
- }
-
- base::FileEnumerator traversal(
- build_dir, false,
- base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
- for (base::FilePath current = traversal.Next(); !current.empty();
- current = traversal.Next()) {
- if (!base::FilePath::CompareEqualIgnoreCase(current.BaseName().value(),
- FILE_PATH_LITERAL("args.gn"))) {
- base::DeleteFile(current, true);
- }
- }
-
- // Write the build.ninja file sufficiently to regenerate itself.
- if (base::WriteFile(build_ninja_file, build_commands.data(),
- static_cast<int>(build_commands.size())) == -1) {
- Err(Location(), std::string("Failed to write build.ninja."))
- .PrintToStdout();
- return 1;
- }
-
- // Write a .d file for the build which references a nonexistant file.
- // This will make Ninja always mark the build as dirty.
- std::string dummy_content("build.ninja: nonexistant_file.gn\n");
- if (base::WriteFile(build_ninja_d_file, dummy_content.data(),
- static_cast<int>(dummy_content.size())) == -1) {
- Err(Location(), std::string("Failed to write build.ninja.d."))
- .PrintToStdout();
- return 1;
- }
-
- return 0;
-}
-
-} // namespace commands
diff --git a/chromium/tools/gn/command_desc.cc b/chromium/tools/gn/command_desc.cc
deleted file mode 100644
index 9bd68e47b5b..00000000000
--- a/chromium/tools/gn/command_desc.cc
+++ /dev/null
@@ -1,516 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include <algorithm>
-#include <memory>
-#include <set>
-#include <sstream>
-
-#include "base/command_line.h"
-#include "base/json/json_writer.h"
-#include "base/strings/string_util.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/config.h"
-#include "tools/gn/desc_builder.h"
-#include "tools/gn/setup.h"
-#include "tools/gn/standard_out.h"
-#include "tools/gn/switches.h"
-#include "tools/gn/target.h"
-#include "tools/gn/variables.h"
-
-namespace commands {
-
-namespace {
-
-// Desc-specific command line switches.
-const char kBlame[] = "blame";
-const char kTree[] = "tree";
-const char kAll[] = "all";
-
-// Prints value with specified indentation level
-void PrintValue(const base::Value* value, int indentLevel) {
- std::string indent(indentLevel * 2, ' ');
- const base::ListValue* list_value = nullptr;
- const base::DictionaryValue* dict_value = nullptr;
- std::string string_value;
- bool bool_value = false;
- if (value->GetAsList(&list_value)) {
- for (const auto& v : *list_value) {
- PrintValue(&v, indentLevel);
- }
- } else if (value->GetAsString(&string_value)) {
- OutputString(indent);
- OutputString(string_value);
- OutputString("\n");
- } else if (value->GetAsBoolean(&bool_value)) {
- OutputString(indent);
- OutputString(bool_value ? "true" : "false");
- OutputString("\n");
- } else if (value->GetAsDictionary(&dict_value)) {
- base::DictionaryValue::Iterator iter(*dict_value);
- while (!iter.IsAtEnd()) {
- OutputString(indent + iter.key() + "\n");
- PrintValue(&iter.value(), indentLevel + 1);
- iter.Advance();
- }
- } else if (value->is_none()) {
- OutputString(indent + "<null>\n");
- }
-}
-
-// Default handler for property
-void DefaultHandler(const std::string& name, const base::Value* value) {
- OutputString("\n");
- OutputString(name);
- OutputString("\n");
- PrintValue(value, 1);
-}
-
-// Specific handler for properties that need different treatment
-
-// Prints label and property value on one line, capitalizing the label.
-void LabelHandler(std::string name, const base::Value* value) {
- name[0] = base::ToUpperASCII(name[0]);
- std::string string_value;
- if (value->GetAsString(&string_value)) {
- OutputString(name + ": ", DECORATION_YELLOW);
- OutputString(string_value + "\n");
- }
-}
-
-void VisibilityHandler(const std::string& name, const base::Value* value) {
- const base::ListValue* list;
- if (value->GetAsList(&list)) {
- if (list->empty()) {
- base::Value str("(no visibility)");
- DefaultHandler(name, &str);
- } else {
- DefaultHandler(name, value);
- }
- }
-}
-
-void PublicHandler(const std::string& name, const base::Value* value) {
- std::string p;
- if (value->GetAsString(&p)) {
- if (p == "*") {
- base::Value str("[All headers listed in the sources are public.]");
- DefaultHandler(name, &str);
- return;
- }
- }
- DefaultHandler(name, value);
-}
-
-void ConfigsHandler(const std::string& name, const base::Value* value) {
- bool tree = base::CommandLine::ForCurrentProcess()->HasSwitch(kTree);
- if (tree)
- DefaultHandler(name + " tree (in order applying)", value);
- else
- DefaultHandler(name + " (in order applying, try also --tree)", value);
-}
-
-void DepsHandler(const std::string& name, const base::Value* value) {
- bool tree = base::CommandLine::ForCurrentProcess()->HasSwitch(kTree);
- bool all = base::CommandLine::ForCurrentProcess()->HasSwitch(kTree);
- if (tree) {
- DefaultHandler("Dependency tree", value);
- } else {
- if (!all) {
- DefaultHandler(
- "Direct dependencies "
- "(try also \"--all\", \"--tree\", or even \"--all --tree\")",
- value);
- } else {
- DefaultHandler("All recursive dependencies", value);
- }
- }
-}
-
-// Outputs need special processing when output patterns are present.
-void ProcessOutputs(base::DictionaryValue* target) {
- base::ListValue* patterns = nullptr;
- base::ListValue* outputs = nullptr;
- target->GetList("output_patterns", &patterns);
- target->GetList(variables::kOutputs, &outputs);
-
- if (outputs || patterns) {
- OutputString("\noutputs\n");
- int indent = 1;
- if (patterns) {
- OutputString(" Output patterns\n");
- indent = 2;
- PrintValue(patterns, indent);
- OutputString("\n Resolved output file list\n");
- }
- if (outputs)
- PrintValue(outputs, indent);
-
- target->Remove("output_patterns", nullptr);
- target->Remove(variables::kOutputs, nullptr);
- }
-}
-
-bool PrintTarget(const Target* target,
- const std::string& what,
- bool single_target,
- bool all,
- bool tree,
- bool blame) {
- std::unique_ptr<base::DictionaryValue> dict =
- DescBuilder::DescriptionForTarget(target, what, all, tree, blame);
- if (!what.empty() && dict->empty()) {
- OutputString("Don't know how to display \"" + what + "\" for \"" +
- Target::GetStringForOutputType(target->output_type()) +
- "\".\n");
- return false;
- }
- // Print single value, without any headers
- if (!what.empty() && dict->size() == 1 && single_target) {
- base::DictionaryValue::Iterator iter(*dict);
- PrintValue(&iter.value(), 0);
- return true;
- }
-
- OutputString("Target ", DECORATION_YELLOW);
- OutputString(target->label().GetUserVisibleName(false));
- OutputString("\n");
-
- std::unique_ptr<base::Value> v;
-#define HANDLER(property, handler_name) \
- if (dict->Remove(property, &v)) { \
- handler_name(property, v.get()); \
- }
-
- // Entries with DefaultHandler are present to enforce order
- HANDLER("type", LabelHandler);
- HANDLER("toolchain", LabelHandler);
- HANDLER(variables::kVisibility, VisibilityHandler);
- HANDLER(variables::kTestonly, DefaultHandler);
- HANDLER(variables::kCheckIncludes, DefaultHandler);
- HANDLER(variables::kAllowCircularIncludesFrom, DefaultHandler);
- HANDLER(variables::kSources, DefaultHandler);
- HANDLER(variables::kPublic, PublicHandler);
- HANDLER(variables::kInputs, DefaultHandler);
- HANDLER(variables::kConfigs, ConfigsHandler);
- HANDLER(variables::kPublicConfigs, ConfigsHandler);
- HANDLER(variables::kAllDependentConfigs, ConfigsHandler);
- HANDLER(variables::kScript, DefaultHandler);
- HANDLER(variables::kArgs, DefaultHandler);
- HANDLER(variables::kDepfile, DefaultHandler);
- ProcessOutputs(dict.get());
- HANDLER("bundle_data", DefaultHandler);
- HANDLER(variables::kArflags, DefaultHandler);
- HANDLER(variables::kAsmflags, DefaultHandler);
- HANDLER(variables::kCflags, DefaultHandler);
- HANDLER(variables::kCflagsC, DefaultHandler);
- HANDLER(variables::kCflagsCC, DefaultHandler);
- HANDLER(variables::kCflagsObjC, DefaultHandler);
- HANDLER(variables::kCflagsObjCC, DefaultHandler);
- HANDLER(variables::kDefines, DefaultHandler);
- HANDLER(variables::kIncludeDirs, DefaultHandler);
- HANDLER(variables::kLdflags, DefaultHandler);
- HANDLER(variables::kPrecompiledHeader, DefaultHandler);
- HANDLER(variables::kPrecompiledSource, DefaultHandler);
- HANDLER(variables::kDeps, DepsHandler);
- HANDLER(variables::kLibs, DefaultHandler);
- HANDLER(variables::kLibDirs, DefaultHandler);
-
-#undef HANDLER
-
- // Process the rest (if any)
- base::DictionaryValue::Iterator iter(*dict);
- while (!iter.IsAtEnd()) {
- DefaultHandler(iter.key(), &iter.value());
- iter.Advance();
- }
-
- return true;
-}
-
-bool PrintConfig(const Config* config,
- const std::string& what,
- bool single_config) {
- std::unique_ptr<base::DictionaryValue> dict =
- DescBuilder::DescriptionForConfig(config, what);
- if (!what.empty() && dict->empty()) {
- OutputString("Don't know how to display \"" + what + "\" for a config.\n");
- return false;
- }
- // Print single value, without any headers
- if (!what.empty() && dict->size() == 1 && single_config) {
- base::DictionaryValue::Iterator iter(*dict);
- PrintValue(&iter.value(), 0);
- return true;
- }
-
- OutputString("Config: ", DECORATION_YELLOW);
- OutputString(config->label().GetUserVisibleName(false));
- OutputString("\n");
-
- std::unique_ptr<base::Value> v;
-#define HANDLER(property, handler_name) \
- if (dict->Remove(property, &v)) { \
- handler_name(property, v.get()); \
- }
-
- HANDLER("toolchain", LabelHandler);
- if (!config->configs().empty()) {
- OutputString(
- "(This is a composite config, the values below are after the\n"
- "expansion of the child configs.)\n");
- }
- HANDLER(variables::kArflags, DefaultHandler);
- HANDLER(variables::kAsmflags, DefaultHandler);
- HANDLER(variables::kCflags, DefaultHandler);
- HANDLER(variables::kCflagsC, DefaultHandler);
- HANDLER(variables::kCflagsCC, DefaultHandler);
- HANDLER(variables::kCflagsObjC, DefaultHandler);
- HANDLER(variables::kCflagsObjCC, DefaultHandler);
- HANDLER(variables::kDefines, DefaultHandler);
- HANDLER(variables::kIncludeDirs, DefaultHandler);
- HANDLER(variables::kInputs, DefaultHandler);
- HANDLER(variables::kLdflags, DefaultHandler);
- HANDLER(variables::kLibs, DefaultHandler);
- HANDLER(variables::kLibDirs, DefaultHandler);
- HANDLER(variables::kPrecompiledHeader, DefaultHandler);
- HANDLER(variables::kPrecompiledSource, DefaultHandler);
-
-#undef HANDLER
-
- return true;
-}
-
-} // namespace
-
-// desc ------------------------------------------------------------------------
-
-const char kDesc[] = "desc";
-const char kDesc_HelpShort[] =
- "desc: Show lots of insightful information about a target or config.";
-const char kDesc_Help[] =
- R"(gn desc <out_dir> <label or pattern> [<what to show>] [--blame] "
-[--format=json]
-
- Displays information about a given target or config. The build build
- parameters will be taken for the build in the given <out_dir>.
-
- The <label or pattern> can be a target label, a config label, or a label
- pattern (see "gn help label_pattern"). A label pattern will only match
- targets.
-
-Possibilities for <what to show>
-
- (If unspecified an overall summary will be displayed.)
-
- all_dependent_configs
- allow_circular_includes_from
- arflags [--blame]
- args
- cflags [--blame]
- cflags_cc [--blame]
- cflags_cxx [--blame]
- check_includes
- configs [--tree] (see below)
- defines [--blame]
- depfile
- deps [--all] [--tree] (see below)
- include_dirs [--blame]
- inputs
- ldflags [--blame]
- lib_dirs
- libs
- outputs
- public_configs
- public
- script
- sources
- testonly
- visibility
-
- runtime_deps
- Compute all runtime deps for the given target. This is a computed list
- and does not correspond to any GN variable, unlike most other values
- here.
-
- The output is a list of file names relative to the build directory. See
- "gn help runtime_deps" for how this is computed. This also works with
- "--blame" to see the source of the dependency.
-
-Shared flags
-)"
-
-ALL_TOOLCHAINS_SWITCH_HELP
-
-R"(
- --format=json
- Format the output as JSON instead of text.
-
-Target flags
-
- --blame
- Used with any value specified on a config, this will name the config that
- cause that target to get the flag. This doesn't currently work for libs
- and lib_dirs because those are inherited and are more complicated to
- figure out the blame (patches welcome).
-
-Configs
-
- The "configs" section will list all configs that apply. For targets this will
- include configs specified in the "configs" variable of the target, and also
- configs pushed onto this target via public or "all dependent" configs.
-
- Configs can have child configs. Specifying --tree will show the hierarchy.
-
-Printing outputs
-
- The "outputs" section will list all outputs that apply, including the outputs
- computed from the tool definition (eg for "executable", "static_library", ...
- targets).
-
-Printing deps
-
- Deps will include all public, private, and data deps (TODO this could be
- clarified and enhanced) sorted in order applying. The following may be used:
-
- --all
- Collects all recursive dependencies and prints a sorted flat list. Also
- usable with --tree (see below).
-)"
-
- TARGET_PRINTING_MODE_COMMAND_LINE_HELP
-"\n"
- TARGET_TESTONLY_FILTER_COMMAND_LINE_HELP
-
-R"(
- --tree
- Print a dependency tree. By default, duplicates will be elided with "..."
- but when --all and -tree are used together, no eliding will be performed.
-
- The "deps", "public_deps", and "data_deps" will all be included in the
- tree.
-
- Tree output can not be used with the filtering or output flags: --as,
- --type, --testonly.
-)"
-
-TARGET_TYPE_FILTER_COMMAND_LINE_HELP
-
-R"(Note
-
- This command will show the full name of directories and source files, but
- when directories and source paths are written to the build file, they will be
- adjusted to be relative to the build directory. So the values for paths
- displayed by this command won't match (but should mean the same thing).
-
-Examples
-
- gn desc out/Debug //base:base
- Summarizes the given target.
-
- gn desc out/Foo :base_unittests deps --tree
- Shows a dependency tree of the "base_unittests" project in
- the current directory.
-
- gn desc out/Debug //base defines --blame
- Shows defines set for the //base:base target, annotated by where
- each one was set from.
-)";
-
-int RunDesc(const std::vector<std::string>& args) {
- if (args.size() != 2 && args.size() != 3) {
- Err(Location(), "You're holding it wrong.",
- "Usage: \"gn desc <out_dir> <target_name> [<what to display>]\"")
- .PrintToStdout();
- return 1;
- }
- const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
-
- // Deliberately leaked to avoid expensive process teardown.
- Setup* setup = new Setup;
- if (!setup->DoSetup(args[0], false))
- return 1;
- if (!setup->Run())
- return 1;
-
- // Resolve target(s) and config from inputs.
- UniqueVector<const Target*> target_matches;
- UniqueVector<const Config*> config_matches;
- UniqueVector<const Toolchain*> toolchain_matches;
- UniqueVector<SourceFile> file_matches;
-
- std::vector<std::string> target_list;
- target_list.push_back(args[1]);
-
- if (!ResolveFromCommandLineInput(
- setup, target_list, cmdline->HasSwitch(switches::kAllToolchains),
- &target_matches, &config_matches, &toolchain_matches, &file_matches))
- return 1;
-
- std::string what_to_print;
- if (args.size() == 3)
- what_to_print = args[2];
-
- bool json = cmdline->GetSwitchValueASCII("format") == "json";
-
- if (target_matches.empty() && config_matches.empty()) {
- OutputString("The input " + args[1] +
- " matches no targets, configs or files.\n", DECORATION_YELLOW);
- return 1;
- }
-
- if (json) {
- // Convert all targets/configs to JSON, serialize and print them
- auto res = std::make_unique<base::DictionaryValue>();
- if (!target_matches.empty()) {
- for (const auto* target : target_matches) {
- res->SetWithoutPathExpansion(
- target->label().GetUserVisibleName(
- target->settings()->default_toolchain_label()),
- DescBuilder::DescriptionForTarget(
- target, what_to_print, cmdline->HasSwitch(kAll),
- cmdline->HasSwitch(kTree), cmdline->HasSwitch(kBlame)));
- }
- } else if (!config_matches.empty()) {
- for (const auto* config : config_matches) {
- res->SetWithoutPathExpansion(
- config->label().GetUserVisibleName(false),
- DescBuilder::DescriptionForConfig(config, what_to_print));
- }
- }
- std::string s;
- base::JSONWriter::WriteWithOptions(
- *res.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &s);
- OutputString(s);
- } else {
- // Regular (non-json) formatted output
- bool multiple_outputs = (target_matches.size() + config_matches.size()) > 1;
-
- bool printed_output = false;
- for (const Target* target : target_matches) {
- if (printed_output)
- OutputString("\n\n");
- printed_output = true;
-
- if (!PrintTarget(target, what_to_print, !multiple_outputs,
- cmdline->HasSwitch(kAll), cmdline->HasSwitch(kTree),
- cmdline->HasSwitch(kBlame)))
- return 1;
- }
- for (const Config* config : config_matches) {
- if (printed_output)
- OutputString("\n\n");
- printed_output = true;
-
- if (!PrintConfig(config, what_to_print, !multiple_outputs))
- return 1;
- }
- }
-
- return 0;
-}
-
-} // namespace commands
diff --git a/chromium/tools/gn/command_format.cc b/chromium/tools/gn/command_format.cc
deleted file mode 100644
index c44f637c569..00000000000
--- a/chromium/tools/gn/command_format.cc
+++ /dev/null
@@ -1,1119 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/command_format.h"
-
-#include <stddef.h>
-
-#include <sstream>
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/macros.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parser.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/setup.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/tokenizer.h"
-
-namespace commands {
-
-const char kSwitchDryRun[] = "dry-run";
-const char kSwitchDumpTree[] = "dump-tree";
-const char kSwitchStdin[] = "stdin";
-
-const char kFormat[] = "format";
-const char kFormat_HelpShort[] =
- "format: Format .gn file.";
-const char kFormat_Help[] =
- R"(gn format [--dump-tree] (--stdin | <build_file>)
-
- Formats .gn file to a standard format.
-
- The contents of some lists ('sources', 'deps', etc.) will be sorted to a
- canonical order. To suppress this, you can add a comment of the form "#
- NOSORT" immediately preceding the assignment. e.g.
-
- # NOSORT
- sources = [
- "z.cc",
- "a.cc",
- ]
-
-Arguments
-
- --dry-run
- Does not change or output anything, but sets the process exit code based
- on whether output would be different than what's on disk. This is useful
- for presubmit/lint-type checks.
- - Exit code 0: successful format, matches on disk.
- - Exit code 1: general failure (parse error, etc.)
- - Exit code 2: successful format, but differs from on disk.
-
- --dump-tree
- For debugging, dumps the parse tree to stdout and does not update the
- file or print formatted output.
-
- --stdin
- Read input from stdin and write to stdout rather than update a file
- in-place.
-
-Examples
- gn format //some/BUILD.gn
- gn format some\\BUILD.gn
- gn format /abspath/some/BUILD.gn
- gn format --stdin
-)";
-
-namespace {
-
-const int kIndentSize = 2;
-const int kMaximumWidth = 80;
-
-const int kPenaltyLineBreak = 500;
-const int kPenaltyHorizontalSeparation = 100;
-const int kPenaltyExcess = 10000;
-const int kPenaltyBrokenLineOnOneLiner = 5000;
-
-enum Precedence {
- kPrecedenceLowest,
- kPrecedenceAssign,
- kPrecedenceOr,
- kPrecedenceAnd,
- kPrecedenceCompare,
- kPrecedenceAdd,
- kPrecedenceUnary,
- kPrecedenceSuffix,
-};
-
-int CountLines(const std::string& str) {
- return static_cast<int>(base::SplitStringPiece(
- str, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL).size());
-}
-
-class Printer {
- public:
- Printer();
- ~Printer();
-
- void Block(const ParseNode* file);
-
- std::string String() const { return output_; }
-
- private:
- // Format a list of values using the given style.
- enum SequenceStyle {
- kSequenceStyleList,
- kSequenceStyleBlock,
- kSequenceStyleBracedBlock,
- };
-
- struct Metrics {
- Metrics() : first_length(-1), longest_length(-1), multiline(false) {}
- int first_length;
- int longest_length;
- bool multiline;
- };
-
- // Add to output.
- void Print(base::StringPiece str);
-
- // Add the current margin (as spaces) to the output.
- void PrintMargin();
-
- void TrimAndPrintToken(const Token& token);
-
- // End the current line, flushing end of line comments.
- void Newline();
-
- // Remove trailing spaces from the current line.
- void Trim();
-
- // Whether there's a blank separator line at the current position.
- bool HaveBlankLine();
-
- // Flag assignments to sources, deps, etc. to make their RHSs multiline.
- void AnnotatePreferredMultilineAssignment(const BinaryOpNode* binop);
-
- // Sort a list on the RHS if the LHS is 'sources', 'deps' or 'public_deps'.
- // The 'sources' are sorted alphabetically while the 'deps' and 'public_deps'
- // are sorted putting first the relative targets and then the global ones
- // (both sorted alphabetically).
- void SortIfSourcesOrDeps(const BinaryOpNode* binop);
-
- // Heuristics to decide if there should be a blank line added between two
- // items. For various "small" items, it doesn't look nice if there's too much
- // vertical whitespace added.
- bool ShouldAddBlankLineInBetween(const ParseNode* a, const ParseNode* b);
-
- // Get the 0-based x position on the current line.
- int CurrentColumn() const;
-
- // Get the current line in the output;
- int CurrentLine() const;
-
- // Adds an opening ( if prec is less than the outers (to maintain evalution
- // order for a subexpression). If an opening paren is emitted, *parenthesized
- // will be set so it can be closed at the end of the expression.
- void AddParen(int prec, int outer_prec, bool* parenthesized);
-
- // Print the expression to the output buffer. Returns the type of element
- // added to the output. The value of outer_prec gives the precedence of the
- // operator outside this Expr. If that operator binds tighter than root's,
- // Expr must introduce parentheses.
- int Expr(const ParseNode* root, int outer_prec, const std::string& suffix);
-
- // Generic penalties for exceeding maximum width, adding more lines, etc.
- int AssessPenalty(const std::string& output);
-
- // Tests if any lines exceed the maximum width.
- bool ExceedsMaximumWidth(const std::string& output);
-
- // Format a list of values using the given style.
- // |end| holds any trailing comments to be printed just before the closing
- // bracket.
- template <class PARSENODE> // Just for const covariance.
- void Sequence(SequenceStyle style,
- const std::vector<std::unique_ptr<PARSENODE>>& list,
- const ParseNode* end,
- bool force_multiline);
-
- // Returns the penalty.
- int FunctionCall(const FunctionCallNode* func_call,
- const std::string& suffix);
-
- // Create a clone of this Printer in a similar state (other than the output,
- // but including margins, etc.) to be used for dry run measurements.
- void InitializeSub(Printer* sub);
-
- template <class PARSENODE>
- bool ListWillBeMultiline(const std::vector<std::unique_ptr<PARSENODE>>& list,
- const ParseNode* end);
-
- std::string output_; // Output buffer.
- std::vector<Token> comments_; // Pending end-of-line comments.
- int margin() const { return stack_.back().margin; }
-
- int penalty_depth_;
- int GetPenaltyForLineBreak() const {
- return penalty_depth_ * kPenaltyLineBreak;
- }
-
- struct IndentState {
- IndentState()
- : margin(0),
- continuation_requires_indent(false),
- parent_is_boolean_or(false) {}
- IndentState(int margin,
- bool continuation_requires_indent,
- bool parent_is_boolean_or)
- : margin(margin),
- continuation_requires_indent(continuation_requires_indent),
- parent_is_boolean_or(parent_is_boolean_or) {}
-
- // The left margin (number of spaces).
- int margin;
-
- bool continuation_requires_indent;
-
- bool parent_is_boolean_or;
- };
- // Stack used to track
- std::vector<IndentState> stack_;
-
- // Gives the precedence for operators in a BinaryOpNode.
- std::map<base::StringPiece, Precedence> precedence_;
-
- DISALLOW_COPY_AND_ASSIGN(Printer);
-};
-
-Printer::Printer() : penalty_depth_(0) {
- output_.reserve(100 << 10);
- precedence_["="] = kPrecedenceAssign;
- precedence_["+="] = kPrecedenceAssign;
- precedence_["-="] = kPrecedenceAssign;
- precedence_["||"] = kPrecedenceOr;
- precedence_["&&"] = kPrecedenceAnd;
- precedence_["<"] = kPrecedenceCompare;
- precedence_[">"] = kPrecedenceCompare;
- precedence_["=="] = kPrecedenceCompare;
- precedence_["!="] = kPrecedenceCompare;
- precedence_["<="] = kPrecedenceCompare;
- precedence_[">="] = kPrecedenceCompare;
- precedence_["+"] = kPrecedenceAdd;
- precedence_["-"] = kPrecedenceAdd;
- precedence_["!"] = kPrecedenceUnary;
- stack_.push_back(IndentState());
-}
-
-Printer::~Printer() = default;
-
-void Printer::Print(base::StringPiece str) {
- str.AppendToString(&output_);
-}
-
-void Printer::PrintMargin() {
- output_ += std::string(margin(), ' ');
-}
-
-void Printer::TrimAndPrintToken(const Token& token) {
- std::string trimmed;
- TrimWhitespaceASCII(token.value().as_string(), base::TRIM_ALL, &trimmed);
- Print(trimmed);
-}
-
-void Printer::Newline() {
- if (!comments_.empty()) {
- Print(" ");
- // Save the margin, and temporarily set it to where the first comment
- // starts so that multiple suffix comments are vertically aligned. This
- // will need to be fancier once we enforce 80 col.
- stack_.push_back(IndentState(CurrentColumn(), false, false));
- int i = 0;
- for (const auto& c : comments_) {
- if (i > 0) {
- Trim();
- Print("\n");
- PrintMargin();
- }
- TrimAndPrintToken(c);
- ++i;
- }
- stack_.pop_back();
- comments_.clear();
- }
- Trim();
- Print("\n");
- PrintMargin();
-}
-
-void Printer::Trim() {
- size_t n = output_.size();
- while (n > 0 && output_[n - 1] == ' ')
- --n;
- output_.resize(n);
-}
-
-bool Printer::HaveBlankLine() {
- size_t n = output_.size();
- while (n > 0 && output_[n - 1] == ' ')
- --n;
- return n > 2 && output_[n - 1] == '\n' && output_[n - 2] == '\n';
-}
-
-void Printer::AnnotatePreferredMultilineAssignment(const BinaryOpNode* binop) {
- const IdentifierNode* ident = binop->left()->AsIdentifier();
- const ListNode* list = binop->right()->AsList();
- // This is somewhat arbitrary, but we include the 'deps'- and 'sources'-like
- // things, but not flags things.
- if (binop->op().value() == "=" && ident && list) {
- const base::StringPiece lhs = ident->value().value();
- if (lhs == "data" || lhs == "datadeps" || lhs == "data_deps" ||
- lhs == "deps" || lhs == "inputs" || lhs == "outputs" ||
- lhs == "public" || lhs == "public_deps" || lhs == "sources") {
- const_cast<ListNode*>(list)->set_prefer_multiline(true);
- }
- }
-}
-
-void Printer::SortIfSourcesOrDeps(const BinaryOpNode* binop) {
- if (binop->comments() && !binop->comments()->before().empty() &&
- binop->comments()->before()[0].value().as_string() == "# NOSORT") {
- // Allow disabling of sort for specific actions that might be
- // order-sensitive.
- return;
- }
- const IdentifierNode* ident = binop->left()->AsIdentifier();
- const ListNode* list = binop->right()->AsList();
- if ((binop->op().value() == "=" || binop->op().value() == "+=" ||
- binop->op().value() == "-=") &&
- ident && list) {
- const base::StringPiece lhs = ident->value().value();
- if (lhs == "public" || lhs == "sources")
- const_cast<ListNode*>(list)->SortAsStringsList();
- else if (lhs == "deps" || lhs == "public_deps")
- const_cast<ListNode*>(list)->SortAsDepsList();
- }
-}
-
-bool Printer::ShouldAddBlankLineInBetween(const ParseNode* a,
- const ParseNode* b) {
- LocationRange a_range = a->GetRange();
- LocationRange b_range = b->GetRange();
- // If they're already separated by 1 or more lines, then we want to keep a
- // blank line.
- return (b_range.begin().line_number() > a_range.end().line_number() + 1) ||
- // Always put a blank line before a block comment.
- b->AsBlockComment();
-}
-
-int Printer::CurrentColumn() const {
- int n = 0;
- while (n < static_cast<int>(output_.size()) &&
- output_[output_.size() - 1 - n] != '\n') {
- ++n;
- }
- return n;
-}
-
-int Printer::CurrentLine() const {
- int count = 1;
- for (const char* p = output_.c_str(); (p = strchr(p, '\n')) != nullptr;) {
- ++count;
- ++p;
- }
- return count;
-}
-
-void Printer::Block(const ParseNode* root) {
- const BlockNode* block = root->AsBlock();
-
- if (block->comments()) {
- for (const auto& c : block->comments()->before()) {
- TrimAndPrintToken(c);
- Newline();
- }
- }
-
- size_t i = 0;
- for (const auto& stmt : block->statements()) {
- Expr(stmt.get(), kPrecedenceLowest, std::string());
- Newline();
- if (stmt->comments()) {
- // Why are before() not printed here too? before() are handled inside
- // Expr(), as are suffix() which are queued to the next Newline().
- // However, because it's a general expression handler, it doesn't insert
- // the newline itself, which only happens between block statements. So,
- // the after are handled explicitly here.
- for (const auto& c : stmt->comments()->after()) {
- TrimAndPrintToken(c);
- Newline();
- }
- }
- if (i < block->statements().size() - 1 &&
- (ShouldAddBlankLineInBetween(block->statements()[i].get(),
- block->statements()[i + 1].get()))) {
- Newline();
- }
- ++i;
- }
-
- if (block->comments()) {
- if (!block->statements().empty() &&
- block->statements().back()->AsBlockComment()) {
- // If the block ends in a comment, and there's a comment following it,
- // then the two comments were originally separate, so keep them that way.
- Newline();
- }
- for (const auto& c : block->comments()->after()) {
- TrimAndPrintToken(c);
- Newline();
- }
- }
-}
-
-int Printer::AssessPenalty(const std::string& output) {
- int penalty = 0;
- std::vector<std::string> lines = base::SplitString(
- output, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
- penalty += static_cast<int>(lines.size() - 1) * GetPenaltyForLineBreak();
- for (const auto& line : lines) {
- if (line.size() > kMaximumWidth)
- penalty += static_cast<int>(line.size() - kMaximumWidth) * kPenaltyExcess;
- }
- return penalty;
-}
-
-bool Printer::ExceedsMaximumWidth(const std::string& output) {
- for (const auto& line : base::SplitString(
- output, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL)) {
- if (line.size() > kMaximumWidth)
- return true;
- }
- return false;
-}
-
-void Printer::AddParen(int prec, int outer_prec, bool* parenthesized) {
- if (prec < outer_prec) {
- Print("(");
- *parenthesized = true;
- }
-}
-
-int Printer::Expr(const ParseNode* root,
- int outer_prec,
- const std::string& suffix) {
- std::string at_end = suffix;
- int penalty = 0;
- penalty_depth_++;
-
- if (root->comments()) {
- if (!root->comments()->before().empty()) {
- Trim();
- // If there's already other text on the line, start a new line.
- if (CurrentColumn() > 0)
- Print("\n");
- // We're printing a line comment, so we need to be at the current margin.
- PrintMargin();
- for (const auto& c : root->comments()->before()) {
- TrimAndPrintToken(c);
- Newline();
- }
- }
- }
-
- bool parenthesized = false;
-
- if (const AccessorNode* accessor = root->AsAccessor()) {
- AddParen(kPrecedenceSuffix, outer_prec, &parenthesized);
- Print(accessor->base().value());
- if (accessor->member()) {
- Print(".");
- Expr(accessor->member(), kPrecedenceLowest, std::string());
- } else {
- CHECK(accessor->index());
- Print("[");
- Expr(accessor->index(), kPrecedenceLowest, "]");
- }
- } else if (const BinaryOpNode* binop = root->AsBinaryOp()) {
- CHECK(precedence_.find(binop->op().value()) != precedence_.end());
- AnnotatePreferredMultilineAssignment(binop);
-
- SortIfSourcesOrDeps(binop);
-
- Precedence prec = precedence_[binop->op().value()];
-
- // Since binary operators format left-to-right, it is ok for the left side
- // use the same operator without parentheses, so the left uses prec. For the
- // same reason, the right side cannot reuse the same operator, or else "x +
- // (y + z)" would format as "x + y + z" which means "(x + y) + z". So, treat
- // the right expression as appearing one precedence level higher.
- // However, because the source parens are not in the parse tree, as a
- // special case for && and || we insert strictly-redundant-but-helpful-for-
- // human-readers parentheses.
- int prec_left = prec;
- int prec_right = prec + 1;
- if (binop->op().value() == "&&" && stack_.back().parent_is_boolean_or) {
- Print("(");
- parenthesized = true;
- } else {
- AddParen(prec_left, outer_prec, &parenthesized);
- }
-
- int start_line = CurrentLine();
- int start_column = CurrentColumn();
- bool is_assignment = binop->op().value() == "=" ||
- binop->op().value() == "+=" ||
- binop->op().value() == "-=";
-
- int indent_column = start_column;
- if (is_assignment) {
- // Default to a double-indent for wrapped assignments.
- indent_column = margin() + kIndentSize * 2;
-
- // A special case for the long lists and scope assignments that are
- // common in .gn files, don't indent them + 4, even though they're just
- // continuations when they're simple lists like "x = [ a, b, c, ... ]" or
- // scopes like "x = { a = 1 b = 2 }". Put back to "normal" indenting.
- const ListNode* right_as_list = binop->right()->AsList();
- if (right_as_list) {
- if (right_as_list->prefer_multiline() ||
- ListWillBeMultiline(right_as_list->contents(),
- right_as_list->End()))
- indent_column = start_column;
- } else {
- const BlockNode* right_as_block = binop->right()->AsBlock();
- if (right_as_block)
- indent_column = start_column;
- }
- }
- if (stack_.back().continuation_requires_indent)
- indent_column += kIndentSize * 2;
-
- stack_.push_back(IndentState(indent_column,
- stack_.back().continuation_requires_indent,
- binop->op().value() == "||"));
- Printer sub_left;
- InitializeSub(&sub_left);
- sub_left.Expr(binop->left(),
- prec_left,
- std::string(" ") + binop->op().value().as_string());
- bool left_is_multiline = CountLines(sub_left.String()) > 1;
- // Avoid walking the whole left redundantly times (see timing of Format.046)
- // so pull the output and comments from subprinter.
- Print(sub_left.String().substr(start_column));
- std::copy(sub_left.comments_.begin(),
- sub_left.comments_.end(),
- std::back_inserter(comments_));
-
- // Single line.
- Printer sub1;
- InitializeSub(&sub1);
- sub1.Print(" ");
- int penalty_current_line =
- sub1.Expr(binop->right(), prec_right, std::string());
- sub1.Print(suffix);
- penalty_current_line += AssessPenalty(sub1.String());
- if (!is_assignment && left_is_multiline) {
- // In e.g. xxx + yyy, if xxx is already multiline, then we want a penalty
- // for trying to continue as if this were one line.
- penalty_current_line +=
- (CountLines(sub1.String()) - 1) * kPenaltyBrokenLineOnOneLiner;
- }
-
- // Break after operator.
- Printer sub2;
- InitializeSub(&sub2);
- sub2.Newline();
- int penalty_next_line =
- sub2.Expr(binop->right(), prec_right, std::string());
- sub2.Print(suffix);
- penalty_next_line += AssessPenalty(sub2.String());
-
- // Force a list on the RHS that would normally be a single line into
- // multiline.
- bool tried_rhs_multiline = false;
- Printer sub3;
- InitializeSub(&sub3);
- int penalty_multiline_rhs_list = std::numeric_limits<int>::max();
- const ListNode* rhs_list = binop->right()->AsList();
- if (is_assignment && rhs_list &&
- !ListWillBeMultiline(rhs_list->contents(), rhs_list->End())) {
- sub3.Print(" ");
- sub3.stack_.push_back(IndentState(start_column, false, false));
- sub3.Sequence(kSequenceStyleList, rhs_list->contents(), rhs_list->End(),
- true);
- sub3.stack_.pop_back();
- penalty_multiline_rhs_list = AssessPenalty(sub3.String());
- tried_rhs_multiline = true;
- }
-
- // If in all cases it was forced past 80col, then we don't break to avoid
- // breaking after '=' in the case of:
- // variable = "... very long string ..."
- // as breaking and indenting doesn't make things much more readable, even
- // though there's fewer characters past the maximum width.
- bool exceeds_maximum_all_ways =
- ExceedsMaximumWidth(sub1.String()) &&
- ExceedsMaximumWidth(sub2.String()) &&
- (!tried_rhs_multiline || ExceedsMaximumWidth(sub3.String()));
-
- if (penalty_current_line < penalty_next_line ||
- exceeds_maximum_all_ways) {
- Print(" ");
- Expr(binop->right(), prec_right, std::string());
- } else if (tried_rhs_multiline &&
- penalty_multiline_rhs_list < penalty_next_line) {
- // Force a multiline list on the right.
- Print(" ");
- stack_.push_back(IndentState(start_column, false, false));
- Sequence(kSequenceStyleList, rhs_list->contents(), rhs_list->End(), true);
- stack_.pop_back();
- } else {
- // Otherwise, put first argument and op, and indent next.
- Newline();
- penalty += std::abs(CurrentColumn() - start_column) *
- kPenaltyHorizontalSeparation;
- Expr(binop->right(), prec_right, std::string());
- }
- stack_.pop_back();
- penalty += (CurrentLine() - start_line) * GetPenaltyForLineBreak();
- } else if (const BlockNode* block = root->AsBlock()) {
- Sequence(
- kSequenceStyleBracedBlock, block->statements(), block->End(), false);
- } else if (const ConditionNode* condition = root->AsConditionNode()) {
- Print("if (");
- // TODO(scottmg): The { needs to be included in the suffix here.
- Expr(condition->condition(), kPrecedenceLowest, ") ");
- Sequence(kSequenceStyleBracedBlock,
- condition->if_true()->statements(),
- condition->if_true()->End(),
- false);
- if (condition->if_false()) {
- Print(" else ");
- // If it's a block it's a bare 'else', otherwise it's an 'else if'. See
- // ConditionNode::Execute.
- bool is_else_if = condition->if_false()->AsBlock() == nullptr;
- if (is_else_if) {
- Expr(condition->if_false(), kPrecedenceLowest, std::string());
- } else {
- Sequence(kSequenceStyleBracedBlock,
- condition->if_false()->AsBlock()->statements(),
- condition->if_false()->AsBlock()->End(),
- false);
- }
- }
- } else if (const FunctionCallNode* func_call = root->AsFunctionCall()) {
- penalty += FunctionCall(func_call, at_end);
- at_end = "";
- } else if (const IdentifierNode* identifier = root->AsIdentifier()) {
- Print(identifier->value().value());
- } else if (const ListNode* list = root->AsList()) {
- bool force_multiline =
- list->prefer_multiline() && !list->contents().empty();
- Sequence(
- kSequenceStyleList, list->contents(), list->End(), force_multiline);
- } else if (const LiteralNode* literal = root->AsLiteral()) {
- Print(literal->value().value());
- } else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) {
- Print(unaryop->op().value());
- Expr(unaryop->operand(), kPrecedenceUnary, std::string());
- } else if (const BlockCommentNode* block_comment = root->AsBlockComment()) {
- Print(block_comment->comment().value());
- } else if (const EndNode* end = root->AsEnd()) {
- Print(end->value().value());
- } else {
- CHECK(false) << "Unhandled case in Expr.";
- }
-
- if (parenthesized)
- Print(")");
-
- // Defer any end of line comment until we reach the newline.
- if (root->comments() && !root->comments()->suffix().empty()) {
- std::copy(root->comments()->suffix().begin(),
- root->comments()->suffix().end(),
- std::back_inserter(comments_));
- }
-
- Print(at_end);
-
- penalty_depth_--;
- return penalty;
-}
-
-template <class PARSENODE>
-void Printer::Sequence(SequenceStyle style,
- const std::vector<std::unique_ptr<PARSENODE>>& list,
- const ParseNode* end,
- bool force_multiline) {
- if (style == kSequenceStyleList)
- Print("[");
- else if (style == kSequenceStyleBracedBlock)
- Print("{");
-
- if (style == kSequenceStyleBlock || style == kSequenceStyleBracedBlock)
- force_multiline = true;
-
- force_multiline |= ListWillBeMultiline(list, end);
-
- if (list.size() == 0 && !force_multiline) {
- // No elements, and not forcing newlines, print nothing.
- } else if (list.size() == 1 && !force_multiline) {
- Print(" ");
- Expr(list[0].get(), kPrecedenceLowest, std::string());
- CHECK(!list[0]->comments() || list[0]->comments()->after().empty());
- Print(" ");
- } else {
- stack_.push_back(IndentState(margin() + kIndentSize,
- style == kSequenceStyleList,
- false));
- size_t i = 0;
- for (const auto& x : list) {
- Newline();
- // If:
- // - we're going to output some comments, and;
- // - we haven't just started this multiline list, and;
- // - there isn't already a blank line here;
- // Then: insert one.
- if (i != 0 && x->comments() && !x->comments()->before().empty() &&
- !HaveBlankLine()) {
- Newline();
- }
- bool body_of_list = i < list.size() - 1 || style == kSequenceStyleList;
- bool want_comma =
- body_of_list && (style == kSequenceStyleList && !x->AsBlockComment());
- Expr(x.get(), kPrecedenceLowest, want_comma ? "," : std::string());
- CHECK(!x->comments() || x->comments()->after().empty());
- if (body_of_list) {
- if (i < list.size() - 1 &&
- ShouldAddBlankLineInBetween(list[i].get(), list[i + 1].get()))
- Newline();
- }
- ++i;
- }
-
- // Trailing comments.
- if (end->comments() && !end->comments()->before().empty()) {
- if (list.size() >= 2)
- Newline();
- for (const auto& c : end->comments()->before()) {
- Newline();
- TrimAndPrintToken(c);
- }
- }
-
- stack_.pop_back();
- Newline();
-
- // Defer any end of line comment until we reach the newline.
- if (end->comments() && !end->comments()->suffix().empty()) {
- std::copy(end->comments()->suffix().begin(),
- end->comments()->suffix().end(),
- std::back_inserter(comments_));
- }
- }
-
- if (style == kSequenceStyleList)
- Print("]");
- else if (style == kSequenceStyleBracedBlock)
- Print("}");
-}
-
-int Printer::FunctionCall(const FunctionCallNode* func_call,
- const std::string& suffix) {
- int start_line = CurrentLine();
- int start_column = CurrentColumn();
- Print(func_call->function().value());
- Print("(");
-
- bool have_block = func_call->block() != nullptr;
- bool force_multiline = false;
-
- const auto& list = func_call->args()->contents();
- const ParseNode* end = func_call->args()->End();
-
- if (end->comments() && !end->comments()->before().empty())
- force_multiline = true;
-
- // If there's before line comments, make sure we have a place to put them.
- for (const auto& i : list) {
- if (i->comments() && !i->comments()->before().empty())
- force_multiline = true;
- }
-
- // Calculate the penalties for 3 possible layouts:
- // 1. all on same line;
- // 2. starting on same line, broken at each comma but paren aligned;
- // 3. broken to next line + 4, broken at each comma.
- std::string terminator = ")";
- if (have_block)
- terminator += " {";
- terminator += suffix;
-
- // Special case to make function calls of one arg taking a long list of
- // boolean operators not indent.
- bool continuation_requires_indent =
- list.size() != 1 || !list[0]->AsBinaryOp();
-
- // 1: Same line.
- Printer sub1;
- InitializeSub(&sub1);
- sub1.stack_.push_back(
- IndentState(CurrentColumn(), continuation_requires_indent, false));
- int penalty_one_line = 0;
- for (size_t i = 0; i < list.size(); ++i) {
- penalty_one_line += sub1.Expr(list[i].get(), kPrecedenceLowest,
- i < list.size() - 1 ? ", " : std::string());
- }
- sub1.Print(terminator);
- penalty_one_line += AssessPenalty(sub1.String());
- // This extra penalty prevents a short second argument from being squeezed in
- // after a first argument that went multiline (and instead preferring a
- // variant below).
- penalty_one_line +=
- (CountLines(sub1.String()) - 1) * kPenaltyBrokenLineOnOneLiner;
-
- // 2: Starting on same line, broken at commas.
- Printer sub2;
- InitializeSub(&sub2);
- sub2.stack_.push_back(
- IndentState(CurrentColumn(), continuation_requires_indent, false));
- int penalty_multiline_start_same_line = 0;
- for (size_t i = 0; i < list.size(); ++i) {
- penalty_multiline_start_same_line +=
- sub2.Expr(list[i].get(), kPrecedenceLowest,
- i < list.size() - 1 ? "," : std::string());
- if (i < list.size() - 1) {
- sub2.Newline();
- }
- }
- sub2.Print(terminator);
- penalty_multiline_start_same_line += AssessPenalty(sub2.String());
-
- // 3: Starting on next line, broken at commas.
- Printer sub3;
- InitializeSub(&sub3);
- sub3.stack_.push_back(IndentState(margin() + kIndentSize * 2,
- continuation_requires_indent, false));
- sub3.Newline();
- int penalty_multiline_start_next_line = 0;
- for (size_t i = 0; i < list.size(); ++i) {
- if (i == 0) {
- penalty_multiline_start_next_line +=
- std::abs(sub3.CurrentColumn() - start_column) *
- kPenaltyHorizontalSeparation;
- }
- penalty_multiline_start_next_line +=
- sub3.Expr(list[i].get(), kPrecedenceLowest,
- i < list.size() - 1 ? "," : std::string());
- if (i < list.size() - 1) {
- sub3.Newline();
- }
- }
- sub3.Print(terminator);
- penalty_multiline_start_next_line += AssessPenalty(sub3.String());
-
- int penalty = penalty_multiline_start_next_line;
- bool fits_on_current_line = false;
- if (penalty_one_line < penalty_multiline_start_next_line ||
- penalty_multiline_start_same_line < penalty_multiline_start_next_line) {
- fits_on_current_line = true;
- penalty = penalty_one_line;
- if (penalty_multiline_start_same_line < penalty_one_line) {
- penalty = penalty_multiline_start_same_line;
- force_multiline = true;
- }
- } else {
- force_multiline = true;
- }
-
- if (list.size() == 0 && !force_multiline) {
- // No elements, and not forcing newlines, print nothing.
- } else {
- if (penalty_multiline_start_next_line < penalty_multiline_start_same_line) {
- stack_.push_back(IndentState(margin() + kIndentSize * 2,
- continuation_requires_indent,
- false));
- Newline();
- } else {
- stack_.push_back(
- IndentState(CurrentColumn(), continuation_requires_indent, false));
- }
-
- for (size_t i = 0; i < list.size(); ++i) {
- const auto& x = list[i];
- if (i > 0) {
- if (fits_on_current_line && !force_multiline)
- Print(" ");
- else
- Newline();
- }
- bool want_comma = i < list.size() - 1 && !x->AsBlockComment();
- Expr(x.get(), kPrecedenceLowest, want_comma ? "," : std::string());
- CHECK(!x->comments() || x->comments()->after().empty());
- if (i < list.size() - 1) {
- if (!want_comma)
- Newline();
- }
- }
-
- // Trailing comments.
- if (end->comments() && !end->comments()->before().empty()) {
- if (!list.empty())
- Newline();
- for (const auto& c : end->comments()->before()) {
- Newline();
- TrimAndPrintToken(c);
- }
- Newline();
- }
- stack_.pop_back();
- }
-
- // Defer any end of line comment until we reach the newline.
- if (end->comments() && !end->comments()->suffix().empty()) {
- std::copy(end->comments()->suffix().begin(),
- end->comments()->suffix().end(), std::back_inserter(comments_));
- }
-
- Print(")");
- Print(suffix);
-
- if (have_block) {
- Print(" ");
- Sequence(kSequenceStyleBracedBlock,
- func_call->block()->statements(),
- func_call->block()->End(),
- false);
- }
- return penalty + (CurrentLine() - start_line) * GetPenaltyForLineBreak();
-}
-
-void Printer::InitializeSub(Printer* sub) {
- sub->stack_ = stack_;
- sub->comments_ = comments_;
- sub->penalty_depth_ = penalty_depth_;
- sub->Print(std::string(CurrentColumn(), 'x'));
-}
-
-template <class PARSENODE>
-bool Printer::ListWillBeMultiline(
- const std::vector<std::unique_ptr<PARSENODE>>& list,
- const ParseNode* end) {
- if (list.size() > 1)
- return true;
-
- if (end && end->comments() && !end->comments()->before().empty())
- return true;
-
- // If there's before line comments, make sure we have a place to put them.
- for (const auto& i : list) {
- if (i->comments() && !i->comments()->before().empty())
- return true;
- }
-
- // When a scope is used as a list entry, it's too complicated to go one a
- // single line (the block will always be formatted multiline itself).
- if (list.size() >= 1 && list[0]->AsBlock())
- return true;
-
- return false;
-}
-
-void DoFormat(const ParseNode* root, bool dump_tree, std::string* output) {
- if (dump_tree) {
- std::ostringstream os;
- root->Print(os, 0);
- fprintf(stderr, "%s", os.str().c_str());
- }
- Printer pr;
- pr.Block(root);
- *output = pr.String();
-}
-
-std::string ReadStdin() {
- static const int kBufferSize = 256;
- char buffer[kBufferSize];
- std::string result;
- while (true) {
- char* input = nullptr;
- input = fgets(buffer, kBufferSize, stdin);
- if (input == nullptr && feof(stdin))
- return result;
- int length = static_cast<int>(strlen(buffer));
- if (length == 0)
- return result;
- else
- result += std::string(buffer, length);
- }
-}
-
-} // namespace
-
-bool FormatFileToString(Setup* setup,
- const SourceFile& file,
- bool dump_tree,
- std::string* output) {
- Err err;
- const ParseNode* parse_node =
- setup->scheduler().input_file_manager()->SyncLoadFile(
- LocationRange(), &setup->build_settings(), file, &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
- DoFormat(parse_node, dump_tree, output);
- return true;
-}
-
-bool FormatStringToString(const std::string& input,
- bool dump_tree,
- std::string* output) {
- SourceFile source_file;
- InputFile file(source_file);
- file.SetContents(input);
- Err err;
- // Tokenize.
- std::vector<Token> tokens = Tokenizer::Tokenize(&file, &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
-
- // Parse.
- std::unique_ptr<ParseNode> parse_node = Parser::Parse(tokens, &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
-
- DoFormat(parse_node.get(), dump_tree, output);
- return true;
-}
-
-int RunFormat(const std::vector<std::string>& args) {
- bool dry_run =
- base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchDryRun);
- bool dump_tree =
- base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchDumpTree);
- bool from_stdin =
- base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchStdin);
-
- if (dry_run) {
- // --dry-run only works with an actual file to compare to.
- from_stdin = false;
- }
-
- if (from_stdin) {
- if (args.size() != 0) {
- Err(Location(), "Expecting no arguments when reading from stdin.\n")
- .PrintToStdout();
- return 1;
- }
- std::string input = ReadStdin();
- std::string output;
- if (!FormatStringToString(input, dump_tree, &output))
- return 1;
- printf("%s", output.c_str());
- return 0;
- }
-
- // TODO(scottmg): Eventually, this should be a list/spec of files, and they
- // should all be done in parallel.
- if (args.size() != 1) {
- Err(Location(), "Expecting exactly one argument, see `gn help format`.\n")
- .PrintToStdout();
- return 1;
- }
-
- Setup setup;
- SourceDir source_dir =
- SourceDirForCurrentDirectory(setup.build_settings().root_path());
-
- Err err;
- SourceFile file = source_dir.ResolveRelativeFile(Value(nullptr, args[0]),
- &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return 1;
- }
-
- std::string output_string;
- if (FormatFileToString(&setup, file, dump_tree, &output_string)) {
- if (!dump_tree) {
- // Update the file in-place.
- base::FilePath to_write = setup.build_settings().GetFullPath(file);
- std::string original_contents;
- if (!base::ReadFileToString(to_write, &original_contents)) {
- Err(Location(), std::string("Couldn't read \"") +
- to_write.AsUTF8Unsafe() +
- std::string("\" for comparison.")).PrintToStdout();
- return 1;
- }
- if (dry_run)
- return original_contents == output_string ? 0 : 2;
- if (original_contents != output_string) {
- if (base::WriteFile(to_write,
- output_string.data(),
- static_cast<int>(output_string.size())) == -1) {
- Err(Location(),
- std::string("Failed to write formatted output back to \"") +
- to_write.AsUTF8Unsafe() + std::string("\".")).PrintToStdout();
- return 1;
- }
- printf("Wrote formatted to '%s'.\n", to_write.AsUTF8Unsafe().c_str());
- }
- }
- }
-
- return 0;
-}
-
-} // namespace commands
diff --git a/chromium/tools/gn/command_format.h b/chromium/tools/gn/command_format.h
deleted file mode 100644
index 97c3e4ca6f8..00000000000
--- a/chromium/tools/gn/command_format.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_COMAND_FORMAT_H_
-#define TOOLS_GN_COMAND_FORMAT_H_
-
-#include <string>
-
-class Setup;
-class SourceFile;
-
-namespace commands {
-
-bool FormatFileToString(Setup* setup,
- const SourceFile& file,
- bool dump_tree,
- std::string* output);
-
-bool FormatStringToString(const std::string& input,
- bool dump_tree,
- std::string* output);
-
-} // namespace commands
-
-#endif // TOOLS_GN_COMAND_FORMAT_H_
-
diff --git a/chromium/tools/gn/command_format_unittest.cc b/chromium/tools/gn/command_format_unittest.cc
deleted file mode 100644
index 1780eb4c7c8..00000000000
--- a/chromium/tools/gn/command_format_unittest.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/command_format.h"
-
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "base/strings/string_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/setup.h"
-#include "tools/gn/test_with_scheduler.h"
-
-using FormatTest = TestWithScheduler;
-
-#define FORMAT_TEST(n) \
- TEST_F(FormatTest, n) { \
- ::Setup setup; \
- std::string out; \
- std::string expected; \
- base::FilePath src_dir; \
- base::PathService::Get(base::DIR_SOURCE_ROOT, &src_dir); \
- base::SetCurrentDirectory(src_dir); \
- EXPECT_TRUE(commands::FormatFileToString( \
- &setup, SourceFile("//tools/gn/format_test_data/" #n ".gn"), false, \
- &out)); \
- ASSERT_TRUE(base::ReadFileToString( \
- base::FilePath(FILE_PATH_LITERAL("tools/gn/format_test_data/") \
- FILE_PATH_LITERAL(#n) \
- FILE_PATH_LITERAL(".golden")), \
- &expected)); \
- EXPECT_EQ(expected, out); \
- }
-
-// These are expanded out this way rather than a runtime loop so that
-// --gtest_filter works as expected for individual test running.
-FORMAT_TEST(001)
-FORMAT_TEST(002)
-FORMAT_TEST(003)
-FORMAT_TEST(004)
-FORMAT_TEST(005)
-FORMAT_TEST(006)
-FORMAT_TEST(007)
-FORMAT_TEST(008)
-FORMAT_TEST(009)
-FORMAT_TEST(010)
-FORMAT_TEST(011)
-FORMAT_TEST(012)
-FORMAT_TEST(013)
-FORMAT_TEST(014)
-FORMAT_TEST(015)
-FORMAT_TEST(016)
-FORMAT_TEST(017)
-FORMAT_TEST(018)
-FORMAT_TEST(019)
-FORMAT_TEST(020)
-FORMAT_TEST(021)
-FORMAT_TEST(022)
-FORMAT_TEST(023)
-FORMAT_TEST(024)
-FORMAT_TEST(025)
-FORMAT_TEST(026)
-FORMAT_TEST(027)
-FORMAT_TEST(028)
-FORMAT_TEST(029)
-FORMAT_TEST(030)
-FORMAT_TEST(031)
-FORMAT_TEST(032)
-FORMAT_TEST(033)
-// TODO(scottmg): args+rebase_path unnecessarily split: FORMAT_TEST(034)
-FORMAT_TEST(035)
-FORMAT_TEST(036)
-FORMAT_TEST(037)
-FORMAT_TEST(038)
-FORMAT_TEST(039)
-// TODO(scottmg): Bad break, exceeding 80 col: FORMAT_TEST(040)
-FORMAT_TEST(041)
-FORMAT_TEST(042)
-FORMAT_TEST(043)
-// TODO(scottmg): Dewrapped caused exceeding 80 col: FORMAT_TEST(044)
-FORMAT_TEST(045)
-FORMAT_TEST(046)
-FORMAT_TEST(047)
-FORMAT_TEST(048)
-// TODO(scottmg): Eval is broken (!) and comment output might have extra ,
-// FORMAT_TEST(049)
-FORMAT_TEST(050)
-FORMAT_TEST(051)
-FORMAT_TEST(052)
-FORMAT_TEST(053)
-FORMAT_TEST(054)
-FORMAT_TEST(055)
-FORMAT_TEST(056)
-FORMAT_TEST(057)
-FORMAT_TEST(058)
-FORMAT_TEST(059)
-FORMAT_TEST(060)
-FORMAT_TEST(061)
-FORMAT_TEST(062)
-FORMAT_TEST(063)
-FORMAT_TEST(064)
-FORMAT_TEST(065)
-FORMAT_TEST(066)
-FORMAT_TEST(067)
-FORMAT_TEST(068)
-FORMAT_TEST(069)
-FORMAT_TEST(070)
diff --git a/chromium/tools/gn/command_gen.cc b/chromium/tools/gn/command_gen.cc
deleted file mode 100644
index ca6587761fd..00000000000
--- a/chromium/tools/gn/command_gen.cc
+++ /dev/null
@@ -1,477 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/atomicops.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/timer/elapsed_timer.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/eclipse_writer.h"
-#include "tools/gn/json_project_writer.h"
-#include "tools/gn/ninja_target_writer.h"
-#include "tools/gn/ninja_writer.h"
-#include "tools/gn/qt_creator_writer.h"
-#include "tools/gn/runtime_deps.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/setup.h"
-#include "tools/gn/standard_out.h"
-#include "tools/gn/switches.h"
-#include "tools/gn/target.h"
-#include "tools/gn/visual_studio_writer.h"
-#include "tools/gn/xcode_writer.h"
-
-namespace commands {
-
-namespace {
-
-const char kSwitchCheck[] = "check";
-const char kSwitchFilters[] = "filters";
-const char kSwitchIde[] = "ide";
-const char kSwitchIdeValueEclipse[] = "eclipse";
-const char kSwitchIdeValueQtCreator[] = "qtcreator";
-const char kSwitchIdeValueVs[] = "vs";
-const char kSwitchIdeValueVs2013[] = "vs2013";
-const char kSwitchIdeValueVs2015[] = "vs2015";
-const char kSwitchIdeValueVs2017[] = "vs2017";
-const char kSwitchIdeValueWinSdk[] = "winsdk";
-const char kSwitchIdeValueXcode[] = "xcode";
-const char kSwitchIdeValueJson[] = "json";
-const char kSwitchNinjaExtraArgs[] = "ninja-extra-args";
-const char kSwitchNoDeps[] = "no-deps";
-const char kSwitchRootTarget[] = "root-target";
-const char kSwitchSln[] = "sln";
-const char kSwitchWorkspace[] = "workspace";
-const char kSwitchJsonFileName[] = "json-file-name";
-const char kSwitchJsonIdeScript[] = "json-ide-script";
-const char kSwitchJsonIdeScriptArgs[] = "json-ide-script-args";
-
-// Collects Ninja rules for each toolchain. The lock protectes the rules.
-struct TargetWriteInfo {
- base::Lock lock;
- NinjaWriter::PerToolchainRules rules;
-};
-
-// Called on worker thread to write the ninja file.
-void BackgroundDoWrite(TargetWriteInfo* write_info, const Target* target) {
- std::string rule = NinjaTargetWriter::RunAndWriteFile(target);
- DCHECK(!rule.empty());
-
- {
- base::AutoLock lock(write_info->lock);
- write_info->rules[target->toolchain()].emplace_back(
- target, std::move(rule));
- }
-}
-
-// Called on the main thread.
-void ItemResolvedAndGeneratedCallback(TargetWriteInfo* write_info,
- const BuilderRecord* record) {
- const Item* item = record->item();
- const Target* target = item->AsTarget();
- if (target) {
- g_scheduler->ScheduleWork(base::Bind(&BackgroundDoWrite,
- write_info, target));
- }
-}
-
-// Returns a pointer to the target with the given file as an output, or null
-// if no targets generate the file. This is brute force since this is an
-// error condition and performance shouldn't matter.
-const Target* FindTargetThatGeneratesFile(const Builder& builder,
- const SourceFile& file) {
- std::vector<const Target*> targets = builder.GetAllResolvedTargets();
- if (targets.empty())
- return nullptr;
-
- OutputFile output_file(targets[0]->settings()->build_settings(), file);
- for (const Target* target : targets) {
- for (const auto& cur_output : target->computed_outputs()) {
- if (cur_output == output_file)
- return target;
- }
- }
- return nullptr;
-}
-
-// Prints an error that the given file was present as a source or input in
-// the given target(s) but was not generated by any of its dependencies.
-void PrintInvalidGeneratedInput(const Builder& builder,
- const SourceFile& file,
- const std::vector<const Target*>& targets) {
- std::string err;
-
- // Only show the toolchain labels (which can be confusing) if something
- // isn't the default.
- bool show_toolchains = false;
- const Label& default_toolchain =
- targets[0]->settings()->default_toolchain_label();
- for (const Target* target : targets) {
- if (target->settings()->toolchain_label() != default_toolchain) {
- show_toolchains = true;
- break;
- }
- }
-
- const Target* generator = FindTargetThatGeneratesFile(builder, file);
- if (generator &&
- generator->settings()->toolchain_label() != default_toolchain)
- show_toolchains = true;
-
- const std::string target_str = targets.size() > 1 ? "targets" : "target";
- err += "The file:\n";
- err += " " + file.value() + "\n";
- err += "is listed as an input or source for the " + target_str + ":\n";
- for (const Target* target : targets)
- err += " " + target->label().GetUserVisibleName(show_toolchains) + "\n";
-
- if (generator) {
- err += "but this file was not generated by any dependencies of the " +
- target_str + ". The target\nthat generates the file is:\n ";
- err += generator->label().GetUserVisibleName(show_toolchains);
- } else {
- err += "but no targets in the build generate that file.";
- }
-
- Err(Location(), "Input to " + target_str + " not generated by a dependency.",
- err).PrintToStdout();
-}
-
-bool CheckForInvalidGeneratedInputs(Setup* setup) {
- std::multimap<SourceFile, const Target*> unknown_inputs =
- g_scheduler->GetUnknownGeneratedInputs();
- if (unknown_inputs.empty())
- return true; // No bad files.
-
- int errors_found = 0;
- auto cur = unknown_inputs.begin();
- while (cur != unknown_inputs.end()) {
- errors_found++;
- auto end_of_range = unknown_inputs.upper_bound(cur->first);
-
- // Package the values more conveniently for printing.
- SourceFile bad_input = cur->first;
- std::vector<const Target*> targets;
- while (cur != end_of_range)
- targets.push_back((cur++)->second);
-
- PrintInvalidGeneratedInput(setup->builder(), bad_input, targets);
- OutputString("\n");
- }
-
- OutputString(
- "If you have generated inputs, there needs to be a dependency path "
- "between the\ntwo targets in addition to just listing the files. For "
- "indirect dependencies,\nthe intermediate ones must be public_deps. "
- "data_deps don't count since they're\nonly runtime dependencies. If "
- "you think a dependency chain exists, it might be\nbecause the chain "
- "is private. Try \"gn path\" to analyze.\n");
-
- if (errors_found > 1) {
- OutputString(base::StringPrintf("\n%d generated input errors found.\n",
- errors_found), DECORATION_YELLOW);
- }
- return false;
-}
-
-bool RunIdeWriter(const std::string& ide,
- const BuildSettings* build_settings,
- const Builder& builder,
- Err* err) {
- const base::CommandLine* command_line =
- base::CommandLine::ForCurrentProcess();
- bool quiet = command_line->HasSwitch(switches::kQuiet);
- base::ElapsedTimer timer;
-
- if (ide == kSwitchIdeValueEclipse) {
- bool res = EclipseWriter::RunAndWriteFile(build_settings, builder, err);
- if (res && !quiet) {
- OutputString("Generating Eclipse settings took " +
- base::Int64ToString(timer.Elapsed().InMilliseconds()) +
- "ms\n");
- }
- return res;
- } else if (ide == kSwitchIdeValueVs || ide == kSwitchIdeValueVs2013 ||
- ide == kSwitchIdeValueVs2015 || ide == kSwitchIdeValueVs2017) {
- VisualStudioWriter::Version version = VisualStudioWriter::Version::Vs2017;
- if (ide == kSwitchIdeValueVs2013)
- version = VisualStudioWriter::Version::Vs2013;
- else if (ide == kSwitchIdeValueVs2015)
- version = VisualStudioWriter::Version::Vs2015;
-
- std::string sln_name;
- if (command_line->HasSwitch(kSwitchSln))
- sln_name = command_line->GetSwitchValueASCII(kSwitchSln);
- std::string filters;
- if (command_line->HasSwitch(kSwitchFilters))
- filters = command_line->GetSwitchValueASCII(kSwitchFilters);
- std::string win_kit;
- if (command_line->HasSwitch(kSwitchIdeValueWinSdk))
- win_kit = command_line->GetSwitchValueASCII(kSwitchIdeValueWinSdk);
- std::string ninja_extra_args;
- if (command_line->HasSwitch(kSwitchNinjaExtraArgs))
- ninja_extra_args =
- command_line->GetSwitchValueASCII(kSwitchNinjaExtraArgs);
- bool no_deps = command_line->HasSwitch(kSwitchNoDeps);
- bool res = VisualStudioWriter::RunAndWriteFiles(
- build_settings, builder, version, sln_name, filters, win_kit,
- ninja_extra_args, no_deps, err);
- if (res && !quiet) {
- OutputString("Generating Visual Studio projects took " +
- base::Int64ToString(timer.Elapsed().InMilliseconds()) +
- "ms\n");
- }
- return res;
- } else if (ide == kSwitchIdeValueXcode) {
- bool res = XcodeWriter::RunAndWriteFiles(
- command_line->GetSwitchValueASCII(kSwitchWorkspace),
- command_line->GetSwitchValueASCII(kSwitchRootTarget),
- command_line->GetSwitchValueASCII(kSwitchNinjaExtraArgs),
- command_line->GetSwitchValueASCII(kSwitchFilters), build_settings,
- builder, err);
- if (res && !quiet) {
- OutputString("Generating Xcode projects took " +
- base::Int64ToString(timer.Elapsed().InMilliseconds()) +
- "ms\n");
- }
- return res;
- } else if (ide == kSwitchIdeValueQtCreator) {
- std::string root_target;
- if (command_line->HasSwitch(kSwitchRootTarget))
- root_target = command_line->GetSwitchValueASCII(kSwitchRootTarget);
- bool res = QtCreatorWriter::RunAndWriteFile(build_settings, builder, err,
- root_target);
- if (res && !quiet) {
- OutputString("Generating QtCreator projects took " +
- base::Int64ToString(timer.Elapsed().InMilliseconds()) +
- "ms\n");
- }
- return res;
- } else if (ide == kSwitchIdeValueJson) {
- std::string file_name =
- command_line->GetSwitchValueASCII(kSwitchJsonFileName);
- if (file_name.empty())
- file_name = "project.json";
- std::string exec_script =
- command_line->GetSwitchValueASCII(kSwitchJsonIdeScript);
- std::string exec_script_extra_args =
- command_line->GetSwitchValueASCII(kSwitchJsonIdeScriptArgs);
- std::string filters = command_line->GetSwitchValueASCII(kSwitchFilters);
-
- bool res = JSONProjectWriter::RunAndWriteFiles(
- build_settings, builder, file_name, exec_script, exec_script_extra_args,
- filters, quiet, err);
- if (res && !quiet) {
- OutputString("Generating JSON projects took " +
- base::Int64ToString(timer.Elapsed().InMilliseconds()) +
- "ms\n");
- }
- return res;
- }
-
- *err = Err(Location(), "Unknown IDE: " + ide);
- return false;
-}
-
-} // namespace
-
-const char kGen[] = "gen";
-const char kGen_HelpShort[] = "gen: Generate ninja files.";
-const char kGen_Help[] =
- R"(gn gen [--check] [<ide options>] <out_dir>
-
- Generates ninja files from the current tree and puts them in the given output
- directory.
-
- The output directory can be a source-repo-absolute path name such as:
- //out/foo
- Or it can be a directory relative to the current directory such as:
- out/foo
-
- "gn gen --check" is the same as running "gn check". See "gn help check"
- for documentation on that mode.
-
- See "gn help switches" for the common command-line switches.
-
-IDE options
-
- GN optionally generates files for IDE. Possibilities for <ide options>
-
- --ide=<ide_name>
- Generate files for an IDE. Currently supported values:
- "eclipse" - Eclipse CDT settings file.
- "vs" - Visual Studio project/solution files.
- (default Visual Studio version: 2017)
- "vs2013" - Visual Studio 2013 project/solution files.
- "vs2015" - Visual Studio 2015 project/solution files.
- "vs2017" - Visual Studio 2017 project/solution files.
- "xcode" - Xcode workspace/solution files.
- "qtcreator" - QtCreator project files.
- "json" - JSON file containing target information
-
- --filters=<path_prefixes>
- Semicolon-separated list of label patterns used to limit the set of
- generated projects (see "gn help label_pattern"). Only matching targets
- and their dependencies will be included in the solution. Only used for
- Visual Studio, Xcode and JSON.
-
-Visual Studio Flags
-
- --sln=<file_name>
- Override default sln file name ("all"). Solution file is written to the
- root build directory.
-
- --no-deps
- Don't include targets dependencies to the solution. Changes the way how
- --filters option works. Only directly matching targets are included.
-
- --winsdk=<sdk_version>
- Use the specified Windows 10 SDK version to generate project files.
- As an example, "10.0.15063.0" can be specified to use Creators Update SDK
- instead of the default one.
-
- --ninja-extra-args=<string>
- This string is passed without any quoting to the ninja invocation
- command-line. Can be used to configure ninja flags, like "-j".
-
-Xcode Flags
-
- --workspace=<file_name>
- Override defaut workspace file name ("all"). The workspace file is
- written to the root build directory.
-
- --ninja-extra-args=<string>
- This string is passed without any quoting to the ninja invocation
- command-line. Can be used to configure ninja flags, like "-j".
-
- --root-target=<target_name>
- Name of the target corresponding to "All" target in Xcode. If unset,
- "All" invokes ninja without any target and builds everything.
-
-QtCreator Flags
-
- --root-target=<target_name>
- Name of the root target for which the QtCreator project will be generated
- to contain files of it and its dependencies. If unset, the whole build
- graph will be emitted.
-
-
-Eclipse IDE Support
-
- GN DOES NOT generate Eclipse CDT projects. Instead, it generates a settings
- file which can be imported into an Eclipse CDT project. The XML file contains
- a list of include paths and defines. Because GN does not generate a full
- .cproject definition, it is not possible to properly define includes/defines
- for each file individually. Instead, one set of includes/defines is generated
- for the entire project. This works fairly well but may still result in a few
- indexer issues here and there.
-
-Generic JSON Output
-
- Dumps target information to a JSON file and optionally invokes a
- python script on the generated file. See the comments at the beginning
- of json_project_writer.cc and desc_builder.cc for an overview of the JSON
- file format.
-
- --json-file-name=<json_file_name>
- Overrides default file name (project.json) of generated JSON file.
-
- --json-ide-script=<path_to_python_script>
- Executes python script after the JSON file is generated. Path can be
- project absolute (//), system absolute (/) or relative, in which case the
- output directory will be base. Path to generated JSON file will be first
- argument when invoking script.
-
- --json-ide-script-args=<argument>
- Optional second argument that will passed to executed script.
-)";
-
-int RunGen(const std::vector<std::string>& args) {
- base::ElapsedTimer timer;
-
- if (args.size() != 1) {
- Err(Location(), "Need exactly one build directory to generate.",
- "I expected something more like \"gn gen out/foo\"\n"
- "You can also see \"gn help gen\".").PrintToStdout();
- return 1;
- }
-
- // Deliberately leaked to avoid expensive process teardown.
- Setup* setup = new Setup();
- if (!setup->DoSetup(args[0], true))
- return 1;
-
- const base::CommandLine* command_line =
- base::CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(kSwitchCheck))
- setup->set_check_public_headers(true);
-
- // Cause the load to also generate the ninja files for each target.
- TargetWriteInfo write_info;
- setup->builder().set_resolved_and_generated_callback(
- base::Bind(&ItemResolvedAndGeneratedCallback, &write_info));
-
- // Do the actual load. This will also write out the target ninja files.
- if (!setup->Run())
- return 1;
-
- // Sort the targets in each toolchain according to their label. This makes
- // the ninja files have deterministic content.
- for (auto& cur_toolchain : write_info.rules) {
- std::sort(cur_toolchain.second.begin(), cur_toolchain.second.end(),
- [](const NinjaWriter::TargetRulePair& a,
- const NinjaWriter::TargetRulePair& b) {
- return a.first->label() < b.first->label();
- });
- }
-
- Err err;
- // Write the root ninja files.
- if (!NinjaWriter::RunAndWriteFiles(&setup->build_settings(),
- setup->builder(),
- write_info.rules,
- &err)) {
- err.PrintToStdout();
- return 1;
- }
-
- if (!WriteRuntimeDepsFilesIfNecessary(setup->builder(), &err)) {
- err.PrintToStdout();
- return 1;
- }
-
- if (!CheckForInvalidGeneratedInputs(setup))
- return 1;
-
- if (command_line->HasSwitch(kSwitchIde) &&
- !RunIdeWriter(command_line->GetSwitchValueASCII(kSwitchIde),
- &setup->build_settings(), setup->builder(), &err)) {
- err.PrintToStdout();
- return 1;
- }
-
- base::TimeDelta elapsed_time = timer.Elapsed();
-
- if (!command_line->HasSwitch(switches::kQuiet)) {
- OutputString("Done. ", DECORATION_GREEN);
-
- size_t targets_collected = 0;
- for (const auto& rules : write_info.rules)
- targets_collected += rules.second.size();
-
- std::string stats =
- "Made " + base::NumberToString(targets_collected) + " targets from " +
- base::IntToString(
- setup->scheduler().input_file_manager()->GetInputFileCount()) +
- " files in " + base::Int64ToString(elapsed_time.InMilliseconds()) +
- "ms\n";
- OutputString(stats);
- }
-
- return 0;
-}
-
-} // namespace commands
diff --git a/chromium/tools/gn/command_help.cc b/chromium/tools/gn/command_help.cc
deleted file mode 100644
index a6777cfe692..00000000000
--- a/chromium/tools/gn/command_help.cc
+++ /dev/null
@@ -1,316 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <iostream>
-
-#include "base/command_line.h"
-#include "tools/gn/args.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/err.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/input_conversion.h"
-#include "tools/gn/label.h"
-#include "tools/gn/label_pattern.h"
-#include "tools/gn/ninja_build_writer.h"
-#include "tools/gn/parser.h"
-#include "tools/gn/runtime_deps.h"
-#include "tools/gn/setup.h"
-#include "tools/gn/standard_out.h"
-#include "tools/gn/string_utils.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/switches.h"
-#include "tools/gn/target.h"
-#include "tools/gn/variables.h"
-
-namespace commands {
-
-namespace {
-
-void PrintToplevelHelp() {
- PrintSectionHelp("Commands", "<command>", "commands");
- for (const auto& cmd : commands::GetCommands())
- PrintShortHelp(cmd.second.help_short);
-
- // Target declarations.
- PrintSectionHelp("Target declarations", "<function>", "targets");
- for (const auto& func : functions::GetFunctions()) {
- if (func.second.is_target)
- PrintShortHelp(func.second.help_short);
- }
-
- // Functions.
- PrintSectionHelp("Buildfile functions", "<function>", "functions");
- for (const auto& func : functions::GetFunctions()) {
- if (!func.second.is_target)
- PrintShortHelp(func.second.help_short);
- }
-
- // Built-in variables.
- PrintSectionHelp("Built-in predefined variables", "<variable>",
- "predefined_variables");
- for (const auto& builtin : variables::GetBuiltinVariables())
- PrintShortHelp(builtin.second.help_short);
-
- // Target variables.
- PrintSectionHelp("Variables you set in targets", "<variable>",
- "target_variables");
- for (const auto& target : variables::GetTargetVariables())
- PrintShortHelp(target.second.help_short);
-
- PrintSectionHelp("Other help topics", "", "other");
- PrintShortHelp("all: Print all the help at once");
- PrintShortHelp("buildargs: How build arguments work.");
- PrintShortHelp("dotfile: Info about the toplevel .gn file.");
- PrintShortHelp("execution: Build graph and execution overview.");
- PrintShortHelp("grammar: Language and grammar for GN build files.");
- PrintShortHelp(
- "input_conversion: Processing input from exec_script and read_file.");
- PrintShortHelp("label_pattern: Matching more than one label.");
- PrintShortHelp("labels: About labels.");
- PrintShortHelp("ninja_rules: How Ninja build rules are named.");
- PrintShortHelp("nogncheck: Annotating includes for checking.");
- PrintShortHelp("runtime_deps: How runtime dependency computation works.");
- PrintShortHelp("source_expansion: Map sources to outputs for scripts.");
- PrintShortHelp("switches: Show available command-line switches.");
-}
-
-void PrintSwitchHelp() {
- const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
- bool is_markdown = cmdline->HasSwitch(switches::kMarkdown);
-
- OutputString("Available global switches\n", DECORATION_YELLOW);
- OutputString(
- " Do \"gn help --the_switch_you_want_help_on\" for more. Individual\n"
- " commands may take command-specific switches not listed here. See the\n"
- " help on your specific command for more.\n\n");
-
- if (is_markdown)
- OutputString("```\n", DECORATION_NONE);
-
- for (const auto& s : switches::GetSwitches())
- PrintShortHelp(s.second.short_help);
-
- if (is_markdown)
- OutputString("```\n", DECORATION_NONE);
-
- OutputString("\n");
-}
-
-void PrintAllHelp() {
- const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
- bool is_markdown = cmdline->HasSwitch(switches::kMarkdown);
-
- if (is_markdown) {
- OutputString("# GN Reference\n\n");
- OutputString("*This page is automatically generated from* "
- "`gn help --markdown all`.\n\n");
-
- // Generate our own table of contents so that we have more control
- // over what's in and out.
- OutputString("## Contents\n\n");
- }
-
- PrintToplevelHelp();
-
- OutputString("\n");
-
- if (is_markdown)
- OutputString("## <a name=\"commands\"></a>Commands\n\n");
- for (const auto& c: commands::GetCommands())
- PrintLongHelp(c.second.help);
-
- if (is_markdown)
- OutputString("## <a name=\"targets\"></a>Target declarations\n\n");
- for (const auto& f : functions::GetFunctions()) {
- if (f.second.is_target)
- PrintLongHelp(f.second.help);
- }
-
- if (is_markdown)
- OutputString("## <a name=\"functions\"></a>Buildfile functions\n\n");
- for (const auto& f : functions::GetFunctions()) {
- if (!f.second.is_target)
- PrintLongHelp(f.second.help);
- }
-
- if (is_markdown) {
- OutputString(
- "## <a name=\"predefined_variables\"></a>"
- "Built-in predefined variables\n\n");
- }
- for (const auto& v: variables::GetBuiltinVariables())
- PrintLongHelp(v.second.help);
-
- if (is_markdown) {
- OutputString(
- "## <a name=\"target_variables\"></a>"
- "Variables you set in targets\n\n");
- }
- for (const auto& v: variables::GetTargetVariables())
- PrintLongHelp(v.second.help);
-
- if (is_markdown)
- OutputString("## <a name=\"other\"></a>Other help topics\n\n");
- PrintLongHelp(kBuildArgs_Help, "buildargs");
- PrintLongHelp(kDotfile_Help, "dotfile");
- PrintLongHelp(kExecution_Help, "execution");
- PrintLongHelp(kGrammar_Help, "grammar");
- PrintLongHelp(kInputConversion_Help, "input_conversion");
- PrintLongHelp(kLabelPattern_Help, "label_pattern");
- PrintLongHelp(kLabels_Help, "labels");
- PrintLongHelp(kNinjaRules_Help, "ninja_rules");
- PrintLongHelp(kNoGnCheck_Help, "nogncheck");
- PrintLongHelp(kRuntimeDeps_Help, "runtime_deps");
- PrintLongHelp(kSourceExpansion_Help, "source_expansion");
-
- if (is_markdown)
- OutputString("## <a name=\"switches\"></a>Command Line Switches\n\n");
- PrintSwitchHelp();
-}
-
-// Prints help on the given switch. There should be no leading hyphens. Returns
-// true if the switch was found and help was printed. False means the switch is
-// unknown.
-bool PrintHelpOnSwitch(const std::string& what) {
- const switches::SwitchInfoMap& all = switches::GetSwitches();
- switches::SwitchInfoMap::const_iterator found =
- all.find(base::StringPiece(what));
- if (found == all.end())
- return false;
- PrintLongHelp(found->second.long_help);
- return true;
-}
-
-} // namespace
-
-const char kHelp[] = "help";
-const char kHelp_HelpShort[] =
- "help: Does what you think.";
-const char kHelp_Help[] =
- R"(gn help <anything>
-
- Yo dawg, I heard you like help on your help so I put help on the help in the
- help.
-
- You can also use "all" as the parameter to get all help at once.
-
-Switches
-
- --markdown
- Format output in markdown syntax.
-
-Example
-
- gn help --markdown all
- Dump all help to stdout in markdown format.
-)";
-
-int RunHelp(const std::vector<std::string>& args) {
- std::string what;
- if (args.size() == 0) {
- // If no argument is specified, check for switches to allow things like
- // "gn help --args" for help on the args switch.
- const base::CommandLine::SwitchMap& switches =
- base::CommandLine::ForCurrentProcess()->GetSwitches();
- if (switches.empty()) {
- // Still nothing, show help overview.
- PrintToplevelHelp();
- return 0;
- }
-
- // Switch help needs to be done separately. The CommandLine will strip the
- // switch separators so --args will come out as "args" which is then
- // ambiguous with the variable named "args".
- if (!PrintHelpOnSwitch(switches.begin()->first))
- PrintToplevelHelp();
- return 0;
- } else {
- what = args[0];
- }
-
- std::vector<base::StringPiece> all_help_topics;
-
- // Check commands.
- const commands::CommandInfoMap& command_map = commands::GetCommands();
- auto found_command = command_map.find(what);
- if (found_command != command_map.end()) {
- PrintLongHelp(found_command->second.help);
- return 0;
- }
- for (const auto& entry : command_map)
- all_help_topics.push_back(entry.first);
-
- // Check functions.
- const functions::FunctionInfoMap& function_map = functions::GetFunctions();
- auto found_function = function_map.find(what);
- if (found_function != function_map.end())
- PrintLongHelp(found_function->second.help);
- for (const auto& entry : function_map)
- all_help_topics.push_back(entry.first);
-
- // Builtin variables.
- const variables::VariableInfoMap& builtin_vars =
- variables::GetBuiltinVariables();
- auto found_builtin_var = builtin_vars.find(what);
- if (found_builtin_var != builtin_vars.end())
- PrintLongHelp(found_builtin_var->second.help);
- for (const auto& entry : builtin_vars)
- all_help_topics.push_back(entry.first);
-
- // Target variables.
- const variables::VariableInfoMap& target_vars =
- variables::GetTargetVariables();
- auto found_target_var = target_vars.find(what);
- if (found_target_var != target_vars.end())
- PrintLongHelp(found_target_var->second.help);
- for (const auto& entry : target_vars)
- all_help_topics.push_back(entry.first);
-
- if (found_function != function_map.end() ||
- found_builtin_var != builtin_vars.end() ||
- found_target_var != target_vars.end())
- return 0;
-
- // Random other topics.
- std::map<std::string, void(*)()> random_topics;
- random_topics["all"] = PrintAllHelp;
- random_topics["execution"] = []() { PrintLongHelp(kExecution_Help); };
- random_topics["buildargs"] = []() { PrintLongHelp(kBuildArgs_Help); };
- random_topics["dotfile"] = []() { PrintLongHelp(kDotfile_Help); };
- random_topics["grammar"] = []() { PrintLongHelp(kGrammar_Help); };
- random_topics["input_conversion"] = []() {
- PrintLongHelp(kInputConversion_Help);
- };
- random_topics["label_pattern"] = []() { PrintLongHelp(kLabelPattern_Help); };
- random_topics["labels"] = []() { PrintLongHelp(kLabels_Help); };
- random_topics["ninja_rules"] = []() { PrintLongHelp(kNinjaRules_Help); };
- random_topics["nogncheck"] = []() { PrintLongHelp(kNoGnCheck_Help); };
- random_topics["runtime_deps"] = []() { PrintLongHelp(kRuntimeDeps_Help); };
- random_topics["source_expansion"] = []() {
- PrintLongHelp(kSourceExpansion_Help);
- };
- random_topics["switches"] = PrintSwitchHelp;
- auto found_random_topic = random_topics.find(what);
- if (found_random_topic != random_topics.end()) {
- found_random_topic->second();
- return 0;
- }
- for (const auto& entry : random_topics)
- all_help_topics.push_back(entry.first);
-
- // No help on this.
- Err(Location(), "No help on \"" + what + "\".").PrintToStdout();
- base::StringPiece suggestion = SpellcheckString(what, all_help_topics);
- if (suggestion.empty()) {
- OutputString("Run `gn help` for a list of available topics.\n",
- DECORATION_NONE);
- } else {
- OutputString("Did you mean `gn help " + suggestion.as_string() + "`?\n",
- DECORATION_NONE);
- }
- return 1;
-}
-
-} // namespace commands
diff --git a/chromium/tools/gn/command_ls.cc b/chromium/tools/gn/command_ls.cc
deleted file mode 100644
index 58b9c875951..00000000000
--- a/chromium/tools/gn/command_ls.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <set>
-
-#include "base/command_line.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/label_pattern.h"
-#include "tools/gn/setup.h"
-#include "tools/gn/standard_out.h"
-#include "tools/gn/switches.h"
-#include "tools/gn/target.h"
-
-namespace commands {
-
-const char kLs[] = "ls";
-const char kLs_HelpShort[] =
- "ls: List matching targets.";
-const char kLs_Help[] =
- R"(gn ls <out_dir> [<label_pattern>] [--all-toolchains] [--as=...]
- [--type=...] [--testonly=...]
-
- Lists all targets matching the given pattern for the given build directory.
- By default, only targets in the default toolchain will be matched unless a
- toolchain is explicitly supplied.
-
- If the label pattern is unspecified, list all targets. The label pattern is
- not a general regular expression (see "gn help label_pattern"). If you need
- more complex expressions, pipe the result through grep.
-
-Options
-
-)"
- TARGET_PRINTING_MODE_COMMAND_LINE_HELP
-"\n"
- ALL_TOOLCHAINS_SWITCH_HELP
-"\n"
- TARGET_TESTONLY_FILTER_COMMAND_LINE_HELP
-"\n"
- TARGET_TYPE_FILTER_COMMAND_LINE_HELP
-R"(
-Examples
-
- gn ls out/Debug
- Lists all targets in the default toolchain.
-
- gn ls out/Debug "//base/*"
- Lists all targets in the directory base and all subdirectories.
-
- gn ls out/Debug "//base:*"
- Lists all targets defined in //base/BUILD.gn.
-
- gn ls out/Debug //base --as=output
- Lists the build output file for //base:base
-
- gn ls out/Debug --type=executable
- Lists all executables produced by the build.
-
- gn ls out/Debug "//base/*" --as=output | xargs ninja -C out/Debug
- Builds all targets in //base and all subdirectories.
-
- gn ls out/Debug //base --all-toolchains
- Lists all variants of the target //base:base (it may be referenced
- in multiple toolchains).
-)";
-
-int RunLs(const std::vector<std::string>& args) {
- if (args.size() == 0) {
- Err(Location(), "You're holding it wrong.",
- "Usage: \"gn ls <build dir> [<label_pattern>]*\"").PrintToStdout();
- return 1;
- }
-
- Setup* setup = new Setup;
- if (!setup->DoSetup(args[0], false) || !setup->Run())
- return 1;
-
- const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
- bool all_toolchains = cmdline->HasSwitch(switches::kAllToolchains);
-
- std::vector<const Target*> matches;
- if (args.size() > 1) {
- // Some patterns or explicit labels were specified.
- std::vector<std::string> inputs(args.begin() + 1, args.end());
-
- UniqueVector<const Target*> target_matches;
- UniqueVector<const Config*> config_matches;
- UniqueVector<const Toolchain*> toolchain_matches;
- UniqueVector<SourceFile> file_matches;
- if (!ResolveFromCommandLineInput(setup, inputs, all_toolchains,
- &target_matches, &config_matches,
- &toolchain_matches, &file_matches))
- return 1;
- matches.insert(matches.begin(),
- target_matches.begin(), target_matches.end());
- } else if (all_toolchains) {
- // List all resolved targets.
- matches = setup->builder().GetAllResolvedTargets();
- } else {
- // List all resolved targets in the default toolchain.
- for (auto* target : setup->builder().GetAllResolvedTargets()) {
- if (target->settings()->is_default())
- matches.push_back(target);
- }
- }
- FilterAndPrintTargets(false, &matches);
- return 0;
-}
-
-} // namespace commands
diff --git a/chromium/tools/gn/command_path.cc b/chromium/tools/gn/command_path.cc
deleted file mode 100644
index daa220048d9..00000000000
--- a/chromium/tools/gn/command_path.cc
+++ /dev/null
@@ -1,415 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include <algorithm>
-
-#include "base/command_line.h"
-#include "base/containers/hash_tables.h"
-#include "base/strings/stringprintf.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/setup.h"
-#include "tools/gn/standard_out.h"
-
-namespace commands {
-
-namespace {
-
-enum class DepType {
- NONE,
- PUBLIC,
- PRIVATE,
- DATA
-};
-
-// The dependency paths are stored in a vector. Assuming the chain:
-// A --[public]--> B --[private]--> C
-// The stack will look like:
-// [0] = A, NONE (this has no dep type since nobody depends on it)
-// [1] = B, PUBLIC
-// [2] = C, PRIVATE
-using TargetDep = std::pair<const Target*, DepType>;
-using PathVector = std::vector<TargetDep>;
-
-// How to search.
-enum class PrivateDeps { INCLUDE, EXCLUDE };
-enum class DataDeps { INCLUDE, EXCLUDE };
-enum class PrintWhat { ONE, ALL };
-
-struct Options {
- Options()
- : print_what(PrintWhat::ONE),
- public_only(false),
- with_data(false) {
- }
-
- PrintWhat print_what;
- bool public_only;
- bool with_data;
-};
-
-typedef std::list<PathVector> WorkQueue;
-
-struct Stats {
- Stats() : public_paths(0), other_paths(0) {
- }
-
- int total_paths() const { return public_paths + other_paths; }
-
- int public_paths;
- int other_paths;
-
- // Stores targets that have a path to the destination, and whether that
- // path is public, private, or data.
- std::map<const Target*, DepType> found_paths;
-};
-
-// If the implicit_last_dep is not "none", this type indicates the
-// classification of the elided last part of path.
-DepType ClassifyPath(const PathVector& path, DepType implicit_last_dep) {
- DepType result;
- if (implicit_last_dep != DepType::NONE)
- result = implicit_last_dep;
- else
- result = DepType::PUBLIC;
-
- // Skip the 0th one since that is always NONE.
- for (size_t i = 1; i < path.size(); i++) {
- // PRIVATE overrides PUBLIC, and DATA overrides everything (the idea is
- // to find the worst link in the path).
- if (path[i].second == DepType::PRIVATE) {
- if (result == DepType::PUBLIC)
- result = DepType::PRIVATE;
- } else if (path[i].second == DepType::DATA) {
- result = DepType::DATA;
- }
- }
- return result;
-}
-
-const char* StringForDepType(DepType type) {
- switch(type) {
- case DepType::PUBLIC:
- return "public";
- case DepType::PRIVATE:
- return "private";
- case DepType::DATA:
- return "data";
- break;
- case DepType::NONE:
- default:
- return "";
- }
-}
-
-// Prints the given path. If the implicit_last_dep is not "none", the last
-// dependency will show an elided dependency with the given annotation.
-void PrintPath(const PathVector& path, DepType implicit_last_dep) {
- if (path.empty())
- return;
-
- // Don't print toolchains unless they differ from the first target.
- const Label& default_toolchain = path[0].first->label().GetToolchainLabel();
-
- for (size_t i = 0; i < path.size(); i++) {
- OutputString(path[i].first->label().GetUserVisibleName(default_toolchain));
-
- // Output dependency type.
- if (i == path.size() - 1) {
- // Last one either gets the implicit last dep type or nothing.
- if (implicit_last_dep != DepType::NONE) {
- OutputString(std::string(" --> see ") +
- StringForDepType(implicit_last_dep) +
- " chain printed above...", DECORATION_DIM);
- }
- } else {
- // Take type from the next entry.
- OutputString(std::string(" --[") + StringForDepType(path[i + 1].second) +
- "]-->", DECORATION_DIM);
- }
- OutputString("\n");
- }
-
- OutputString("\n");
-}
-
-void InsertTargetsIntoFoundPaths(const PathVector& path,
- DepType implicit_last_dep,
- Stats* stats) {
- DepType type = ClassifyPath(path, implicit_last_dep);
-
- bool inserted = false;
-
- // Don't try to insert the 0th item in the list which is the "from" target.
- // The search will be run more than once (for the different path types) and
- // if the "from" target was in the list, subsequent passes could never run
- // the starting point is alredy in the list of targets considered).
- //
- // One might imagine an alternate implementation where all items are counted
- // here but the "from" item is erased at the beginning of each search, but
- // that will mess up the metrics (the private search pass will find the
- // same public paths as the previous public pass, "inserted" will be true
- // here since the item wasn't found, and the public path will be
- // double-counted in the stats.
- for (size_t i = 1; i < path.size(); i++) {
- const auto& pair = path[i];
-
- // Don't overwrite an existing one. The algorithm works by first doing
- // public, then private, then data, so anything already there is guaranteed
- // at least as good as our addition.
- if (stats->found_paths.find(pair.first) == stats->found_paths.end()) {
- stats->found_paths.insert(std::make_pair(pair.first, type));
- inserted = true;
- }
- }
-
- if (inserted) {
- // Only count this path in the stats if any part of it was actually new.
- if (type == DepType::PUBLIC)
- stats->public_paths++;
- else
- stats->other_paths++;
- }
-}
-
-void BreadthFirstSearch(const Target* from, const Target* to,
- PrivateDeps private_deps, DataDeps data_deps,
- PrintWhat print_what,
- Stats* stats) {
- // Seed the initial stack with just the "from" target.
- PathVector initial_stack;
- initial_stack.emplace_back(from, DepType::NONE);
- WorkQueue work_queue;
- work_queue.push_back(initial_stack);
-
- // Track checked targets to avoid checking the same once more than once.
- std::set<const Target*> visited;
-
- while (!work_queue.empty()) {
- PathVector current_path = work_queue.front();
- work_queue.pop_front();
-
- const Target* current_target = current_path.back().first;
-
- if (current_target == to) {
- // Found a new path.
- if (stats->total_paths() == 0 || print_what == PrintWhat::ALL)
- PrintPath(current_path, DepType::NONE);
-
- // Insert all nodes on the path into the found paths list. Since we're
- // doing search breadth first, we know that the current path is the best
- // path for all nodes on it.
- InsertTargetsIntoFoundPaths(current_path, DepType::NONE, stats);
- } else {
- // Check for a path that connects to an already known-good one. Printing
- // this here will mean the results aren't strictly in depth-first order
- // since there could be many items on the found path this connects to.
- // Doing this here will mean that the output is sorted by length of items
- // printed (with the redundant parts of the path omitted) rather than
- // complete path length.
- const auto& found_current_target =
- stats->found_paths.find(current_target);
- if (found_current_target != stats->found_paths.end()) {
- if (stats->total_paths() == 0 || print_what == PrintWhat::ALL)
- PrintPath(current_path, found_current_target->second);
-
- // Insert all nodes on the path into the found paths list since we know
- // everything along this path also leads to the destination.
- InsertTargetsIntoFoundPaths(current_path, found_current_target->second,
- stats);
- continue;
- }
- }
-
- // If we've already checked this one, stop. This should be after the above
- // check for a known-good check, because known-good ones will always have
- // been previously visited.
- if (visited.find(current_target) == visited.end())
- visited.insert(current_target);
- else
- continue;
-
- // Add public deps for this target to the queue.
- for (const auto& pair : current_target->public_deps()) {
- work_queue.push_back(current_path);
- work_queue.back().push_back(TargetDep(pair.ptr, DepType::PUBLIC));
- }
-
- if (private_deps == PrivateDeps::INCLUDE) {
- // Add private deps.
- for (const auto& pair : current_target->private_deps()) {
- work_queue.push_back(current_path);
- work_queue.back().push_back(
- TargetDep(pair.ptr, DepType::PRIVATE));
- }
- }
-
- if (data_deps == DataDeps::INCLUDE) {
- // Add data deps.
- for (const auto& pair : current_target->data_deps()) {
- work_queue.push_back(current_path);
- work_queue.back().push_back(TargetDep(pair.ptr, DepType::DATA));
- }
- }
- }
-}
-
-void DoSearch(const Target* from, const Target* to, const Options& options,
- Stats* stats) {
- BreadthFirstSearch(from, to, PrivateDeps::EXCLUDE, DataDeps::EXCLUDE,
- options.print_what, stats);
- if (!options.public_only) {
- // Check private deps.
- BreadthFirstSearch(from, to, PrivateDeps::INCLUDE,
- DataDeps::EXCLUDE, options.print_what, stats);
- if (options.with_data) {
- // Check data deps.
- BreadthFirstSearch(from, to, PrivateDeps::INCLUDE,
- DataDeps::INCLUDE, options.print_what, stats);
- }
- }
-}
-
-} // namespace
-
-const char kPath[] = "path";
-const char kPath_HelpShort[] =
- "path: Find paths between two targets.";
-const char kPath_Help[] =
- R"(gn path <out_dir> <target_one> <target_two>
-
- Finds paths of dependencies between two targets. Each unique path will be
- printed in one group, and groups will be separate by newlines. The two
- targets can appear in either order (paths will be found going in either
- direction).
-
- By default, a single path will be printed. If there is a path with only
- public dependencies, the shortest public path will be printed. Otherwise, the
- shortest path using either public or private dependencies will be printed. If
- --with-data is specified, data deps will also be considered. If there are
- multiple shortest paths, an arbitrary one will be selected.
-
-Interesting paths
-
- In a large project, there can be 100's of millions of unique paths between a
- very high level and a common low-level target. To make the output more useful
- (and terminate in a reasonable time), GN will not revisit sub-paths
- previously known to lead to the target.
-
-Options
-
- --all
- Prints all "interesting" paths found rather than just the first one.
- Public paths will be printed first in order of increasing length, followed
- by non-public paths in order of increasing length.
-
- --public
- Considers only public paths. Can't be used with --with-data.
-
- --with-data
- Additionally follows data deps. Without this flag, only public and private
- linked deps will be followed. Can't be used with --public.
-
-Example
-
- gn path out/Default //base //tools/gn
-)";
-
-int RunPath(const std::vector<std::string>& args) {
- if (args.size() != 3) {
- Err(Location(), "You're holding it wrong.",
- "Usage: \"gn path <out_dir> <target_one> <target_two>\"")
- .PrintToStdout();
- return 1;
- }
-
- Setup* setup = new Setup;
- if (!setup->DoSetup(args[0], false))
- return 1;
- if (!setup->Run())
- return 1;
-
- const Target* target1 = ResolveTargetFromCommandLineString(setup, args[1]);
- if (!target1)
- return 1;
- const Target* target2 = ResolveTargetFromCommandLineString(setup, args[2]);
- if (!target2)
- return 1;
-
- Options options;
- options.print_what = base::CommandLine::ForCurrentProcess()->HasSwitch("all")
- ? PrintWhat::ALL : PrintWhat::ONE;
- options.public_only =
- base::CommandLine::ForCurrentProcess()->HasSwitch("public");
- options.with_data =
- base::CommandLine::ForCurrentProcess()->HasSwitch("with-data");
- if (options.public_only && options.with_data) {
- Err(Location(), "Can't use --public with --with-data for 'gn path'.",
- "Your zealous over-use of arguments has inevitably resulted in an "
- "invalid\ncombination of flags.").PrintToStdout();
- return 1;
- }
-
- Stats stats;
- DoSearch(target1, target2, options, &stats);
- if (stats.total_paths() == 0) {
- // If we don't find a path going "forwards", try the reverse direction.
- // Deps can only go in one direction without having a cycle, which will
- // have caused a run failure above.
- DoSearch(target2, target1, options, &stats);
- }
-
- // This string is inserted in the results to annotate whether the result
- // is only public or includes data deps or not.
- const char* path_annotation = "";
- if (options.public_only)
- path_annotation = "public ";
- else if (!options.with_data)
- path_annotation = "non-data ";
-
- if (stats.total_paths() == 0) {
- // No results.
- OutputString(base::StringPrintf(
- "No %spaths found between these two targets.\n", path_annotation),
- DECORATION_YELLOW);
- } else if (stats.total_paths() == 1) {
- // Exactly one result.
- OutputString(base::StringPrintf("1 %spath found.", path_annotation),
- DECORATION_YELLOW);
- if (!options.public_only) {
- if (stats.public_paths)
- OutputString(" It is public.");
- else
- OutputString(" It is not public.");
- }
- OutputString("\n");
- } else {
- if (options.print_what == PrintWhat::ALL) {
- // Showing all paths when there are many.
- OutputString(base::StringPrintf("%d \"interesting\" %spaths found.",
- stats.total_paths(), path_annotation),
- DECORATION_YELLOW);
- if (!options.public_only) {
- OutputString(base::StringPrintf(" %d of them are public.",
- stats.public_paths));
- }
- OutputString("\n");
- } else {
- // Showing one path when there are many.
- OutputString(
- base::StringPrintf("Showing one of %d \"interesting\" %spaths.",
- stats.total_paths(), path_annotation),
- DECORATION_YELLOW);
- if (!options.public_only) {
- OutputString(
- base::StringPrintf(" %d of them are public.", stats.public_paths));
- }
- OutputString("\nUse --all to print all paths.\n");
- }
- }
- return 0;
-}
-
-} // namespace commands
diff --git a/chromium/tools/gn/command_refs.cc b/chromium/tools/gn/command_refs.cc
deleted file mode 100644
index ad1eb6e2fda..00000000000
--- a/chromium/tools/gn/command_refs.cc
+++ /dev/null
@@ -1,501 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include <map>
-#include <set>
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/config_values_extractors.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/item.h"
-#include "tools/gn/setup.h"
-#include "tools/gn/standard_out.h"
-#include "tools/gn/switches.h"
-#include "tools/gn/target.h"
-
-namespace commands {
-
-namespace {
-
-typedef std::set<const Target*> TargetSet;
-typedef std::vector<const Target*> TargetVector;
-
-// Maps targets to the list of targets that depend on them.
-typedef std::multimap<const Target*, const Target*> DepMap;
-
-// Populates the reverse dependency map for the targets in the Setup.
-void FillDepMap(Setup* setup, DepMap* dep_map) {
- for (auto* target : setup->builder().GetAllResolvedTargets()) {
- for (const auto& dep_pair : target->GetDeps(Target::DEPS_ALL))
- dep_map->insert(std::make_pair(dep_pair.ptr, target));
- }
-}
-
-// Forward declaration for function below.
-size_t RecursivePrintTargetDeps(const DepMap& dep_map,
- const Target* target,
- TargetSet* seen_targets,
- int indent_level);
-
-// Prints the target and its dependencies in tree form. If the set is non-null,
-// new targets encountered will be added to the set, and if a ref is in the set
-// already, it will not be recused into. When the set is null, all refs will be
-// printed.
-//
-// Returns the number of items printed.
-size_t RecursivePrintTarget(const DepMap& dep_map,
- const Target* target,
- TargetSet* seen_targets,
- int indent_level) {
- std::string indent(indent_level * 2, ' ');
- size_t count = 1;
-
- // Only print the toolchain for non-default-toolchain targets.
- OutputString(indent + target->label().GetUserVisibleName(
- !target->settings()->is_default()));
-
- bool print_children = true;
- if (seen_targets) {
- if (seen_targets->find(target) == seen_targets->end()) {
- // New target, mark it visited.
- seen_targets->insert(target);
- } else {
- // Already seen.
- print_children = false;
- // Only print "..." if something is actually elided, which means that
- // the current target has children.
- if (dep_map.lower_bound(target) != dep_map.upper_bound(target))
- OutputString("...");
- }
- }
-
- OutputString("\n");
- if (print_children) {
- count += RecursivePrintTargetDeps(dep_map, target, seen_targets,
- indent_level + 1);
- }
- return count;
-}
-
-// Prints refs of the given target (not the target itself). See
-// RecursivePrintTarget.
-size_t RecursivePrintTargetDeps(const DepMap& dep_map,
- const Target* target,
- TargetSet* seen_targets,
- int indent_level) {
- DepMap::const_iterator dep_begin = dep_map.lower_bound(target);
- DepMap::const_iterator dep_end = dep_map.upper_bound(target);
- size_t count = 0;
- for (DepMap::const_iterator cur_dep = dep_begin;
- cur_dep != dep_end; cur_dep++) {
- count += RecursivePrintTarget(dep_map, cur_dep->second, seen_targets,
- indent_level);
- }
- return count;
-}
-
-void RecursiveCollectChildRefs(const DepMap& dep_map,
- const Target* target,
- TargetSet* results);
-
-// Recursively finds all targets that reference the given one, and additionally
-// adds the current one to the list.
-void RecursiveCollectRefs(const DepMap& dep_map,
- const Target* target,
- TargetSet* results) {
- if (results->find(target) != results->end())
- return; // Already found this target.
- results->insert(target);
- RecursiveCollectChildRefs(dep_map, target, results);
-}
-
-// Recursively finds all targets that reference the given one.
-void RecursiveCollectChildRefs(const DepMap& dep_map,
- const Target* target,
- TargetSet* results) {
- DepMap::const_iterator dep_begin = dep_map.lower_bound(target);
- DepMap::const_iterator dep_end = dep_map.upper_bound(target);
- for (DepMap::const_iterator cur_dep = dep_begin;
- cur_dep != dep_end; cur_dep++)
- RecursiveCollectRefs(dep_map, cur_dep->second, results);
-}
-
-bool TargetContainsFile(const Target* target, const SourceFile& file) {
- for (const auto& cur_file : target->sources()) {
- if (cur_file == file)
- return true;
- }
- for (const auto& cur_file : target->public_headers()) {
- if (cur_file == file)
- return true;
- }
- for (ConfigValuesIterator iter(target); !iter.done(); iter.Next()) {
- for (const auto& cur_file : iter.cur().inputs()) {
- if (cur_file == file)
- return true;
- }
- }
- for (const auto& cur_file : target->data()) {
- if (cur_file == file.value())
- return true;
- if (cur_file.back() == '/' &&
- base::StartsWith(file.value(), cur_file, base::CompareCase::SENSITIVE))
- return true;
- }
-
- if (target->action_values().script().value() == file.value())
- return true;
-
- std::vector<SourceFile> output_sources;
- target->action_values().GetOutputsAsSourceFiles(target, &output_sources);
- for (const auto& cur_file : output_sources) {
- if (cur_file == file)
- return true;
- }
-
- for (const auto& cur_file : target->computed_outputs()) {
- if (cur_file.AsSourceFile(target->settings()->build_settings()) == file)
- return true;
- }
- return false;
-}
-
-void GetTargetsContainingFile(Setup* setup,
- const std::vector<const Target*>& all_targets,
- const SourceFile& file,
- bool all_toolchains,
- UniqueVector<const Target*>* matches) {
- Label default_toolchain = setup->loader()->default_toolchain_label();
- for (auto* target : all_targets) {
- if (!all_toolchains) {
- // Only check targets in the default toolchain.
- if (target->label().GetToolchainLabel() != default_toolchain)
- continue;
- }
- if (TargetContainsFile(target, file))
- matches->push_back(target);
- }
-}
-
-bool TargetReferencesConfig(const Target* target, const Config* config) {
- for (const LabelConfigPair& cur : target->configs()) {
- if (cur.ptr == config)
- return true;
- }
- for (const LabelConfigPair& cur : target->public_configs()) {
- if (cur.ptr == config)
- return true;
- }
- return false;
-}
-
-void GetTargetsReferencingConfig(Setup* setup,
- const std::vector<const Target*>& all_targets,
- const Config* config,
- bool all_toolchains,
- UniqueVector<const Target*>* matches) {
- Label default_toolchain = setup->loader()->default_toolchain_label();
- for (auto* target : all_targets) {
- if (!all_toolchains) {
- // Only check targets in the default toolchain.
- if (target->label().GetToolchainLabel() != default_toolchain)
- continue;
- }
- if (TargetReferencesConfig(target, config))
- matches->push_back(target);
- }
-}
-
-// Returns the number of matches printed.
-size_t DoTreeOutput(const DepMap& dep_map,
- const UniqueVector<const Target*>& implicit_target_matches,
- const UniqueVector<const Target*>& explicit_target_matches,
- bool all) {
- TargetSet seen_targets;
- size_t count = 0;
-
- // Implicit targets don't get printed themselves.
- for (const Target* target : implicit_target_matches) {
- if (all)
- count += RecursivePrintTargetDeps(dep_map, target, nullptr, 0);
- else
- count += RecursivePrintTargetDeps(dep_map, target, &seen_targets, 0);
- }
-
- // Explicit targets appear in the output.
- for (const Target* target : implicit_target_matches) {
- if (all)
- count += RecursivePrintTarget(dep_map, target, nullptr, 0);
- else
- count += RecursivePrintTarget(dep_map, target, &seen_targets, 0);
- }
-
- return count;
-}
-
-// Returns the number of matches printed.
-size_t DoAllListOutput(
- const DepMap& dep_map,
- const UniqueVector<const Target*>& implicit_target_matches,
- const UniqueVector<const Target*>& explicit_target_matches) {
- // Output recursive dependencies, uniquified and flattened.
- TargetSet results;
-
- for (const Target* target : implicit_target_matches)
- RecursiveCollectChildRefs(dep_map, target, &results);
- for (const Target* target : explicit_target_matches) {
- // Explicit targets also get added to the output themselves.
- results.insert(target);
- RecursiveCollectChildRefs(dep_map, target, &results);
- }
-
- FilterAndPrintTargetSet(false, results);
- return results.size();
-}
-
-// Returns the number of matches printed.
-size_t DoDirectListOutput(
- const DepMap& dep_map,
- const UniqueVector<const Target*>& implicit_target_matches,
- const UniqueVector<const Target*>& explicit_target_matches) {
- TargetSet results;
-
- // Output everything that refers to the implicit ones.
- for (const Target* target : implicit_target_matches) {
- DepMap::const_iterator dep_begin = dep_map.lower_bound(target);
- DepMap::const_iterator dep_end = dep_map.upper_bound(target);
- for (DepMap::const_iterator cur_dep = dep_begin;
- cur_dep != dep_end; cur_dep++)
- results.insert(cur_dep->second);
- }
-
- // And just output the explicit ones directly (these are the target matches
- // when referring to what references a file or config).
- for (const Target* target : explicit_target_matches)
- results.insert(target);
-
- FilterAndPrintTargetSet(false, results);
- return results.size();
-}
-
-} // namespace
-
-const char kRefs[] = "refs";
-const char kRefs_HelpShort[] =
- "refs: Find stuff referencing a target or file.";
-const char kRefs_Help[] =
- R"(gn refs <out_dir> (<label_pattern>|<label>|<file>|@<response_file>)*
- [--all] [--all-toolchains] [--as=...] [--testonly=...] [--type=...]
-
- Finds reverse dependencies (which targets reference something). The input is
- a list containing:
-
- - Target label: The result will be which targets depend on it.
-
- - Config label: The result will be which targets list the given config in
- its "configs" or "public_configs" list.
-
- - Label pattern: The result will be which targets depend on any target
- matching the given pattern. Patterns will not match configs. These are not
- general regular expressions, see "gn help label_pattern" for details.
-
- - File name: The result will be which targets list the given file in its
- "inputs", "sources", "public", "data", or "outputs". Any input that does
- not contain wildcards and does not match a target or a config will be
- treated as a file.
-
- - Response file: If the input starts with an "@", it will be interpreted as
- a path to a file containing a list of labels or file names, one per line.
- This allows us to handle long lists of inputs without worrying about
- command line limits.
-
-Options
-
- --all
- When used without --tree, will recurse and display all unique
- dependencies of the given targets. For example, if the input is a target,
- this will output all targets that depend directly or indirectly on the
- input. If the input is a file, this will output all targets that depend
- directly or indirectly on that file.
-
- When used with --tree, turns off eliding to show a complete tree.
-)"
-
-ALL_TOOLCHAINS_SWITCH_HELP
-"\n"
-TARGET_PRINTING_MODE_COMMAND_LINE_HELP
-
-R"(
- -q
- Quiet. If nothing matches, don't print any output. Without this option, if
- there are no matches there will be an informational message printed which
- might interfere with scripts processing the output.
-)"
-
-TARGET_TESTONLY_FILTER_COMMAND_LINE_HELP
-
-R"(
- --tree
- Outputs a reverse dependency tree from the given target. Duplicates will
- be elided. Combine with --all to see a full dependency tree.
-
- Tree output can not be used with the filtering or output flags: --as,
- --type, --testonly.
-)"
-
-TARGET_TYPE_FILTER_COMMAND_LINE_HELP
-
-R"(
-
-Examples (target input)
-
- gn refs out/Debug //tools/gn:gn
- Find all targets depending on the given exact target name.
-
- gn refs out/Debug //base:i18n --as=buildfiles | xargs gvim
- Edit all .gn files containing references to //base:i18n
-
- gn refs out/Debug //base --all
- List all targets depending directly or indirectly on //base:base.
-
- gn refs out/Debug "//base/*"
- List all targets depending directly on any target in //base or
- its subdirectories.
-
- gn refs out/Debug "//base:*"
- List all targets depending directly on any target in
- //base/BUILD.gn.
-
- gn refs out/Debug //base --tree
- Print a reverse dependency tree of //base:base
-
-Examples (file input)
-
- gn refs out/Debug //base/macros.h
- Print target(s) listing //base/macros.h as a source.
-
- gn refs out/Debug //base/macros.h --tree
- Display a reverse dependency tree to get to the given file. This
- will show how dependencies will reference that file.
-
- gn refs out/Debug //base/macros.h //base/at_exit.h --all
- Display all unique targets with some dependency path to a target
- containing either of the given files as a source.
-
- gn refs out/Debug //base/macros.h --testonly=true --type=executable
- --all --as=output
- Display the executable file names of all test executables
- potentially affected by a change to the given file.
-)";
-
-int RunRefs(const std::vector<std::string>& args) {
- if (args.size() <= 1) {
- Err(Location(), "You're holding it wrong.",
- "Usage: \"gn refs <out_dir> (<label_pattern>|<file>)*\"")
- .PrintToStdout();
- return 1;
- }
-
- const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
- bool tree = cmdline->HasSwitch("tree");
- bool all = cmdline->HasSwitch("all");
- bool all_toolchains = cmdline->HasSwitch(switches::kAllToolchains);
-
- Setup* setup = new Setup;
- if (!setup->DoSetup(args[0], false) || !setup->Run())
- return 1;
-
- // The inputs are everything but the first arg (which is the build dir).
- std::vector<std::string> inputs;
- for (size_t i = 1; i < args.size(); i++) {
- if (args[i][0] == '@') {
- // The argument is as a path to a response file.
- std::string contents;
- bool ret = base::ReadFileToString(UTF8ToFilePath(args[i].substr(1)),
- &contents);
- if (!ret) {
- Err(Location(), "Response file " + args[i].substr(1) + " not found.")
- .PrintToStdout();
- return 1;
- }
- for (const std::string& line : base::SplitString(
- contents, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
- if (!line.empty())
- inputs.push_back(line);
- }
- } else {
- // The argument is a label or a path.
- inputs.push_back(args[i]);
- }
- }
-
- // Get the matches for the command-line input.
- UniqueVector<const Target*> target_matches;
- UniqueVector<const Config*> config_matches;
- UniqueVector<const Toolchain*> toolchain_matches;
- UniqueVector<SourceFile> file_matches;
- if (!ResolveFromCommandLineInput(setup, inputs, all_toolchains,
- &target_matches, &config_matches,
- &toolchain_matches, &file_matches))
- return 1;
-
- // When you give a file or config as an input, you want the targets that are
- // associated with it. We don't want to just append this to the
- // target_matches, however, since these targets should actually be listed in
- // the output, while for normal targets you don't want to see the inputs,
- // only what refers to them.
- std::vector<const Target*> all_targets =
- setup->builder().GetAllResolvedTargets();
- UniqueVector<const Target*> explicit_target_matches;
- for (const auto& file : file_matches) {
- GetTargetsContainingFile(setup, all_targets, file, all_toolchains,
- &explicit_target_matches);
- }
- for (auto* config : config_matches) {
- GetTargetsReferencingConfig(setup, all_targets, config, all_toolchains,
- &explicit_target_matches);
- }
-
- // Tell the user if their input matches no files or labels. We need to check
- // both that it matched no targets and no configs. File input will already
- // have been converted to targets at this point. Configs will have been
- // converted to targets also, but there could be no targets referencing the
- // config, which is different than no config with that name.
- bool quiet = cmdline->HasSwitch("q");
- if (!quiet && config_matches.empty() &&
- explicit_target_matches.empty() && target_matches.empty()) {
- OutputString("The input matches no targets, configs, or files.\n",
- DECORATION_YELLOW);
- return 1;
- }
-
- // Construct the reverse dependency tree.
- DepMap dep_map;
- FillDepMap(setup, &dep_map);
-
- size_t cnt = 0;
- if (tree)
- cnt = DoTreeOutput(dep_map, target_matches, explicit_target_matches, all);
- else if (all)
- cnt = DoAllListOutput(dep_map, target_matches, explicit_target_matches);
- else
- cnt = DoDirectListOutput(dep_map, target_matches, explicit_target_matches);
-
- // If you ask for the references of a valid target, but that target has
- // nothing referencing it, we'll get here without having printed anything.
- if (!quiet && cnt == 0)
- OutputString("Nothing references this.\n", DECORATION_YELLOW);
-
- return 0;
-}
-
-} // namespace commands
diff --git a/chromium/tools/gn/commands.cc b/chromium/tools/gn/commands.cc
deleted file mode 100644
index 59d2391c993..00000000000
--- a/chromium/tools/gn/commands.cc
+++ /dev/null
@@ -1,568 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/commands.h"
-
-#include "base/command_line.h"
-#include "base/environment.h"
-#include "base/strings/string_split.h"
-#include "base/values.h"
-#include "build/build_config.h"
-#include "tools/gn/builder.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/item.h"
-#include "tools/gn/label.h"
-#include "tools/gn/label_pattern.h"
-#include "tools/gn/setup.h"
-#include "tools/gn/standard_out.h"
-#include "tools/gn/target.h"
-
-namespace commands {
-
-namespace {
-
-// Like above but the input string can be a pattern that matches multiple
-// targets. If the input does not parse as a pattern, prints and error and
-// returns false. If the pattern is valid, fills the vector (which might be
-// empty if there are no matches) and returns true.
-//
-// If all_toolchains is false, a pattern with an unspecified toolchain will
-// match the default toolchain only. If true, all toolchains will be matched.
-bool ResolveTargetsFromCommandLinePattern(
- Setup* setup,
- const std::string& label_pattern,
- bool all_toolchains,
- std::vector<const Target*>* matches) {
- Value pattern_value(nullptr, label_pattern);
-
- Err err;
- LabelPattern pattern = LabelPattern::GetPattern(
- SourceDirForCurrentDirectory(setup->build_settings().root_path()),
- pattern_value,
- &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
-
- if (!all_toolchains) {
- // By default a pattern with an empty toolchain will match all toolchains.
- // If the caller wants to default to the main toolchain only, set it
- // explicitly.
- if (pattern.toolchain().is_null()) {
- // No explicit toolchain set.
- pattern.set_toolchain(setup->loader()->default_toolchain_label());
- }
- }
-
- std::vector<LabelPattern> pattern_vector;
- pattern_vector.push_back(pattern);
- FilterTargetsByPatterns(setup->builder().GetAllResolvedTargets(),
- pattern_vector, matches);
- return true;
-}
-
-
-// If there's an error, it will be printed and false will be returned.
-bool ResolveStringFromCommandLineInput(
- Setup* setup,
- const SourceDir& current_dir,
- const std::string& input,
- bool all_toolchains,
- UniqueVector<const Target*>* target_matches,
- UniqueVector<const Config*>* config_matches,
- UniqueVector<const Toolchain*>* toolchain_matches,
- UniqueVector<SourceFile>* file_matches) {
- if (LabelPattern::HasWildcard(input)) {
- // For now, only match patterns against targets. It might be nice in the
- // future to allow the user to specify which types of things they want to
- // match, but it should probably only match targets by default.
- std::vector<const Target*> target_match_vector;
- if (!ResolveTargetsFromCommandLinePattern(setup, input, all_toolchains,
- &target_match_vector))
- return false;
- for (const Target* target : target_match_vector)
- target_matches->push_back(target);
- return true;
- }
-
- // Try to figure out what this thing is.
- Err err;
- Label label = Label::Resolve(current_dir,
- setup->loader()->default_toolchain_label(),
- Value(nullptr, input), &err);
- if (err.has_error()) {
- // Not a valid label, assume this must be a file.
- err = Err();
- file_matches->push_back(current_dir.ResolveRelativeFile(
- Value(nullptr, input), &err, setup->build_settings().root_path_utf8()));
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
- return true;
- }
-
- const Item* item = setup->builder().GetItem(label);
- if (item) {
- if (const Config* as_config = item->AsConfig())
- config_matches->push_back(as_config);
- else if (const Target* as_target = item->AsTarget())
- target_matches->push_back(as_target);
- else if (const Toolchain* as_toolchain = item->AsToolchain())
- toolchain_matches->push_back(as_toolchain);
- } else {
- // Not an item, assume this must be a file.
- file_matches->push_back(current_dir.ResolveRelativeFile(
- Value(nullptr, input), &err, setup->build_settings().root_path_utf8()));
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
- }
-
- return true;
-}
-
-enum TargetPrintingMode {
- TARGET_PRINT_BUILDFILE,
- TARGET_PRINT_LABEL,
- TARGET_PRINT_OUTPUT,
-};
-
-// Retrieves the target printing mode based on the command line flags for the
-// current process. Returns true on success. On error, prints a message to the
-// console and returns false.
-bool GetTargetPrintingMode(TargetPrintingMode* mode) {
- std::string switch_key = "as";
- const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
-
- if (!cmdline->HasSwitch(switch_key)) {
- // Default to labels.
- *mode = TARGET_PRINT_LABEL;
- return true;
- }
-
- std::string value = cmdline->GetSwitchValueASCII(switch_key);
- if (value == "buildfile") {
- *mode = TARGET_PRINT_BUILDFILE;
- return true;
- }
- if (value == "label") {
- *mode = TARGET_PRINT_LABEL;
- return true;
- }
- if (value == "output") {
- *mode = TARGET_PRINT_OUTPUT;
- return true;
- }
-
- Err(Location(), "Invalid value for \"--as\".",
- "I was expecting \"buildfile\", \"label\", or \"output\" but you\n"
- "said \"" + value + "\".").PrintToStdout();
- return false;
-}
-
-// Returns the target type filter based on the command line flags for the
-// current process. Returns true on success. On error, prints a message to the
-// console and returns false.
-//
-// Target::UNKNOWN will be set if there is no filter. Target::ACTION_FOREACH
-// will never be returned. Code applying the filters should apply Target::ACTION
-// to both ACTION and ACTION_FOREACH.
-bool GetTargetTypeFilter(Target::OutputType* type) {
- std::string switch_key = "type";
- const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
-
- if (!cmdline->HasSwitch(switch_key)) {
- // Default to unknown -> no filtering.
- *type = Target::UNKNOWN;
- return true;
- }
-
- std::string value = cmdline->GetSwitchValueASCII(switch_key);
- if (value == "group") {
- *type = Target::GROUP;
- return true;
- }
- if (value == "executable") {
- *type = Target::EXECUTABLE;
- return true;
- }
- if (value == "shared_library") {
- *type = Target::SHARED_LIBRARY;
- return true;
- }
- if (value == "loadable_module") {
- *type = Target::LOADABLE_MODULE;
- return true;
- }
- if (value == "static_library") {
- *type = Target::STATIC_LIBRARY;
- return true;
- }
- if (value == "source_set") {
- *type = Target::SOURCE_SET;
- return true;
- }
- if (value == "copy") {
- *type = Target::COPY_FILES;
- return true;
- }
- if (value == "action") {
- *type = Target::ACTION;
- return true;
- }
-
- Err(Location(), "Invalid value for \"--type\".").PrintToStdout();
- return false;
-}
-
-
-// Applies any testonly filtering specified on the command line to the given
-// target set. On failure, prints an error and returns false.
-bool ApplyTestonlyFilter(std::vector<const Target*>* targets) {
- const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
- std::string testonly_key = "testonly";
-
- if (targets->empty() || !cmdline->HasSwitch(testonly_key))
- return true;
-
- std::string testonly_value = cmdline->GetSwitchValueASCII(testonly_key);
- bool testonly = false;
- if (testonly_value == "true") {
- testonly = true;
- } else if (testonly_value != "false") {
- Err(Location(), "Bad value for --testonly.",
- "I was expecting --testonly=true or --testonly=false.")
- .PrintToStdout();
- return false;
- }
-
- // Filter into a copy of the vector, then swap to output.
- std::vector<const Target*> result;
- result.reserve(targets->size());
-
- for (const Target* target : *targets) {
- if (target->testonly() == testonly)
- result.push_back(target);
- }
-
- targets->swap(result);
- return true;
-}
-
-// Applies any target type filtering specified on the command line to the given
-// target set. On failure, prints an error and returns false.
-bool ApplyTypeFilter(std::vector<const Target*>* targets) {
- Target::OutputType type = Target::UNKNOWN;
- if (!GetTargetTypeFilter(&type))
- return false;
- if (targets->empty() || type == Target::UNKNOWN)
- return true; // Nothing to filter out.
-
- // Filter into a copy of the vector, then swap to output.
- std::vector<const Target*> result;
- result.reserve(targets->size());
-
- for (const Target* target : *targets) {
- // Make "action" also apply to ACTION_FOREACH.
- if (target->output_type() == type ||
- (type == Target::ACTION &&
- target->output_type() == Target::ACTION_FOREACH))
- result.push_back(target);
- }
-
- targets->swap(result);
- return true;
-}
-
-// Returns the file path generating this item.
-base::FilePath BuildFileForItem(const Item* item) {
- return item->defined_from()->GetRange().begin().file()->physical_name();
-}
-
-void PrintTargetsAsBuildfiles(const std::vector<const Target*>& targets,
- base::ListValue* out) {
- // Output the set of unique source files.
- std::set<std::string> unique_files;
- for (const Target* target : targets)
- unique_files.insert(FilePathToUTF8(BuildFileForItem(target)));
-
- for (const std::string& file : unique_files) {
- out->AppendString(file);
- }
-}
-
-void PrintTargetsAsLabels(const std::vector<const Target*>& targets,
- base::ListValue* out) {
- // Putting the labels into a set automatically sorts them for us.
- std::set<Label> unique_labels;
- for (auto* target : targets)
- unique_labels.insert(target->label());
-
- // Grab the label of the default toolchain from the first target.
- Label default_tc_label =
- targets[0]->settings()->default_toolchain_label();
-
- for (const Label& label : unique_labels) {
- // Print toolchain only for ones not in the default toolchain.
- out->AppendString(label.GetUserVisibleName(label.GetToolchainLabel() !=
- default_tc_label));
- }
-}
-
-void PrintTargetsAsOutputs(const std::vector<const Target*>& targets,
- base::ListValue* out) {
- if (targets.empty())
- return;
-
- // Grab the build settings from a random target.
- const BuildSettings* build_settings =
- targets[0]->settings()->build_settings();
-
- for (const Target* target : targets) {
- // Use the link output file if there is one, otherwise fall back to the
- // dependency output file (for actions, for example).
- OutputFile output_file = target->link_output_file();
- if (output_file.value().empty())
- output_file = target->dependency_output_file();
-
- SourceFile output_as_source =
- output_file.AsSourceFile(build_settings);
- std::string result = RebasePath(output_as_source.value(),
- build_settings->build_dir(),
- build_settings->root_path_utf8());
- out->AppendString(result);
- }
-}
-
-#if defined(OS_WIN)
-// Git bash will remove the first "/" in "//" paths
-// This also happens for labels assigned to command line parameters, e.g.
-// --filters
-// Fix "//" paths, but not absolute and relative paths
-inline std::string FixGitBashLabelEdit(const std::string& label) {
- static std::unique_ptr<base::Environment> git_bash_env;
- if (!git_bash_env)
- git_bash_env = base::Environment::Create();
-
- std::string temp_label(label);
-
- if (git_bash_env->HasVar(
- "MSYSTEM") && // Only for MinGW based shells like Git Bash
- temp_label[0] == '/' && // Only fix for //foo paths, not /f:oo paths
- (temp_label.length() < 2 ||
- (temp_label[1] != '/' &&
- (temp_label.length() < 3 || temp_label[1] != ':'))))
- temp_label.insert(0, "/");
- return temp_label;
-}
-#else
-// Only repair on Windows
-inline std::string FixGitBashLabelEdit(const std::string& label) {
- return label;
-}
-#endif
-
-
-} // namespace
-
-CommandInfo::CommandInfo()
- : help_short(nullptr),
- help(nullptr),
- runner(nullptr) {
-}
-
-CommandInfo::CommandInfo(const char* in_help_short,
- const char* in_help,
- CommandRunner in_runner)
- : help_short(in_help_short),
- help(in_help),
- runner(in_runner) {
-}
-
-const CommandInfoMap& GetCommands() {
- static CommandInfoMap info_map;
- if (info_map.empty()) {
- #define INSERT_COMMAND(cmd) \
- info_map[k##cmd] = CommandInfo(k##cmd##_HelpShort, \
- k##cmd##_Help, \
- &Run##cmd);
-
- INSERT_COMMAND(Analyze)
- INSERT_COMMAND(Args)
- INSERT_COMMAND(Check)
- INSERT_COMMAND(Clean)
- INSERT_COMMAND(Desc)
- INSERT_COMMAND(Gen)
- INSERT_COMMAND(Format)
- INSERT_COMMAND(Help)
- INSERT_COMMAND(Ls)
- INSERT_COMMAND(Path)
- INSERT_COMMAND(Refs)
-
- #undef INSERT_COMMAND
- }
- return info_map;
-}
-
-const Target* ResolveTargetFromCommandLineString(
- Setup* setup,
- const std::string& label_string) {
- // Need to resolve the label after we know the default toolchain.
- Label default_toolchain = setup->loader()->default_toolchain_label();
- Value arg_value(nullptr, FixGitBashLabelEdit(label_string));
- Err err;
- Label label = Label::Resolve(SourceDirForCurrentDirectory(
- setup->build_settings().root_path()),
- default_toolchain, arg_value, &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return nullptr;
- }
-
- const Item* item = setup->builder().GetItem(label);
- if (!item) {
- Err(Location(), "Label not found.",
- label.GetUserVisibleName(false) + " not found.").PrintToStdout();
- return nullptr;
- }
-
- const Target* target = item->AsTarget();
- if (!target) {
- Err(Location(), "Not a target.",
- "The \"" + label.GetUserVisibleName(false) + "\" thing\n"
- "is not a target. Somebody should probably implement this command for "
- "other\nitem types.").PrintToStdout();
- return nullptr;
- }
-
- return target;
-}
-
-bool ResolveFromCommandLineInput(
- Setup* setup,
- const std::vector<std::string>& input,
- bool all_toolchains,
- UniqueVector<const Target*>* target_matches,
- UniqueVector<const Config*>* config_matches,
- UniqueVector<const Toolchain*>* toolchain_matches,
- UniqueVector<SourceFile>* file_matches) {
- if (input.empty()) {
- Err(Location(), "You need to specify a label, file, or pattern.")
- .PrintToStdout();
- return false;
- }
-
- SourceDir cur_dir =
- SourceDirForCurrentDirectory(setup->build_settings().root_path());
- for (const auto& cur : input) {
- if (!ResolveStringFromCommandLineInput(setup, cur_dir, cur,
- all_toolchains, target_matches,
- config_matches, toolchain_matches,
- file_matches))
- return false;
- }
- return true;
-}
-
-void FilterTargetsByPatterns(const std::vector<const Target*>& input,
- const std::vector<LabelPattern>& filter,
- std::vector<const Target*>* output) {
- for (auto* target : input) {
- for (const auto& pattern : filter) {
- if (pattern.Matches(target->label())) {
- output->push_back(target);
- break;
- }
- }
- }
-}
-
-void FilterTargetsByPatterns(const std::vector<const Target*>& input,
- const std::vector<LabelPattern>& filter,
- UniqueVector<const Target*>* output) {
- for (auto* target : input) {
- for (const auto& pattern : filter) {
- if (pattern.Matches(target->label())) {
- output->push_back(target);
- break;
- }
- }
- }
-}
-
-bool FilterPatternsFromString(const BuildSettings* build_settings,
- const std::string& label_list_string,
- std::vector<LabelPattern>* filters,
- Err* err) {
- std::vector<std::string> tokens = base::SplitString(
- label_list_string, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- SourceDir root_dir("//");
-
- filters->reserve(tokens.size());
- for (const std::string& token : tokens) {
- LabelPattern pattern = LabelPattern::GetPattern(
- root_dir, Value(nullptr, FixGitBashLabelEdit(token)), err);
- if (err->has_error())
- return false;
- filters->push_back(pattern);
- }
-
- return true;
-}
-
-void FilterAndPrintTargets(std::vector<const Target*>* targets,
- base::ListValue* out) {
- if (targets->empty())
- return;
-
- if (!ApplyTestonlyFilter(targets))
- return;
- if (!ApplyTypeFilter(targets))
- return;
-
- TargetPrintingMode printing_mode = TARGET_PRINT_LABEL;
- if (targets->empty() || !GetTargetPrintingMode(&printing_mode))
- return;
- switch (printing_mode) {
- case TARGET_PRINT_BUILDFILE:
- PrintTargetsAsBuildfiles(*targets, out);
- break;
- case TARGET_PRINT_LABEL:
- PrintTargetsAsLabels(*targets, out);
- break;
- case TARGET_PRINT_OUTPUT:
- PrintTargetsAsOutputs(*targets, out);
- break;
- }
-}
-
-void FilterAndPrintTargets(bool indent, std::vector<const Target*>* targets) {
- base::ListValue tmp;
- FilterAndPrintTargets(targets, &tmp);
- for (const auto& value : tmp) {
- std::string string;
- value.GetAsString(&string);
- if (indent)
- OutputString(" ");
- OutputString(string);
- OutputString("\n");
- }
-}
-
-void FilterAndPrintTargetSet(bool indent,
- const std::set<const Target*>& targets) {
- std::vector<const Target*> target_vector(targets.begin(), targets.end());
- FilterAndPrintTargets(indent, &target_vector);
-}
-
-void FilterAndPrintTargetSet(const std::set<const Target*>& targets,
- base::ListValue* out) {
- std::vector<const Target*> target_vector(targets.begin(), targets.end());
- FilterAndPrintTargets(&target_vector, out);
-}
-
-} // namespace commands
diff --git a/chromium/tools/gn/commands.h b/chromium/tools/gn/commands.h
deleted file mode 100644
index 9593d4e1e1d..00000000000
--- a/chromium/tools/gn/commands.h
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_COMMANDS_H_
-#define TOOLS_GN_COMMANDS_H_
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/strings/string_piece.h"
-#include "base/values.h"
-#include "tools/gn/target.h"
-#include "tools/gn/unique_vector.h"
-
-class BuildSettings;
-class Config;
-class LabelPattern;
-class Setup;
-class SourceFile;
-class Target;
-class Toolchain;
-
-// Each "Run" command returns the value we should return from main().
-
-namespace commands {
-
-typedef int (*CommandRunner)(const std::vector<std::string>&);
-
-extern const char kAnalyze[];
-extern const char kAnalyze_HelpShort[];
-extern const char kAnalyze_Help[];
-int RunAnalyze(const std::vector<std::string>& args);
-
-extern const char kArgs[];
-extern const char kArgs_HelpShort[];
-extern const char kArgs_Help[];
-int RunArgs(const std::vector<std::string>& args);
-
-extern const char kCheck[];
-extern const char kCheck_HelpShort[];
-extern const char kCheck_Help[];
-int RunCheck(const std::vector<std::string>& args);
-
-extern const char kClean[];
-extern const char kClean_HelpShort[];
-extern const char kClean_Help[];
-int RunClean(const std::vector<std::string>& args);
-
-extern const char kDesc[];
-extern const char kDesc_HelpShort[];
-extern const char kDesc_Help[];
-int RunDesc(const std::vector<std::string>& args);
-
-extern const char kGen[];
-extern const char kGen_HelpShort[];
-extern const char kGen_Help[];
-int RunGen(const std::vector<std::string>& args);
-
-extern const char kFormat[];
-extern const char kFormat_HelpShort[];
-extern const char kFormat_Help[];
-int RunFormat(const std::vector<std::string>& args);
-
-extern const char kHelp[];
-extern const char kHelp_HelpShort[];
-extern const char kHelp_Help[];
-int RunHelp(const std::vector<std::string>& args);
-
-extern const char kLs[];
-extern const char kLs_HelpShort[];
-extern const char kLs_Help[];
-int RunLs(const std::vector<std::string>& args);
-
-extern const char kPath[];
-extern const char kPath_HelpShort[];
-extern const char kPath_Help[];
-int RunPath(const std::vector<std::string>& args);
-
-extern const char kRefs[];
-extern const char kRefs_HelpShort[];
-extern const char kRefs_Help[];
-int RunRefs(const std::vector<std::string>& args);
-
-// -----------------------------------------------------------------------------
-
-struct CommandInfo {
- CommandInfo();
- CommandInfo(const char* in_help_short,
- const char* in_help,
- CommandRunner in_runner);
-
- const char* help_short;
- const char* help;
- CommandRunner runner;
-};
-
-typedef std::map<base::StringPiece, CommandInfo> CommandInfoMap;
-
-const CommandInfoMap& GetCommands();
-
-// Helper functions for some commands ------------------------------------------
-
-// Given a setup that has already been run and some command-line input,
-// resolves that input as a target label and returns the corresponding target.
-// On failure, returns null and prints the error to the standard output.
-const Target* ResolveTargetFromCommandLineString(
- Setup* setup,
- const std::string& label_string);
-
-// Resolves a vector of command line inputs and figures out the full set of
-// things they resolve to.
-//
-// Patterns with wildcards will only match targets. The file_matches aren't
-// validated that they are real files or referenced by any targets. They're just
-// the set of things that didn't match anything else.
-bool ResolveFromCommandLineInput(
- Setup* setup,
- const std::vector<std::string>& input,
- bool all_toolchains,
- UniqueVector<const Target*>* target_matches,
- UniqueVector<const Config*>* config_matches,
- UniqueVector<const Toolchain*>* toolchain_matches,
- UniqueVector<SourceFile>* file_matches);
-
-// Runs the header checker. All targets in the build should be given in
-// all_targets, and the specific targets to check should be in to_check.
-//
-// force_check, if true, will override targets opting out of header checking
-// with "check_includes = false" and will check them anyway.
-//
-// On success, returns true. If the check fails, the error(s) will be printed
-// to stdout and false will be returned.
-bool CheckPublicHeaders(const BuildSettings* build_settings,
- const std::vector<const Target*>& all_targets,
- const std::vector<const Target*>& to_check,
- bool force_check);
-
-// Filters the given list of targets by the given pattern list.
-void FilterTargetsByPatterns(const std::vector<const Target*>& input,
- const std::vector<LabelPattern>& filter,
- std::vector<const Target*>* output);
-void FilterTargetsByPatterns(const std::vector<const Target*>& input,
- const std::vector<LabelPattern>& filter,
- UniqueVector<const Target*>* output);
-
-// Builds a list of pattern from a semicolon-separated list of labels.
-bool FilterPatternsFromString(const BuildSettings* build_settings,
- const std::string& label_list_string,
- std::vector<LabelPattern>* filters,
- Err* err);
-
-// These are the documentation strings for the command-line flags used by
-// FilterAndPrintTargets. Commands that call that function should incorporate
-// these into their help.
-#define TARGET_PRINTING_MODE_COMMAND_LINE_HELP \
- " --as=(buildfile|label|output)\n"\
- " How to print targets.\n"\
- "\n"\
- " buildfile\n"\
- " Prints the build files where the given target was declared as\n"\
- " file names.\n"\
- " label (default)\n"\
- " Prints the label of the target.\n"\
- " output\n"\
- " Prints the first output file for the target relative to the\n"\
- " root build directory.\n"
-#define TARGET_TYPE_FILTER_COMMAND_LINE_HELP \
- " --type=(action|copy|executable|group|loadable_module|shared_library|\n"\
- " source_set|static_library)\n"\
- " Restrict outputs to targets matching the given type. If\n"\
- " unspecified, no filtering will be performed.\n"
-#define TARGET_TESTONLY_FILTER_COMMAND_LINE_HELP \
- " --testonly=(true|false)\n"\
- " Restrict outputs to targets with the testonly flag set\n"\
- " accordingly. When unspecified, the target's testonly flags are\n"\
- " ignored.\n"
-
-// Applies any testonly and type filters specified on the command line,
-// and prints the targets as specified by the --as command line flag.
-//
-// If indent is true, the results will be indented two spaces.
-//
-// The vector will be modified so that only the printed targets will remain.
-void FilterAndPrintTargets(bool indent, std::vector<const Target*>* targets);
-void FilterAndPrintTargets(std::vector<const Target*>* targets,
- base::ListValue* out);
-
-void FilterAndPrintTargetSet(bool indent,
- const std::set<const Target*>& targets);
-void FilterAndPrintTargetSet(const std::set<const Target*>& targets,
- base::ListValue* out);
-
-// Extra help from command_check.cc
-extern const char kNoGnCheck_Help[];
-
-} // namespace commands
-
-#endif // TOOLS_GN_COMMANDS_H_
diff --git a/chromium/tools/gn/config.cc b/chromium/tools/gn/config.cc
deleted file mode 100644
index e021fe40b9d..00000000000
--- a/chromium/tools/gn/config.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/config.h"
-
-#include "tools/gn/err.h"
-#include "tools/gn/input_file_manager.h"
-#include "tools/gn/scheduler.h"
-
-Config::Config(const Settings* settings,
- const Label& label,
- const std::set<SourceFile>& build_dependency_files)
- : Item(settings, label, build_dependency_files), resolved_(false) {}
-
-Config::~Config() = default;
-
-Config* Config::AsConfig() {
- return this;
-}
-
-const Config* Config::AsConfig() const {
- return this;
-}
-
-bool Config::OnResolved(Err* err) {
- DCHECK(!resolved_);
- resolved_ = true;
-
- if (!configs_.empty()) {
- // Subconfigs, flatten.
- //
- // Implementation note for the future: Flattening these here means we
- // lose the ability to de-dupe subconfigs. If a subconfig is listed as
- // a separate config or a subconfig that also applies to the target, the
- // subconfig's flags will be duplicated.
- //
- // If we want to be able to de-dupe these, here's one idea. As a config is
- // resolved, inline any sub-sub configs so the configs_ vector is a flat
- // list, much the same way that libs and lib_dirs are pushed through
- // targets. Do the same for Target.configs_ when a target is resolved. This
- // will naturally de-dupe and also prevents recursive config walking to
- // compute every possible flag, although it will expand the configs list on
- // a target nontrivially (depending on build configuration).
- composite_values_ = own_values_;
- for (const auto& pair : configs_)
- composite_values_.AppendValues(pair.ptr->resolved_values());
- }
- return true;
-}
diff --git a/chromium/tools/gn/config.h b/chromium/tools/gn/config.h
deleted file mode 100644
index ad049737330..00000000000
--- a/chromium/tools/gn/config.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_CONFIG_H_
-#define TOOLS_GN_CONFIG_H_
-
-#include <set>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "tools/gn/config_values.h"
-#include "tools/gn/item.h"
-#include "tools/gn/label_ptr.h"
-#include "tools/gn/unique_vector.h"
-
-// Represents a named config in the dependency graph.
-//
-// A config can list other configs. We track both the data assigned directly
-// on the config, this list of sub-configs, and (when the config is resolved)
-// the resulting values of everything merged together. The flatten step
-// means we can avoid doing a recursive config walk for every target to compute
-// flags.
-class Config : public Item {
- public:
- // We track the set of build files that may affect this config, please refer
- // to Scope for how this is determined.
- Config(const Settings* settings,
- const Label& label,
- const std::set<SourceFile>& build_dependency_files = {});
- ~Config() override;
-
- // Item implementation.
- Config* AsConfig() override;
- const Config* AsConfig() const override;
- bool OnResolved(Err* err) override;
-
- // The values set directly on this config. This will not contain data from
- // sub-configs.
- ConfigValues& own_values() { return own_values_; }
- const ConfigValues& own_values() const { return own_values_; }
-
- // The values that represent this config and all sub-configs combined into
- // one. This is only valid after the config is resolved (when we know the
- // contents of the sub-configs).
- const ConfigValues& resolved_values() const {
- DCHECK(resolved_);
- if (configs_.empty()) // No sub configs, just use the regular values.
- return own_values_;
- return composite_values_;
- }
-
- // List of sub-configs.
- const UniqueVector<LabelConfigPair>& configs() const { return configs_; }
- UniqueVector<LabelConfigPair>& configs() { return configs_; }
-
- private:
- ConfigValues own_values_;
-
- // Contains the own_values combined with sub-configs. Most configs don't have
- // sub-configs. So as an optimization, this is not populated if there are no
- // items in configs_. The resolved_values() getter handles this.
- bool resolved_;
- ConfigValues composite_values_;
-
- UniqueVector<LabelConfigPair> configs_;
-
- DISALLOW_COPY_AND_ASSIGN(Config);
-};
-
-#endif // TOOLS_GN_CONFIG_H_
diff --git a/chromium/tools/gn/config_unittest.cc b/chromium/tools/gn/config_unittest.cc
deleted file mode 100644
index 9a1e01df62f..00000000000
--- a/chromium/tools/gn/config_unittest.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/config.h"
-#include "tools/gn/test_with_scope.h"
-
-// Tests that the "resolved" values are the same as "own" values when there
-// are no subconfigs.
-TEST(Config, ResolvedNoSub) {
- TestWithScope setup;
- Err err;
-
- Config config(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- config.own_values().defines().push_back("FOO");
- ASSERT_TRUE(config.OnResolved(&err));
-
- // The resolved values should be the same as the value we put in to
- // own_values().
- ASSERT_EQ(1u, config.resolved_values().defines().size());
- EXPECT_EQ("FOO", config.resolved_values().defines()[0]);
-
- // As an optimization, the string should actually refer to the original. This
- // isn't required to pass for semantic correctness, though.
- EXPECT_TRUE(&config.own_values() == &config.resolved_values());
-}
-
-// Tests that subconfigs are resolved in the correct order.
-TEST(Config, ResolvedSub) {
- TestWithScope setup;
- Err err;
-
- Config sub1(setup.settings(), Label(SourceDir("//foo/"), "1"));
- sub1.own_values().defines().push_back("ONE");
- ASSERT_TRUE(sub1.OnResolved(&err));
-
- Config sub2(setup.settings(), Label(SourceDir("//foo/"), "2"));
- sub2.own_values().defines().push_back("TWO");
- ASSERT_TRUE(sub2.OnResolved(&err));
-
- Config config(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- config.own_values().defines().push_back("FOO");
- config.configs().push_back(LabelConfigPair(&sub1));
- config.configs().push_back(LabelConfigPair(&sub2));
- ASSERT_TRUE(config.OnResolved(&err));
-
- // The resolved values should be the same as the value we put in to
- // own_values().
- ASSERT_EQ(3u, config.resolved_values().defines().size());
- EXPECT_EQ("FOO", config.resolved_values().defines()[0]);
- EXPECT_EQ("ONE", config.resolved_values().defines()[1]);
- EXPECT_EQ("TWO", config.resolved_values().defines()[2]);
-
- // The "own" values should be unchanged.
- ASSERT_EQ(1u, config.own_values().defines().size());
- EXPECT_EQ("FOO", config.own_values().defines()[0]);
-}
-
-// Tests that subconfigs of subconfigs are resolved properly.
-TEST(Config, SubSub) {
- TestWithScope setup;
- Err err;
-
- // Set up first -> middle -> last configs.
- Config last(setup.settings(), Label(SourceDir("//foo/"), "last"));
- last.own_values().defines().push_back("LAST");
- ASSERT_TRUE(last.OnResolved(&err));
-
- Config middle(setup.settings(), Label(SourceDir("//foo/"), "middle"));
- middle.own_values().defines().push_back("MIDDLE");
- middle.configs().push_back(LabelConfigPair(&last));
- ASSERT_TRUE(middle.OnResolved(&err));
-
- Config first(setup.settings(), Label(SourceDir("//foo/"), "first"));
- first.own_values().defines().push_back("FIRST");
- first.configs().push_back(LabelConfigPair(&middle));
- ASSERT_TRUE(first.OnResolved(&err));
-
- // Check final resolved defines on "first".
- ASSERT_EQ(3u, first.resolved_values().defines().size());
- EXPECT_EQ("FIRST", first.resolved_values().defines()[0]);
- EXPECT_EQ("MIDDLE", first.resolved_values().defines()[1]);
- EXPECT_EQ("LAST", first.resolved_values().defines()[2]);
-}
diff --git a/chromium/tools/gn/config_values.cc b/chromium/tools/gn/config_values.cc
deleted file mode 100644
index b3e9f6f148d..00000000000
--- a/chromium/tools/gn/config_values.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/config_values.h"
-
-namespace {
-
-template<typename T>
-void VectorAppend(std::vector<T>* append_to,
- const std::vector<T>& append_this) {
- if (append_this.empty())
- return;
- append_to->insert(append_to->end(),append_this.begin(), append_this.end());
-}
-
-} // namespace
-
-ConfigValues::ConfigValues() = default;
-
-ConfigValues::~ConfigValues() = default;
-
-void ConfigValues::AppendValues(const ConfigValues& append) {
- VectorAppend(&asmflags_, append.asmflags_);
- VectorAppend(&arflags_, append.arflags_);
- VectorAppend(&cflags_, append.cflags_);
- VectorAppend(&cflags_c_, append.cflags_c_);
- VectorAppend(&cflags_cc_, append.cflags_cc_);
- VectorAppend(&cflags_objc_, append.cflags_objc_);
- VectorAppend(&cflags_objcc_, append.cflags_objcc_);
- VectorAppend(&defines_, append.defines_);
- VectorAppend(&include_dirs_, append.include_dirs_);
- VectorAppend(&inputs_, append.inputs_);
- VectorAppend(&ldflags_, append.ldflags_);
- VectorAppend(&lib_dirs_, append.lib_dirs_);
- VectorAppend(&libs_, append.libs_);
-
- // Only append precompiled header if there isn't one. It might be nice to
- // throw an error if there are conflicting precompiled headers, but that
- // requires piping through some context of the actual configs involved, and
- // conflicts here should be very unusual. Instead, use the first value.
- if (!append.precompiled_header_.empty() && !precompiled_header_.empty())
- precompiled_header_ = append.precompiled_header_;
- if (!append.precompiled_source_.is_null() && !precompiled_source_.is_null())
- precompiled_source_ = append.precompiled_source_;
-}
diff --git a/chromium/tools/gn/config_values.h b/chromium/tools/gn/config_values.h
deleted file mode 100644
index 0099e81b004..00000000000
--- a/chromium/tools/gn/config_values.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_CONFIG_VALUES_H_
-#define TOOLS_GN_CONFIG_VALUES_H_
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "tools/gn/lib_file.h"
-#include "tools/gn/source_dir.h"
-#include "tools/gn/source_file.h"
-
-// Holds the values (include_dirs, defines, compiler flags, etc.) for a given
-// config or target.
-class ConfigValues {
- public:
- ConfigValues();
- ~ConfigValues();
-
- // Appends the values from the given config to this one.
- void AppendValues(const ConfigValues& append);
-
-#define STRING_VALUES_ACCESSOR(name) \
- const std::vector<std::string>& name() const { return name##_; } \
- std::vector<std::string>& name() { return name##_; }
-#define DIR_VALUES_ACCESSOR(name) \
- const std::vector<SourceDir>& name() const { return name##_; } \
- std::vector<SourceDir>& name() { return name##_; }
-
- // =================================================================
- // IMPORTANT: If you add a new one, be sure to update AppendValues()
- // and command_desc.cc.
- // =================================================================
- STRING_VALUES_ACCESSOR(arflags)
- STRING_VALUES_ACCESSOR(asmflags)
- STRING_VALUES_ACCESSOR(cflags)
- STRING_VALUES_ACCESSOR(cflags_c)
- STRING_VALUES_ACCESSOR(cflags_cc)
- STRING_VALUES_ACCESSOR(cflags_objc)
- STRING_VALUES_ACCESSOR(cflags_objcc)
- STRING_VALUES_ACCESSOR(defines)
- DIR_VALUES_ACCESSOR (include_dirs)
- STRING_VALUES_ACCESSOR(ldflags)
- DIR_VALUES_ACCESSOR (lib_dirs)
- // =================================================================
- // IMPORTANT: If you add a new one, be sure to update AppendValues()
- // and command_desc.cc.
- // =================================================================
-
-#undef STRING_VALUES_ACCESSOR
-#undef DIR_VALUES_ACCESSOR
-
- const std::vector<SourceFile>& inputs() const { return inputs_; }
- std::vector<SourceFile>& inputs() { return inputs_; }
-
- const std::vector<LibFile>& libs() const { return libs_; }
- std::vector<LibFile>& libs() { return libs_; }
-
- bool has_precompiled_headers() const {
- return !precompiled_header_.empty() || !precompiled_source_.is_null();
- }
- const std::string& precompiled_header() const {
- return precompiled_header_;
- }
- void set_precompiled_header(const std::string& f) {
- precompiled_header_ = f;
- }
- const SourceFile& precompiled_source() const {
- return precompiled_source_;
- }
- void set_precompiled_source(const SourceFile& f) {
- precompiled_source_ = f;
- }
-
- private:
- std::vector<std::string> arflags_;
- std::vector<std::string> asmflags_;
- std::vector<std::string> cflags_;
- std::vector<std::string> cflags_c_;
- std::vector<std::string> cflags_cc_;
- std::vector<std::string> cflags_objc_;
- std::vector<std::string> cflags_objcc_;
- std::vector<std::string> defines_;
- std::vector<SourceDir> include_dirs_;
- std::vector<SourceFile> inputs_;
- std::vector<std::string> ldflags_;
- std::vector<SourceDir> lib_dirs_;
- std::vector<LibFile> libs_;
- // If you add a new one, be sure to update AppendValues().
-
- std::string precompiled_header_;
- SourceFile precompiled_source_;
-};
-
-#endif // TOOLS_GN_CONFIG_VALUES_H_
diff --git a/chromium/tools/gn/config_values_extractors.cc b/chromium/tools/gn/config_values_extractors.cc
deleted file mode 100644
index 18617db7970..00000000000
--- a/chromium/tools/gn/config_values_extractors.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/config_values_extractors.h"
-
-#include "tools/gn/escape.h"
-
-namespace {
-
-class EscapedStringWriter {
- public:
- explicit EscapedStringWriter(const EscapeOptions& escape_options)
- : escape_options_(escape_options) {
- }
-
- void operator()(const std::string& s, std::ostream& out) const {
- out << " ";
- EscapeStringToStream(out, s, escape_options_);
- }
-
- private:
- const EscapeOptions& escape_options_;
-};
-
-} // namespace
-
-void RecursiveTargetConfigStringsToStream(
- const Target* target,
- const std::vector<std::string>& (ConfigValues::* getter)() const,
- const EscapeOptions& escape_options,
- std::ostream& out) {
- RecursiveTargetConfigToStream(target, getter,
- EscapedStringWriter(escape_options), out);
-}
diff --git a/chromium/tools/gn/config_values_extractors.h b/chromium/tools/gn/config_values_extractors.h
deleted file mode 100644
index f87f52b42e4..00000000000
--- a/chromium/tools/gn/config_values_extractors.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_CONFIG_VALUES_EXTRACTORS_H_
-#define TOOLS_GN_CONFIG_VALUES_EXTRACTORS_H_
-
-#include <stddef.h>
-
-#include <ostream>
-#include <string>
-#include <vector>
-
-#include "tools/gn/config.h"
-#include "tools/gn/config_values.h"
-#include "tools/gn/target.h"
-
-struct EscapeOptions;
-
-// Provides a way to iterate through all ConfigValues applying to a given
-// target. This is more complicated than normal because the target has a list
-// of configs applying to it, and also config values on the target itself.
-//
-// This iterator allows one to iterate through all of these in a defined order
-// in one convenient loop. The order is defined to be the ConfigValues on the
-// target itself first, then the applying configs, in order.
-//
-// Example:
-// for (ConfigValueIterator iter(target); !iter.done(); iter.Next())
-// DoSomething(iter.cur());
-class ConfigValuesIterator {
- public:
- explicit ConfigValuesIterator(const Target* target)
- : target_(target),
- cur_index_(-1) {
- }
-
- bool done() const {
- return cur_index_ >= static_cast<int>(target_->configs().size());
- }
-
- const ConfigValues& cur() const {
- if (cur_index_ == -1)
- return target_->config_values();
- return target_->configs()[cur_index_].ptr->resolved_values();
- }
-
- // Returns the origin of who added this config, if any. This will always be
- // null for the config values of a target itself.
- const ParseNode* origin() const {
- if (cur_index_ == -1)
- return nullptr;
- return target_->configs()[cur_index_].origin;
- }
-
- void Next() {
- cur_index_++;
- }
-
- // Returns the config holding the current config values, or NULL for those
- // config values associated with the target itself.
- const Config* GetCurrentConfig() const {
- if (cur_index_ == -1)
- return nullptr;
- return target_->configs()[cur_index_].ptr;
- }
-
- private:
- const Target* target_;
-
- // Represents an index into the target_'s configs() or, when -1, the config
- // values on the target itself.
- int cur_index_;
-};
-
-template<typename T, class Writer>
-inline void ConfigValuesToStream(
- const ConfigValues& values,
- const std::vector<T>& (ConfigValues::* getter)() const,
- const Writer& writer,
- std::ostream& out) {
- const std::vector<T>& v = (values.*getter)();
- for (size_t i = 0; i < v.size(); i++)
- writer(v[i], out);
-}
-
-// Writes a given config value that applies to a given target. This collects
-// all values from the target itself and all configs that apply, and writes
-// then in order.
-template<typename T, class Writer>
-inline void RecursiveTargetConfigToStream(
- const Target* target,
- const std::vector<T>& (ConfigValues::* getter)() const,
- const Writer& writer,
- std::ostream& out) {
- for (ConfigValuesIterator iter(target); !iter.done(); iter.Next())
- ConfigValuesToStream(iter.cur(), getter, writer, out);
-}
-
-// Writes the values out as strings with no transformation.
-void RecursiveTargetConfigStringsToStream(
- const Target* target,
- const std::vector<std::string>& (ConfigValues::* getter)() const,
- const EscapeOptions& escape_options,
- std::ostream& out);
-
-#endif // TOOLS_GN_CONFIG_VALUES_EXTRACTORS_H_
diff --git a/chromium/tools/gn/config_values_extractors_unittest.cc b/chromium/tools/gn/config_values_extractors_unittest.cc
deleted file mode 100644
index b8875eafa85..00000000000
--- a/chromium/tools/gn/config_values_extractors_unittest.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <sstream>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/config.h"
-#include "tools/gn/config_values_extractors.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-struct FlagWriter {
- void operator()(const std::string& dir, std::ostream& out) const {
- out << dir << " ";
- }
-};
-
-struct IncludeWriter {
- void operator()(const SourceDir& dir, std::ostream& out) const {
- out << dir.value() << " ";
- }
-};
-
-} // namespace
-
-TEST(ConfigValuesExtractors, IncludeOrdering) {
- TestWithScope setup;
- Err err;
-
- // Construct a chain of dependencies: target -> dep1 -> dep2
- // Add representative values: cflags (opaque, always copied) and include_dirs
- // (uniquified) to each one so we can check what comes out the other end.
-
- // Set up dep2, direct and all dependent configs.
- Config dep2_all(setup.settings(), Label(SourceDir("//dep2/"), "all"));
- dep2_all.own_values().cflags().push_back("--dep2-all");
- dep2_all.own_values().include_dirs().push_back(SourceDir("//dep2/all/"));
- ASSERT_TRUE(dep2_all.OnResolved(&err));
-
- Config dep2_direct(setup.settings(), Label(SourceDir("//dep2/"), "direct"));
- dep2_direct.own_values().cflags().push_back("--dep2-direct");
- dep2_direct.own_values().include_dirs().push_back(
- SourceDir("//dep2/direct/"));
- ASSERT_TRUE(dep2_direct.OnResolved(&err));
-
- Target dep2(setup.settings(), Label(SourceDir("//dep2/"), "dep2"));
- dep2.set_output_type(Target::SOURCE_SET);
- dep2.visibility().SetPublic();
- dep2.SetToolchain(setup.toolchain());
- dep2.all_dependent_configs().push_back(LabelConfigPair(&dep2_all));
- dep2.public_configs().push_back(LabelConfigPair(&dep2_direct));
-
- // Set up dep1, direct and all dependent configs. Also set up a subconfig
- // on "dep1_all" to test sub configs.
- Config dep1_all_sub(setup.settings(), Label(SourceDir("//dep1"), "allch"));
- dep1_all_sub.own_values().cflags().push_back("--dep1-all-sub");
- ASSERT_TRUE(dep1_all_sub.OnResolved(&err));
-
- Config dep1_all(setup.settings(), Label(SourceDir("//dep1/"), "all"));
- dep1_all.own_values().cflags().push_back("--dep1-all");
- dep1_all.own_values().include_dirs().push_back(SourceDir("//dep1/all/"));
- dep1_all.configs().push_back(LabelConfigPair(&dep1_all_sub));
- ASSERT_TRUE(dep1_all.OnResolved(&err));
-
- Config dep1_direct(setup.settings(), Label(SourceDir("//dep1/"), "direct"));
- dep1_direct.own_values().cflags().push_back("--dep1-direct");
- dep1_direct.own_values().include_dirs().push_back(
- SourceDir("//dep1/direct/"));
- ASSERT_TRUE(dep1_direct.OnResolved(&err));
-
- Target dep1(setup.settings(), Label(SourceDir("//dep1/"), "dep1"));
- dep1.set_output_type(Target::SOURCE_SET);
- dep1.visibility().SetPublic();
- dep1.SetToolchain(setup.toolchain());
- dep1.all_dependent_configs().push_back(LabelConfigPair(&dep1_all));
- dep1.public_configs().push_back(LabelConfigPair(&dep1_direct));
- dep1.private_deps().push_back(LabelTargetPair(&dep2));
-
- // Set up target, direct and all dependent configs.
- Config target_all(setup.settings(), Label(SourceDir("//target/"), "all"));
- target_all.own_values().cflags().push_back("--target-all");
- target_all.own_values().include_dirs().push_back(SourceDir("//target/all/"));
- ASSERT_TRUE(target_all.OnResolved(&err));
-
- Config target_direct(setup.settings(),
- Label(SourceDir("//target/"), "direct"));
- target_direct.own_values().cflags().push_back("--target-direct");
- target_direct.own_values().include_dirs().push_back(
- SourceDir("//target/direct/"));
- ASSERT_TRUE(target_direct.OnResolved(&err));
-
- // This config is applied directly to target.
- Config target_config(setup.settings(),
- Label(SourceDir("//target/"), "config"));
- target_config.own_values().cflags().push_back("--target-config");
- target_config.own_values().include_dirs().push_back(
- SourceDir("//target/config/"));
- ASSERT_TRUE(target_config.OnResolved(&err));
-
- Target target(setup.settings(), Label(SourceDir("//target/"), "target"));
- target.set_output_type(Target::SOURCE_SET);
- target.SetToolchain(setup.toolchain());
- target.all_dependent_configs().push_back(LabelConfigPair(&target_all));
- target.public_configs().push_back(LabelConfigPair(&target_direct));
- target.configs().push_back(LabelConfigPair(&target_config));
- target.private_deps().push_back(LabelTargetPair(&dep1));
-
- // Additionally add some values directly on "target".
- target.config_values().cflags().push_back("--target");
- target.config_values().include_dirs().push_back(
- SourceDir("//target/"));
-
- // Mark targets resolved. This should push dependent configs.
- ASSERT_TRUE(dep2.OnResolved(&err));
- ASSERT_TRUE(dep1.OnResolved(&err));
- ASSERT_TRUE(target.OnResolved(&err));
-
- // Verify cflags by serializing.
- std::ostringstream flag_out;
- FlagWriter flag_writer;
- RecursiveTargetConfigToStream<std::string, FlagWriter>(
- &target, &ConfigValues::cflags, flag_writer, flag_out);
- EXPECT_EQ(flag_out.str(),
- "--target --target-config --target-all --target-direct "
- "--dep1-all --dep1-all-sub --dep2-all --dep1-direct ");
-
- // Verify include dirs by serializing.
- std::ostringstream include_out;
- IncludeWriter include_writer;
- RecursiveTargetConfigToStream<SourceDir, IncludeWriter>(
- &target, &ConfigValues::include_dirs, include_writer, include_out);
- EXPECT_EQ(include_out.str(),
- "//target/ //target/config/ //target/all/ //target/direct/ "
- "//dep1/all/ //dep2/all/ //dep1/direct/ ");
-}
diff --git a/chromium/tools/gn/config_values_generator.cc b/chromium/tools/gn/config_values_generator.cc
deleted file mode 100644
index 97888ace5b8..00000000000
--- a/chromium/tools/gn/config_values_generator.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/config_values_generator.h"
-
-#include "base/strings/string_util.h"
-#include "tools/gn/config_values.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/value.h"
-#include "tools/gn/value_extractors.h"
-#include "tools/gn/variables.h"
-
-namespace {
-
-void GetStringList(
- Scope* scope,
- const char* var_name,
- ConfigValues* config_values,
- std::vector<std::string>& (ConfigValues::* accessor)(),
- Err* err) {
- const Value* value = scope->GetValue(var_name, true);
- if (!value)
- return; // No value, empty input and succeed.
-
- ExtractListOfStringValues(*value, &(config_values->*accessor)(), err);
-}
-
-void GetDirList(
- Scope* scope,
- const char* var_name,
- ConfigValues* config_values,
- const SourceDir input_dir,
- std::vector<SourceDir>& (ConfigValues::* accessor)(),
- Err* err) {
- const Value* value = scope->GetValue(var_name, true);
- if (!value)
- return; // No value, empty input and succeed.
-
- std::vector<SourceDir> result;
- ExtractListOfRelativeDirs(scope->settings()->build_settings(),
- *value, input_dir, &result, err);
- (config_values->*accessor)().swap(result);
-}
-
-} // namespace
-
-ConfigValuesGenerator::ConfigValuesGenerator(
- ConfigValues* dest_values,
- Scope* scope,
- const SourceDir& input_dir,
- Err* err)
- : config_values_(dest_values),
- scope_(scope),
- input_dir_(input_dir),
- err_(err) {
-}
-
-ConfigValuesGenerator::~ConfigValuesGenerator() = default;
-
-void ConfigValuesGenerator::Run() {
-#define FILL_STRING_CONFIG_VALUE(name) \
- GetStringList(scope_, #name, config_values_, &ConfigValues::name, err_);
-#define FILL_DIR_CONFIG_VALUE(name) \
- GetDirList(scope_, #name, config_values_, input_dir_, \
- &ConfigValues::name, err_);
-
- FILL_STRING_CONFIG_VALUE(arflags)
- FILL_STRING_CONFIG_VALUE(asmflags)
- FILL_STRING_CONFIG_VALUE(cflags)
- FILL_STRING_CONFIG_VALUE(cflags_c)
- FILL_STRING_CONFIG_VALUE(cflags_cc)
- FILL_STRING_CONFIG_VALUE(cflags_objc)
- FILL_STRING_CONFIG_VALUE(cflags_objcc)
- FILL_STRING_CONFIG_VALUE(defines)
- FILL_DIR_CONFIG_VALUE( include_dirs)
- FILL_STRING_CONFIG_VALUE(ldflags)
- FILL_DIR_CONFIG_VALUE( lib_dirs)
-
-#undef FILL_STRING_CONFIG_VALUE
-#undef FILL_DIR_CONFIG_VALUE
-
- // Inputs
- const Value* inputs_value = scope_->GetValue(variables::kInputs, true);
- if (inputs_value) {
- ExtractListOfRelativeFiles(scope_->settings()->build_settings(),
- *inputs_value, input_dir_,
- &config_values_->inputs(), err_);
- }
-
- // Libs
- const Value* libs_value = scope_->GetValue("libs", true);
- if (libs_value) {
- ExtractListOfLibs(scope_->settings()->build_settings(), *libs_value,
- input_dir_, &config_values_->libs(), err_);
- }
-
- // Precompiled headers.
- const Value* precompiled_header_value =
- scope_->GetValue(variables::kPrecompiledHeader, true);
- if (precompiled_header_value) {
- if (!precompiled_header_value->VerifyTypeIs(Value::STRING, err_))
- return;
-
- // Check for common errors. This is a string and not a file.
- const std::string& pch_string = precompiled_header_value->string_value();
- if (base::StartsWith(pch_string, "//", base::CompareCase::SENSITIVE)) {
- *err_ = Err(*precompiled_header_value,
- "This precompiled_header value is wrong.",
- "You need to specify a string that the compiler will match against\n"
- "the #include lines rather than a GN-style file name.\n");
- return;
- }
- config_values_->set_precompiled_header(pch_string);
- }
-
- const Value* precompiled_source_value =
- scope_->GetValue(variables::kPrecompiledSource, true);
- if (precompiled_source_value) {
- config_values_->set_precompiled_source(
- input_dir_.ResolveRelativeFile(
- *precompiled_source_value, err_,
- scope_->settings()->build_settings()->root_path_utf8()));
- if (err_->has_error())
- return;
- }
-}
diff --git a/chromium/tools/gn/config_values_generator.h b/chromium/tools/gn/config_values_generator.h
deleted file mode 100644
index 165f41a9532..00000000000
--- a/chromium/tools/gn/config_values_generator.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_CONFIG_VALUES_GENERATOR_H_
-#define TOOLS_GN_CONFIG_VALUES_GENERATOR_H_
-
-#include "base/macros.h"
-#include "tools/gn/source_dir.h"
-
-class ConfigValues;
-class Err;
-class Scope;
-
-// This class fills in the config values from a given scope. It's shared
-// between the "config" function call and all the different binary target types
-// (shared library, static library, etc.) since all of these support the
-// various flags stored in the ConfigValues class.
-class ConfigValuesGenerator {
- public:
- ConfigValuesGenerator(ConfigValues* dest_values,
- Scope* scope,
- const SourceDir& input_dir,
- Err* err);
- ~ConfigValuesGenerator();
-
- // Sets the error passed to the constructor on failure.
- void Run();
-
- private:
- ConfigValues* config_values_;
- Scope* scope_;
- const SourceDir input_dir_;
- Err* err_;
-
- DISALLOW_COPY_AND_ASSIGN(ConfigValuesGenerator);
-};
-
-// For using in documentation for functions which use this.
-#define CONFIG_VALUES_VARS_HELP \
- " Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,\n" \
- " asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,\n" \
- " libs, precompiled_header, precompiled_source\n"
-
-#endif // TOOLS_GN_CONFIG_VALUES_GENERATOR_H_
diff --git a/chromium/tools/gn/copy_target_generator.cc b/chromium/tools/gn/copy_target_generator.cc
deleted file mode 100644
index a86f820c4f4..00000000000
--- a/chromium/tools/gn/copy_target_generator.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/copy_target_generator.h"
-
-#include "tools/gn/build_settings.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/value.h"
-
-CopyTargetGenerator::CopyTargetGenerator(Target* target,
- Scope* scope,
- const FunctionCallNode* function_call,
- Err* err)
- : TargetGenerator(target, scope, function_call, err) {
-}
-
-CopyTargetGenerator::~CopyTargetGenerator() = default;
-
-void CopyTargetGenerator::DoRun() {
- target_->set_output_type(Target::COPY_FILES);
-
- if (!FillSources())
- return;
- if (!FillOutputs(true))
- return;
-
- if (target_->sources().empty()) {
- *err_ = Err(function_call_, "Empty sources for copy command.",
- "You have to specify at least one file to copy in the \"sources\".");
- return;
- }
- if (target_->action_values().outputs().list().size() != 1) {
- *err_ = Err(function_call_, "Copy command must have exactly one output.",
- "You must specify exactly one value in the \"outputs\" array for the "
- "destination of the copy\n(see \"gn help copy\"). If there are "
- "multiple sources to copy, use source expansion\n(see \"gn help "
- "source_expansion\").");
- return;
- }
-}
diff --git a/chromium/tools/gn/copy_target_generator.h b/chromium/tools/gn/copy_target_generator.h
deleted file mode 100644
index b05855f6ae5..00000000000
--- a/chromium/tools/gn/copy_target_generator.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_COPY_TARGET_GENERATOR_H_
-#define TOOLS_GN_COPY_TARGET_GENERATOR_H_
-
-#include "base/macros.h"
-#include "tools/gn/target_generator.h"
-
-// Populates a Target with the values from a copy rule.
-class CopyTargetGenerator : public TargetGenerator {
- public:
- CopyTargetGenerator(Target* target,
- Scope* scope,
- const FunctionCallNode* function_call,
- Err* err);
- ~CopyTargetGenerator() override;
-
- protected:
- void DoRun() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CopyTargetGenerator);
-};
-
-#endif // TOOLS_GN_COPY_TARGET_GENERATOR_H_
-
diff --git a/chromium/tools/gn/create_bundle_target_generator.cc b/chromium/tools/gn/create_bundle_target_generator.cc
deleted file mode 100644
index d4b8f55513a..00000000000
--- a/chromium/tools/gn/create_bundle_target_generator.cc
+++ /dev/null
@@ -1,301 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/create_bundle_target_generator.h"
-
-#include <map>
-
-#include "base/logging.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/label_pattern.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/substitution_type.h"
-#include "tools/gn/target.h"
-#include "tools/gn/value.h"
-#include "tools/gn/value_extractors.h"
-#include "tools/gn/variables.h"
-
-CreateBundleTargetGenerator::CreateBundleTargetGenerator(
- Target* target,
- Scope* scope,
- const FunctionCallNode* function_call,
- Err* err)
- : TargetGenerator(target, scope, function_call, err) {}
-
-CreateBundleTargetGenerator::~CreateBundleTargetGenerator() = default;
-
-void CreateBundleTargetGenerator::DoRun() {
- target_->set_output_type(Target::CREATE_BUNDLE);
-
- BundleData& bundle_data = target_->bundle_data();
- if (!FillBundleDir(SourceDir(), variables::kBundleRootDir,
- &bundle_data.root_dir()))
- return;
- if (!FillBundleDir(bundle_data.root_dir(), variables::kBundleContentsDir,
- &bundle_data.contents_dir()))
- return;
- if (!FillBundleDir(bundle_data.root_dir(), variables::kBundleResourcesDir,
- &bundle_data.resources_dir()))
- return;
- if (!FillBundleDir(bundle_data.root_dir(), variables::kBundleExecutableDir,
- &bundle_data.executable_dir()))
- return;
- if (!FillBundleDir(bundle_data.root_dir(), variables::kBundlePlugInsDir,
- &bundle_data.plugins_dir()))
- return;
-
- if (!FillXcodeExtraAttributes())
- return;
-
- if (!FillProductType())
- return;
-
- if (!FillPartialInfoPlist())
- return;
-
- if (!FillXcodeTestApplicationName())
- return;
-
- if (!FillCodeSigningScript())
- return;
-
- if (!FillCodeSigningSources())
- return;
-
- if (!FillCodeSigningOutputs())
- return;
-
- if (!FillCodeSigningArgs())
- return;
-
- if (!FillBundleDepsFilter())
- return;
-}
-
-bool CreateBundleTargetGenerator::FillBundleDir(
- const SourceDir& bundle_root_dir,
- const base::StringPiece& name,
- SourceDir* bundle_dir) {
- const Value* value = scope_->GetValue(name, true);
- if (!value)
- return true;
- if (!value->VerifyTypeIs(Value::STRING, err_))
- return false;
- std::string str = value->string_value();
- if (!str.empty() && str[str.size() - 1] != '/')
- str.push_back('/');
- if (!EnsureStringIsInOutputDir(GetBuildSettings()->build_dir(), str,
- value->origin(), err_))
- return false;
- if (str != bundle_root_dir.value() &&
- !IsStringInOutputDir(bundle_root_dir, str)) {
- *err_ = Err(value->origin(), "Path is not in bundle root dir.",
- "The given file should be in the bundle root directory or below.\n"
- "Normally you would do \"$bundle_root_dir/foo\". I interpreted this\n"
- "as \"" + str + "\".");
- return false;
- }
- bundle_dir->SwapValue(&str);
- return true;
-}
-
-bool CreateBundleTargetGenerator::FillXcodeExtraAttributes() {
- // Need to get a mutable value to mark all values in the scope as used. This
- // cannot be done on a const Scope.
- Value* value = scope_->GetMutableValue(variables::kXcodeExtraAttributes,
- Scope::SEARCH_CURRENT, true);
- if (!value)
- return true;
-
- if (!value->VerifyTypeIs(Value::SCOPE, err_))
- return false;
-
- Scope* scope_value = value->scope_value();
-
- Scope::KeyValueMap value_map;
- scope_value->GetCurrentScopeValues(&value_map);
- scope_value->MarkAllUsed();
-
- std::map<std::string, std::string> xcode_extra_attributes;
- for (const auto& iter : value_map) {
- if (!iter.second.VerifyTypeIs(Value::STRING, err_))
- return false;
-
- xcode_extra_attributes.insert(
- std::make_pair(iter.first.as_string(), iter.second.string_value()));
- }
-
- target_->bundle_data().xcode_extra_attributes().swap(xcode_extra_attributes);
- return true;
-}
-
-bool CreateBundleTargetGenerator::FillProductType() {
- const Value* value = scope_->GetValue(variables::kProductType, true);
- if (!value)
- return true;
-
- if (!value->VerifyTypeIs(Value::STRING, err_))
- return false;
-
- target_->bundle_data().product_type().assign(value->string_value());
- return true;
-}
-
-bool CreateBundleTargetGenerator::FillPartialInfoPlist() {
- const Value* value = scope_->GetValue(variables::kPartialInfoPlist, true);
- if (!value)
- return true;
-
- if (!value->VerifyTypeIs(Value::STRING, err_))
- return false;
-
- const BuildSettings* build_settings = scope_->settings()->build_settings();
- SourceFile path = scope_->GetSourceDir().ResolveRelativeFile(
- *value, err_, build_settings->root_path_utf8());
-
- if (err_->has_error())
- return false;
-
- if (!EnsureStringIsInOutputDir(build_settings->build_dir(), path.value(),
- value->origin(), err_))
- return false;
-
- target_->bundle_data().set_partial_info_plist(path);
- return true;
-}
-
-bool CreateBundleTargetGenerator::FillXcodeTestApplicationName() {
- const Value* value =
- scope_->GetValue(variables::kXcodeTestApplicationName, true);
- if (!value)
- return true;
-
- if (!value->VerifyTypeIs(Value::STRING, err_))
- return false;
-
- target_->bundle_data().xcode_test_application_name().assign(
- value->string_value());
- return true;
-}
-
-bool CreateBundleTargetGenerator::FillCodeSigningScript() {
- const Value* value = scope_->GetValue(variables::kCodeSigningScript, true);
- if (!value)
- return true;
-
- if (!value->VerifyTypeIs(Value::STRING, err_))
- return false;
-
- SourceFile script_file = scope_->GetSourceDir().ResolveRelativeFile(
- *value, err_, scope_->settings()->build_settings()->root_path_utf8());
- if (err_->has_error())
- return false;
-
- target_->bundle_data().set_code_signing_script(script_file);
- return true;
-}
-
-bool CreateBundleTargetGenerator::FillCodeSigningSources() {
- const Value* value = scope_->GetValue(variables::kCodeSigningSources, true);
- if (!value)
- return true;
-
- if (target_->bundle_data().code_signing_script().is_null()) {
- *err_ = Err(
- function_call_,
- "No code signing script."
- "You must define code_signing_script if you use code_signing_sources.");
- return false;
- }
-
- Target::FileList script_sources;
- if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
- scope_->GetSourceDir(), &script_sources,
- err_))
- return false;
-
- target_->bundle_data().code_signing_sources().swap(script_sources);
- return true;
-}
-
-bool CreateBundleTargetGenerator::FillCodeSigningOutputs() {
- const Value* value = scope_->GetValue(variables::kCodeSigningOutputs, true);
- if (!value)
- return true;
-
- if (target_->bundle_data().code_signing_script().is_null()) {
- *err_ = Err(
- function_call_,
- "No code signing script."
- "You must define code_signing_script if you use code_signing_outputs.");
- return false;
- }
-
- if (!value->VerifyTypeIs(Value::LIST, err_))
- return false;
-
- SubstitutionList& outputs = target_->bundle_data().code_signing_outputs();
- if (!outputs.Parse(*value, err_))
- return false;
-
- if (outputs.list().empty()) {
- *err_ =
- Err(function_call_,
- "Code signing script has no output."
- "If you have no outputs, the build system can not tell when your\n"
- "code signing script needs to be run.");
- return false;
- }
-
- // Validate that outputs are in the output dir.
- CHECK_EQ(value->list_value().size(), outputs.list().size());
- for (size_t i = 0; i < value->list_value().size(); ++i) {
- if (!EnsureSubstitutionIsInOutputDir(outputs.list()[i],
- value->list_value()[i]))
- return false;
- }
-
- return true;
-}
-
-bool CreateBundleTargetGenerator::FillCodeSigningArgs() {
- const Value* value = scope_->GetValue(variables::kCodeSigningArgs, true);
- if (!value)
- return true;
-
- if (target_->bundle_data().code_signing_script().is_null()) {
- *err_ = Err(
- function_call_,
- "No code signing script."
- "You must define code_signing_script if you use code_signing_args.");
- return false;
- }
-
- if (!value->VerifyTypeIs(Value::LIST, err_))
- return false;
-
- return target_->bundle_data().code_signing_args().Parse(*value, err_);
-}
-
-bool CreateBundleTargetGenerator::FillBundleDepsFilter() {
- const Value* value = scope_->GetValue(variables::kBundleDepsFilter, true);
- if (!value)
- return true;
-
- if (!value->VerifyTypeIs(Value::LIST, err_))
- return false;
-
- const SourceDir& current_dir = scope_->GetSourceDir();
- std::vector<LabelPattern>& bundle_deps_filter =
- target_->bundle_data().bundle_deps_filter();
- for (const auto& item : value->list_value()) {
- bundle_deps_filter.push_back(
- LabelPattern::GetPattern(current_dir, item, err_));
- if (err_->has_error())
- return false;
- }
-
- return true;
-}
diff --git a/chromium/tools/gn/create_bundle_target_generator.h b/chromium/tools/gn/create_bundle_target_generator.h
deleted file mode 100644
index a7f1edca148..00000000000
--- a/chromium/tools/gn/create_bundle_target_generator.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_CREATE_BUNDLE_TARGET_GENERATOR_H_
-#define TOOLS_GN_CREATE_BUNDLE_TARGET_GENERATOR_H_
-
-#include "base/macros.h"
-#include "tools/gn/target_generator.h"
-
-class SourceDir;
-
-// Populates a Target with the values from a create_bundle rule.
-class CreateBundleTargetGenerator : public TargetGenerator {
- public:
- CreateBundleTargetGenerator(Target* target,
- Scope* scope,
- const FunctionCallNode* function_call,
- Err* err);
- ~CreateBundleTargetGenerator() override;
-
- protected:
- void DoRun() override;
-
- private:
- bool FillBundleDir(const SourceDir& bundle_root_dir,
- const base::StringPiece& name,
- SourceDir* bundle_dir);
-
- bool FillXcodeExtraAttributes();
-
- bool FillProductType();
- bool FillPartialInfoPlist();
- bool FillXcodeTestApplicationName();
-
- bool FillCodeSigningScript();
- bool FillCodeSigningSources();
- bool FillCodeSigningOutputs();
- bool FillCodeSigningArgs();
- bool FillBundleDepsFilter();
-
- DISALLOW_COPY_AND_ASSIGN(CreateBundleTargetGenerator);
-};
-
-#endif // TOOLS_GN_CREATE_BUNDLE_TARGET_GENERATOR_H_
diff --git a/chromium/tools/gn/deps_iterator.cc b/chromium/tools/gn/deps_iterator.cc
deleted file mode 100644
index 92e892e236f..00000000000
--- a/chromium/tools/gn/deps_iterator.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/deps_iterator.h"
-
-#include "tools/gn/target.h"
-
-DepsIterator::DepsIterator() : current_index_(0) {
- vect_stack_[0] = nullptr;
- vect_stack_[1] = nullptr;
- vect_stack_[2] = nullptr;
-}
-
-DepsIterator::DepsIterator(const LabelTargetVector* a,
- const LabelTargetVector* b,
- const LabelTargetVector* c)
- : current_index_(0) {
- vect_stack_[0] = a;
- vect_stack_[1] = b;
- vect_stack_[2] = c;
-
- if (vect_stack_[0] && vect_stack_[0]->empty())
- operator++();
-}
-
-// Advance to the next position. This assumes there are more vectors.
-//
-// For internal use, this function tolerates an initial index equal to the
-// length of the current vector. In this case, it will advance to the next
-// one.
-DepsIterator& DepsIterator::operator++() {
- DCHECK(vect_stack_[0]);
-
- current_index_++;
- if (current_index_ >= vect_stack_[0]->size()) {
- // Advance to next vect. Shift the elements left by one.
- vect_stack_[0] = vect_stack_[1];
- vect_stack_[1] = vect_stack_[2];
- vect_stack_[2] = nullptr;
-
- current_index_ = 0;
-
- if (vect_stack_[0] && vect_stack_[0]->empty())
- operator++();
- }
- return *this;
-}
-
-DepsIteratorRange::DepsIteratorRange(const DepsIterator& b)
- : begin_(b),
- end_() {
-}
-
-DepsIteratorRange::~DepsIteratorRange() = default;
diff --git a/chromium/tools/gn/deps_iterator.h b/chromium/tools/gn/deps_iterator.h
deleted file mode 100644
index c3f2c42c7dc..00000000000
--- a/chromium/tools/gn/deps_iterator.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_DEPS_ITERATOR_H_
-#define TOOLS_GN_DEPS_ITERATOR_H_
-
-#include <stddef.h>
-
-#include "tools/gn/label_ptr.h"
-
-// Provides an iterator for iterating over multiple LabelTargetVectors to
-// make it convenient to iterate over all deps of a target.
-//
-// This works by maintaining a simple stack of vectors (since we have a fixed
-// number of deps types). When the stack is empty, we've reached the end. This
-// means that the default-constructed iterator == end() for any sequence.
-class DepsIterator {
- public:
- // Creates an empty iterator.
- DepsIterator();
-
- // Iterate over the deps in the given vectors. If passing less than three,
- // pad with nulls.
- DepsIterator(const LabelTargetVector* a,
- const LabelTargetVector* b,
- const LabelTargetVector* c);
-
- // Prefix increment operator. This assumes there are more items (i.e.
- // *this != DepsIterator()).
- //
- // For internal use, this function tolerates an initial index equal to the
- // length of the current vector. In this case, it will advance to the next
- // one.
- DepsIterator& operator++();
-
- // Comparison for STL-based loops.
- bool operator!=(const DepsIterator& other) const {
- return current_index_ != other.current_index_ ||
- vect_stack_[0] != other.vect_stack_[0] ||
- vect_stack_[1] != other.vect_stack_[1] ||
- vect_stack_[2] != other.vect_stack_[2];
- }
-
- // Dereference operator for STL-compatible iterators.
- const LabelTargetPair& operator*() const {
- DCHECK_LT(current_index_, vect_stack_[0]->size());
- return (*vect_stack_[0])[current_index_];
- }
-
- private:
- const LabelTargetVector* vect_stack_[3];
-
- size_t current_index_;
-};
-
-// Provides a virtual container implementing begin() and end() for a
-// sequence of deps. This can then be used in range-based for loops.
-class DepsIteratorRange {
- public:
- explicit DepsIteratorRange(const DepsIterator& b);
- ~DepsIteratorRange();
-
- const DepsIterator& begin() const { return begin_; }
- const DepsIterator& end() const { return end_; }
-
- private:
- DepsIterator begin_;
- DepsIterator end_;
-};
-
-#endif // TOOLS_GN_DEPS_ITERATOR_H_
diff --git a/chromium/tools/gn/desc_builder.cc b/chromium/tools/gn/desc_builder.cc
deleted file mode 100644
index b2fd7162bd3..00000000000
--- a/chromium/tools/gn/desc_builder.cc
+++ /dev/null
@@ -1,729 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <memory>
-#include <set>
-
-#include "base/strings/string_number_conversions.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/config.h"
-#include "tools/gn/config_values_extractors.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/desc_builder.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/runtime_deps.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/variables.h"
-
-// Example structure of Value for single target
-// (not applicable or empty fields will be ommitted depending on target type)
-//
-// target_properties = {
-// "type" : "output_type", // matching Target::GetStringForOutputType
-// "toolchain" : "toolchain_name",
-// "visibility" : [ list of visibility pattern descriptions ],
-// "test_only" : true or false,
-// "check_includes": true or false,
-// "allow_circular_includes_from": [ list of target names ],
-// "sources" : [ list of source files ],
-// "public" : either "*" or [ list of public headers],
-// "inputs" : [ list of inputs for target ],
-// "configs" : [ list of configs for this target ],
-// "public_configs" : [ list of public configs for this taget],
-// "all_dependent_configs", [ list of all dependent configs for this target],
-// "script" : "script for action targets",
-// "args" : [ argument list for action targets ],
-// "depfile : "file name for action input dependencies",
-// "outputs" : [ list of target outputs ],
-// "arflags", "asmflags", "cflags", "cflags_c",
-// "clfags_cc", "cflags_objc", "clfags_objcc" : [ list of flags],
-// "defines" : [ list of preprocessor definitions ],
-// "include_dirs" : [ list of include directories ],
-// "precompiled_header" : "name of precompiled header file",
-// "precompiled_source" : "path to precompiled source",
-// "deps : [ list of target dependencies ],
-// "libs" : [ list of libraries ],
-// "lib_dirs" : [ list of library directories ]
-// }
-//
-// Optionally, if "what" is specified while generating description, two other
-// properties can be requested that are not included by default
-//
-// "runtime_deps" : [list of computed runtime dependencies]
-// "source_outputs" : {
-// "source_file x" : [ list of outputs for source file x ]
-// "source_file y" : [ list of outputs for source file y ]
-// ...
-// }
-
-namespace {
-
-std::string FormatSourceDir(const SourceDir& dir) {
-#if defined(OS_WIN)
- // On Windows we fix up system absolute paths to look like native ones.
- // Internally, they'll look like "/C:\foo\bar/"
- if (dir.is_system_absolute()) {
- std::string buf = dir.value();
- if (buf.size() > 3 && buf[2] == ':') {
- buf.erase(buf.begin()); // Erase beginning slash.
- return buf;
- }
- }
-#endif
- return dir.value();
-}
-
-void RecursiveCollectChildDeps(const Target* target,
- std::set<const Target*>* result);
-
-void RecursiveCollectDeps(const Target* target,
- std::set<const Target*>* result) {
- if (result->find(target) != result->end())
- return; // Already did this target.
- result->insert(target);
-
- RecursiveCollectChildDeps(target, result);
-}
-
-void RecursiveCollectChildDeps(const Target* target,
- std::set<const Target*>* result) {
- for (const auto& pair : target->GetDeps(Target::DEPS_ALL))
- RecursiveCollectDeps(pair.ptr, result);
-}
-
-// Common functionality for target and config description builder
-class BaseDescBuilder {
- public:
- typedef std::unique_ptr<base::Value> ValuePtr;
-
- BaseDescBuilder(const std::set<std::string>& what,
- bool all,
- bool tree,
- bool blame)
- : what_(what), all_(all), tree_(tree), blame_(blame) {}
-
- protected:
- virtual Label GetToolchainLabel() const = 0;
-
- bool what(const std::string& w) const {
- return what_.empty() || what_.find(w) != what_.end();
- }
-
- template <typename T>
- ValuePtr RenderValue(const std::vector<T>& vector) {
- auto res = std::make_unique<base::ListValue>();
- for (const auto& v : vector)
- res->Append(RenderValue(v));
-
- return std::move(res);
- }
-
- ValuePtr RenderValue(const std::string& s, bool optional = false) {
- return (s.empty() && optional) ? std::make_unique<base::Value>()
- : ValuePtr(new base::Value(s));
- }
-
- ValuePtr RenderValue(const SourceDir& d) {
- return d.is_null() ? std::make_unique<base::Value>()
- : ValuePtr(new base::Value(FormatSourceDir(d)));
- }
-
- ValuePtr RenderValue(const SourceFile& f) {
- return f.is_null() ? std::make_unique<base::Value>()
- : ValuePtr(new base::Value(f.value()));
- }
-
- ValuePtr RenderValue(const SourceFile* f) { return RenderValue(*f); }
-
- ValuePtr RenderValue(const LibFile& lib) {
- if (lib.is_source_file())
- return RenderValue(lib.source_file());
- return RenderValue(lib.value());
- }
-
- template <class VectorType>
- void FillInConfigVector(base::ListValue* out,
- const VectorType& configs,
- int indent = 0) {
- for (const auto& config : configs) {
- std::string name(indent * 2, ' ');
- name.append(config.label.GetUserVisibleName(GetToolchainLabel()));
- out->AppendString(name);
- if (tree_)
- FillInConfigVector(out, config.ptr->configs(), indent + 1);
- }
- }
-
- void FillInPrecompiledHeader(base::DictionaryValue* out,
- const ConfigValues& values) {
- if (what(variables::kPrecompiledHeader) &&
- !values.precompiled_header().empty()) {
- out->SetWithoutPathExpansion(
- variables::kPrecompiledHeader,
- RenderValue(values.precompiled_header(), true));
- }
- if (what(variables::kPrecompiledSource) &&
- !values.precompiled_source().is_null()) {
- out->SetWithoutPathExpansion(variables::kPrecompiledSource,
- RenderValue(values.precompiled_source()));
- }
- }
-
- std::set<std::string> what_;
- bool all_;
- bool tree_;
- bool blame_;
-};
-
-class ConfigDescBuilder : public BaseDescBuilder {
- public:
- ConfigDescBuilder(const Config* config, const std::set<std::string>& what)
- : BaseDescBuilder(what, false, false, false), config_(config) {}
-
- std::unique_ptr<base::DictionaryValue> BuildDescription() {
- auto res = std::make_unique<base::DictionaryValue>();
- const ConfigValues& values = config_->resolved_values();
-
- if (what_.empty())
- res->SetKey(
- "toolchain",
- base::Value(
- config_->label().GetToolchainLabel().GetUserVisibleName(false)));
-
- if (what(variables::kConfigs) && !config_->configs().empty()) {
- auto configs = std::make_unique<base::ListValue>();
- FillInConfigVector(configs.get(), config_->configs().vector());
- res->SetWithoutPathExpansion(variables::kConfigs, std::move(configs));
- }
-
-#define CONFIG_VALUE_ARRAY_HANDLER(name, type) \
- if (what(#name)) { \
- ValuePtr ptr = \
- render_config_value_array<type>(values, &ConfigValues::name); \
- if (ptr) { \
- res->SetWithoutPathExpansion(#name, std::move(ptr)); \
- } \
- }
- CONFIG_VALUE_ARRAY_HANDLER(arflags, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(asmflags, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(cflags, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(cflags_c, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(cflags_cc, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(cflags_objc, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(cflags_objcc, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(defines, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(include_dirs, SourceDir)
- CONFIG_VALUE_ARRAY_HANDLER(inputs, SourceFile)
- CONFIG_VALUE_ARRAY_HANDLER(ldflags, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(lib_dirs, SourceDir)
- CONFIG_VALUE_ARRAY_HANDLER(libs, LibFile)
-
-#undef CONFIG_VALUE_ARRAY_HANDLER
-
- FillInPrecompiledHeader(res.get(), values);
-
- return res;
- }
-
- protected:
- Label GetToolchainLabel() const override {
- return config_->label().GetToolchainLabel();
- }
-
- private:
- template <typename T>
- ValuePtr render_config_value_array(
- const ConfigValues& values,
- const std::vector<T>& (ConfigValues::*getter)() const) {
- auto res = std::make_unique<base::ListValue>();
-
- for (const T& cur : (values.*getter)())
- res->Append(RenderValue(cur));
-
- return res->empty() ? nullptr : std::move(res);
- }
-
- const Config* config_;
-};
-
-class TargetDescBuilder : public BaseDescBuilder {
- public:
- TargetDescBuilder(const Target* target,
- const std::set<std::string>& what,
- bool all,
- bool tree,
- bool blame)
- : BaseDescBuilder(what, all, tree, blame), target_(target) {}
-
- std::unique_ptr<base::DictionaryValue> BuildDescription() {
- auto res = std::make_unique<base::DictionaryValue>();
- bool is_binary_output = target_->IsBinary();
-
- if (what_.empty()) {
- res->SetKey(
- "type",
- base::Value(Target::GetStringForOutputType(target_->output_type())));
- res->SetKey(
- "toolchain",
- base::Value(
- target_->label().GetToolchainLabel().GetUserVisibleName(false)));
- }
-
- // General target meta variables.
- if (what(variables::kVisibility))
- res->SetWithoutPathExpansion(variables::kVisibility,
- target_->visibility().AsValue());
-
- if (what(variables::kTestonly))
- res->SetKey(variables::kTestonly, base::Value(target_->testonly()));
-
- if (is_binary_output) {
- if (what(variables::kCheckIncludes))
- res->SetKey(variables::kCheckIncludes,
- base::Value(target_->check_includes()));
-
- if (what(variables::kAllowCircularIncludesFrom)) {
- auto labels = std::make_unique<base::ListValue>();
- for (const auto& cur : target_->allow_circular_includes_from())
- labels->AppendString(cur.GetUserVisibleName(GetToolchainLabel()));
-
- res->SetWithoutPathExpansion(variables::kAllowCircularIncludesFrom,
- std::move(labels));
- }
- }
-
- if (what(variables::kSources) && !target_->sources().empty())
- res->SetWithoutPathExpansion(variables::kSources,
- RenderValue(target_->sources()));
-
- if (what(variables::kOutputName) && !target_->output_name().empty())
- res->SetKey(variables::kOutputName, base::Value(target_->output_name()));
-
- if (what(variables::kOutputDir) && !target_->output_dir().is_null())
- res->SetWithoutPathExpansion(variables::kOutputDir,
- RenderValue(target_->output_dir()));
-
- if (what(variables::kOutputExtension) && target_->output_extension_set())
- res->SetKey(variables::kOutputExtension,
- base::Value(target_->output_extension()));
-
- if (what(variables::kPublic)) {
- if (target_->all_headers_public())
- res->SetKey(variables::kPublic, base::Value("*"));
- else
- res->SetWithoutPathExpansion(variables::kPublic,
- RenderValue(target_->public_headers()));
- }
-
- if (what(variables::kInputs)) {
- std::vector<const SourceFile*> inputs;
- for (ConfigValuesIterator iter(target_); !iter.done(); iter.Next()) {
- for (const auto& input : iter.cur().inputs())
- inputs.push_back(&input);
- }
- if (!inputs.empty())
- res->SetWithoutPathExpansion(variables::kInputs, RenderValue(inputs));
- }
-
- if (is_binary_output && what(variables::kConfigs) &&
- !target_->configs().empty()) {
- auto configs = std::make_unique<base::ListValue>();
- FillInConfigVector(configs.get(), target_->configs().vector());
- res->SetWithoutPathExpansion(variables::kConfigs, std::move(configs));
- }
-
- if (what(variables::kPublicConfigs) && !target_->public_configs().empty()) {
- auto configs = std::make_unique<base::ListValue>();
- FillInConfigVector(configs.get(), target_->public_configs());
- res->SetWithoutPathExpansion(variables::kPublicConfigs,
- std::move(configs));
- }
-
- if (what(variables::kAllDependentConfigs) &&
- !target_->all_dependent_configs().empty()) {
- auto configs = std::make_unique<base::ListValue>();
- FillInConfigVector(configs.get(), target_->all_dependent_configs());
- res->SetWithoutPathExpansion(variables::kAllDependentConfigs,
- std::move(configs));
- }
-
- // Action
- if (target_->output_type() == Target::ACTION ||
- target_->output_type() == Target::ACTION_FOREACH) {
- if (what(variables::kScript))
- res->SetKey(variables::kScript,
- base::Value(target_->action_values().script().value()));
-
- if (what(variables::kArgs)) {
- auto args = std::make_unique<base::ListValue>();
- for (const auto& elem : target_->action_values().args().list())
- args->AppendString(elem.AsString());
-
- res->SetWithoutPathExpansion(variables::kArgs, std::move(args));
- }
- if (what(variables::kDepfile) &&
- !target_->action_values().depfile().empty()) {
- res->SetKey(variables::kDepfile,
- base::Value(target_->action_values().depfile().AsString()));
- }
- }
-
- if (target_->output_type() != Target::SOURCE_SET &&
- target_->output_type() != Target::GROUP &&
- target_->output_type() != Target::BUNDLE_DATA) {
- if (what(variables::kOutputs))
- FillInOutputs(res.get());
- }
-
- // Source outputs are only included when specifically asked for it
- if (what_.find("source_outputs") != what_.end())
- FillInSourceOutputs(res.get());
-
- if (target_->output_type() == Target::CREATE_BUNDLE && what("bundle_data"))
- FillInBundle(res.get());
-
- if (is_binary_output) {
-#define CONFIG_VALUE_ARRAY_HANDLER(name, type) \
- if (what(#name)) { \
- ValuePtr ptr = RenderConfigValues<type>(&ConfigValues::name); \
- if (ptr) { \
- res->SetWithoutPathExpansion(#name, std::move(ptr)); \
- } \
- }
- CONFIG_VALUE_ARRAY_HANDLER(arflags, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(asmflags, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(cflags, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(cflags_c, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(cflags_cc, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(cflags_objc, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(cflags_objcc, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(defines, std::string)
- CONFIG_VALUE_ARRAY_HANDLER(include_dirs, SourceDir)
- CONFIG_VALUE_ARRAY_HANDLER(inputs, SourceFile)
- CONFIG_VALUE_ARRAY_HANDLER(ldflags, std::string)
-#undef CONFIG_VALUE_ARRAY_HANDLER
-
- // Libs and lib_dirs are handled specially below.
-
- FillInPrecompiledHeader(res.get(), target_->config_values());
- }
-
- if (what(variables::kDeps))
- res->SetWithoutPathExpansion(variables::kDeps, RenderDeps());
-
- // Runtime deps are special, print only when explicitly asked for and not in
- // overview mode.
- if (what_.find("runtime_deps") != what_.end())
- res->SetWithoutPathExpansion("runtime_deps", RenderRuntimeDeps());
-
- // libs and lib_dirs are special in that they're inherited. We don't
- // currently
- // implement a blame feature for this since the bottom-up inheritance makes
- // this difficult.
-
- // Libs can be part of any target and get recursively pushed up the chain,
- // so display them regardless of target type.
- if (what(variables::kLibs)) {
- const OrderedSet<LibFile>& all_libs = target_->all_libs();
- if (!all_libs.empty()) {
- auto libs = std::make_unique<base::ListValue>();
- for (size_t i = 0; i < all_libs.size(); i++)
- libs->AppendString(all_libs[i].value());
- res->SetWithoutPathExpansion(variables::kLibs, std::move(libs));
- }
- }
-
- if (what(variables::kLibDirs)) {
- const OrderedSet<SourceDir>& all_lib_dirs = target_->all_lib_dirs();
- if (!all_lib_dirs.empty()) {
- auto lib_dirs = std::make_unique<base::ListValue>();
- for (size_t i = 0; i < all_lib_dirs.size(); i++)
- lib_dirs->AppendString(FormatSourceDir(all_lib_dirs[i]));
- res->SetWithoutPathExpansion(variables::kLibDirs, std::move(lib_dirs));
- }
- }
-
- return res;
- }
-
- private:
- // Prints dependencies of the given target (not the target itself). If the
- // set is non-null, new targets encountered will be added to the set, and if
- // a dependency is in the set already, it will not be recused into. When the
- // set is null, all dependencies will be printed.
- void RecursivePrintDeps(base::ListValue* out,
- const Target* target,
- std::set<const Target*>* seen_targets,
- int indent_level) {
- // Combine all deps into one sorted list.
- std::vector<LabelTargetPair> sorted_deps;
- for (const auto& pair : target->GetDeps(Target::DEPS_ALL))
- sorted_deps.push_back(pair);
- std::sort(sorted_deps.begin(), sorted_deps.end(),
- LabelPtrLabelLess<Target>());
-
- std::string indent(indent_level * 2, ' ');
-
- for (const auto& pair : sorted_deps) {
- const Target* cur_dep = pair.ptr;
- std::string str =
- indent + cur_dep->label().GetUserVisibleName(GetToolchainLabel());
-
- bool print_children = true;
- if (seen_targets) {
- if (seen_targets->find(cur_dep) == seen_targets->end()) {
- // New target, mark it visited.
- seen_targets->insert(cur_dep);
- } else {
- // Already seen.
- print_children = false;
- // Only print "..." if something is actually elided, which means that
- // the current target has children.
- if (!cur_dep->public_deps().empty() ||
- !cur_dep->private_deps().empty() || !cur_dep->data_deps().empty())
- str += "...";
- }
- }
-
- out->AppendString(str);
-
- if (print_children)
- RecursivePrintDeps(out, cur_dep, seen_targets, indent_level + 1);
- }
- }
-
- ValuePtr RenderDeps() {
- auto res = std::make_unique<base::ListValue>();
-
- // Tree mode is separate.
- if (tree_) {
- if (all_) {
- // Show all tree deps with no eliding.
- RecursivePrintDeps(res.get(), target_, nullptr, 0);
- } else {
- // Don't recurse into duplicates.
- std::set<const Target*> seen_targets;
- RecursivePrintDeps(res.get(), target_, &seen_targets, 0);
- }
- } else { // not tree
-
- // Collect the deps to display.
- if (all_) {
- // Show all dependencies.
- std::set<const Target*> all_deps;
- RecursiveCollectChildDeps(target_, &all_deps);
- commands::FilterAndPrintTargetSet(all_deps, res.get());
- } else {
- // Show direct dependencies only.
- std::vector<const Target*> deps;
- for (const auto& pair : target_->GetDeps(Target::DEPS_ALL))
- deps.push_back(pair.ptr);
- std::sort(deps.begin(), deps.end());
- commands::FilterAndPrintTargets(&deps, res.get());
- }
- }
-
- return std::move(res);
- }
-
- ValuePtr RenderRuntimeDeps() {
- auto res = std::make_unique<base::ListValue>();
-
- const Target* previous_from = NULL;
- for (const auto& pair : ComputeRuntimeDeps(target_)) {
- std::string str;
- if (blame_) {
- // Generally a target's runtime deps will be listed sequentially, so
- // group them and don't duplicate the "from" label for two in a row.
- if (previous_from == pair.second) {
- str = " ";
- } else {
- previous_from = pair.second;
- res->AppendString(
- str + "From " +
- pair.second->label().GetUserVisibleName(GetToolchainLabel()));
- str = " ";
- }
- }
-
- res->AppendString(str + pair.first.value());
- }
-
- return std::move(res);
- }
-
- void FillInSourceOutputs(base::DictionaryValue* res) {
- auto dict = std::make_unique<base::DictionaryValue>();
- for (const auto& source : target_->sources()) {
- std::vector<OutputFile> outputs;
- Toolchain::ToolType tool_type = Toolchain::TYPE_NONE;
- if (target_->GetOutputFilesForSource(source, &tool_type, &outputs)) {
- auto list = std::make_unique<base::ListValue>();
- for (const auto& output : outputs)
- list->AppendString(output.value());
-
- dict->SetWithoutPathExpansion(source.value(), std::move(list));
- }
- }
- res->SetWithoutPathExpansion("source_outputs", std::move(dict));
- }
-
- void FillInBundle(base::DictionaryValue* res) {
- auto data = std::make_unique<base::DictionaryValue>();
- const BundleData& bundle_data = target_->bundle_data();
- const Settings* settings = target_->settings();
- BundleData::SourceFiles sources;
- bundle_data.GetSourceFiles(&sources);
- data->SetWithoutPathExpansion("source_files", RenderValue(sources));
- data->SetKey(
- "root_dir_output",
- base::Value(bundle_data.GetBundleRootDirOutput(settings).value()));
- data->SetWithoutPathExpansion("root_dir",
- RenderValue(bundle_data.root_dir()));
- data->SetWithoutPathExpansion("resources_dir",
- RenderValue(bundle_data.resources_dir()));
- data->SetWithoutPathExpansion("executable_dir",
- RenderValue(bundle_data.executable_dir()));
- data->SetWithoutPathExpansion("plugins_dir",
- RenderValue(bundle_data.plugins_dir()));
- data->SetKey("product_type", base::Value(bundle_data.product_type()));
- data->SetWithoutPathExpansion(
- "partial_info_plist", RenderValue(bundle_data.partial_info_plist()));
-
- auto deps = std::make_unique<base::ListValue>();
- for (const auto* dep : bundle_data.bundle_deps())
- deps->AppendString(dep->label().GetUserVisibleName(GetToolchainLabel()));
-
- data->SetWithoutPathExpansion("deps", std::move(deps));
- res->SetWithoutPathExpansion("bundle_data", std::move(data));
- }
-
- void FillInOutputs(base::DictionaryValue* res) {
- if (target_->output_type() == Target::ACTION) {
- auto list = std::make_unique<base::ListValue>();
- for (const auto& elem : target_->action_values().outputs().list())
- list->AppendString(elem.AsString());
-
- res->SetWithoutPathExpansion(variables::kOutputs, std::move(list));
- } else if (target_->output_type() == Target::CREATE_BUNDLE) {
- std::vector<SourceFile> output_files;
- target_->bundle_data().GetOutputsAsSourceFiles(target_->settings(),
- &output_files);
- res->SetWithoutPathExpansion(variables::kOutputs,
- RenderValue(output_files));
- } else if (target_->output_type() == Target::ACTION_FOREACH ||
- target_->output_type() == Target::COPY_FILES) {
- const SubstitutionList& outputs = target_->action_values().outputs();
- if (!outputs.required_types().empty()) {
- auto patterns = std::make_unique<base::ListValue>();
- for (const auto& elem : outputs.list())
- patterns->AppendString(elem.AsString());
-
- res->SetWithoutPathExpansion("output_patterns", std::move(patterns));
- }
- std::vector<SourceFile> output_files;
- SubstitutionWriter::ApplyListToSources(target_, target_->settings(),
- outputs, target_->sources(),
- &output_files);
- res->SetWithoutPathExpansion(variables::kOutputs,
- RenderValue(output_files));
- } else {
- DCHECK(target_->IsBinary());
- const Tool* tool =
- target_->toolchain()->GetToolForTargetFinalOutput(target_);
-
- std::vector<OutputFile> output_files;
- SubstitutionWriter::ApplyListToLinkerAsOutputFile(
- target_, tool, tool->outputs(), &output_files);
- std::vector<SourceFile> output_files_as_source_file;
- for (const OutputFile& output_file : output_files)
- output_files_as_source_file.push_back(
- output_file.AsSourceFile(target_->settings()->build_settings()));
-
- res->SetWithoutPathExpansion(variables::kOutputs,
- RenderValue(output_files_as_source_file));
- }
- }
-
- // Writes a given config value type to the string, optionally with
- // attribution.
- // This should match RecursiveTargetConfigToStream in the order it traverses.
- template <class T>
- ValuePtr RenderConfigValues(const std::vector<T>& (ConfigValues::*getter)()
- const) {
- auto res = std::make_unique<base::ListValue>();
- for (ConfigValuesIterator iter(target_); !iter.done(); iter.Next()) {
- const std::vector<T>& vec = (iter.cur().*getter)();
-
- if (vec.empty())
- continue;
-
- if (blame_) {
- const Config* config = iter.GetCurrentConfig();
- if (config) {
- // Source of this value is a config.
- std::string from =
- "From " + config->label().GetUserVisibleName(false);
- res->AppendString(from);
- if (iter.origin()) {
- Location location = iter.origin()->GetRange().begin();
- from = " (Added by " + location.file()->name().value() + ":" +
- base::IntToString(location.line_number()) + ")";
- res->AppendString(from);
- }
- } else {
- // Source of this value is the target itself.
- std::string from =
- "From " + target_->label().GetUserVisibleName(false);
- res->AppendString(from);
- }
- }
-
- for (const T& val : vec) {
- ValuePtr rendered = RenderValue(val);
- std::string str;
- // Indent string values in blame mode
- if (blame_ && rendered->GetAsString(&str)) {
- str = " " + str;
- rendered = std::make_unique<base::Value>(str);
- }
- res->Append(std::move(rendered));
- }
- }
- return res->empty() ? nullptr : std::move(res);
- }
-
- Label GetToolchainLabel() const override {
- return target_->label().GetToolchainLabel();
- }
-
- const Target* target_;
-};
-
-} // namespace
-
-std::unique_ptr<base::DictionaryValue> DescBuilder::DescriptionForTarget(
- const Target* target,
- const std::string& what,
- bool all,
- bool tree,
- bool blame) {
- std::set<std::string> w;
- if (!what.empty())
- w.insert(what);
- TargetDescBuilder b(target, w, all, tree, blame);
- return b.BuildDescription();
-}
-
-std::unique_ptr<base::DictionaryValue> DescBuilder::DescriptionForConfig(
- const Config* config,
- const std::string& what) {
- std::set<std::string> w;
- if (!what.empty())
- w.insert(what);
- ConfigDescBuilder b(config, w);
- return b.BuildDescription();
-}
diff --git a/chromium/tools/gn/desc_builder.h b/chromium/tools/gn/desc_builder.h
deleted file mode 100644
index 1f0c395923f..00000000000
--- a/chromium/tools/gn/desc_builder.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_DESC_BUILDER_H_
-#define TOOLS_GN_DESC_BUILDER_H_
-
-#include "base/values.h"
-#include "tools/gn/target.h"
-
-class DescBuilder {
- public:
- // Creates Dictionary representation for given target
- static std::unique_ptr<base::DictionaryValue> DescriptionForTarget(
- const Target* target,
- const std::string& what,
- bool all,
- bool tree,
- bool blame);
-
- // Creates Dictionary representation for given config
- static std::unique_ptr<base::DictionaryValue> DescriptionForConfig(
- const Config* config,
- const std::string& what);
-};
-
-#endif
diff --git a/chromium/tools/gn/docs/cross_compiles.md b/chromium/tools/gn/docs/cross_compiles.md
deleted file mode 100644
index 6da66543102..00000000000
--- a/chromium/tools/gn/docs/cross_compiles.md
+++ /dev/null
@@ -1,125 +0,0 @@
-# How GN handles cross-compiling
-
-## As a GN user
-
-GN has robust support for doing cross compiles and building things for
-multiple architectures in a single build (e.g., to build some things to
-run locally and some things to run on an embedded device). In fact,
-there is no limit on the number of different architectures you can build
-at once; the Chromium build uses at least four in some configurations.
-
-To start, GN has the concepts of a _host_ and a _target_. The host is
-the platform that the build is run on, and the target is the platform
-where the code will actually run (This is different from
-[autotools](http://www.gnu.org/software/automake/manual/html_node/Cross_002dCompilation.html)'
-terminology, but uses the more common terminology for cross
-compiling**).**
-
-(Confusingly, GN also refers to each build artifact -- an executable,
-library, etc. -- as a target. On this page, we will use "target" only to
-refer to the system you want to run your code on, and use "rule" or some
-other synonym to refer to a specific build artifact).
-
-When GN starts up, the `host_os` and `host_cpu` variables are set
-automatically to match the operating system (they can be overridden in
-args files, which can be useful in weird corner cases). The user can
-specify that they want to do a cross-compile by setting either or both
-of `target_os` and `target_cpu`; if they are not set, the build config
-files will usually set them to the host's values, though the Chromium
-build will set target\_cpu to "arm" if target\_os is set to "android").
-
-So, for example, running on an x64 Linux machine:
-
-```
-gn gen out/Default
-```
-
-is equivalent to:
-
-```
-gn gen out/Default --args='target_os="linux" target_cpu="x64"'
-```
-
-To do an 32-bit ARM Android cross-compile, do:
-
-```
-gn gen out/Default --args='target_os="android"'
-```
-
-(We don't have to specify target\_cpu because of the conditionals
-mentioned above).
-
-And, to do a 64-bit MIPS Chrome OS cross-compile:
-
-```
-gn gen out/Default --args='target_os="chromeos" target_cpu="mips64el"'
-```
-
-## As a BUILD.gn author
-
-If you are editing build files outside of the //build directory (i.e.,
-not directly working on toolchains, compiler configs, etc.), generally
-you only need to worry about a few things:
-
-The `current_toolchain`, `current_cpu`, and `current_os` variables
-reflect the settings that are **currently** in effect in a given rule.
-The `is_linux`, `is_win` etc. variables are updated to reflect the
-current settings, and changes to `cflags`, `ldflags` and so forth also
-only apply to the current toolchain and the current thing being built.
-
-You can also refer to the `target_cpu` and `target_os` variables. This
-is useful if you need to do something different on the host depending on
-which target\_arch is requested; the values are constant across all
-toolchains. You can do similar things for the `host_cpu` and `host_os`
-variables, but should generally never need to.
-
-For the default toolchain, `target_cpu` and `current_cpu` are the same. For a
-secondary toolchain, `current_cpu` is set based on the toolchain definition
-and `target_cpu` remains the same. When writing rules, **`current_cpu` should
-be used rather than `target_cpu` most of the time**.
-
-By default, dependencies listed in the `deps` variable of a rule use the
-same (currently active) toolchain. You may specify a different toolchain
-using the `foo(bar)` label notation as described in [the label section
-of the reference doc](reference.md#Toolchains).
-
-Here's an example of when to use `target_cpu` vs `current_cpu`:
-
-```
-declare_args() {
- # Applies only to toolchains targeting target_cpu.
- sysroot = ""
-}
-
-config("my_config") {
- # Uses current_cpu because compile flags are toolchain-dependent.
- if (current_cpu == "arm") {
- defines = [ "CPU_IS_32_BIT" ]
- } else {
- defines = [ "CPU_IS_64_BIT" ]
- }
- # Compares current_cpu with target_cpu to see whether current_toolchain
- # has the same architecture as target_toolchain.
- if (sysroot != "" && current_cpu == target_cpu) {
- cflags = [
- "-isysroot",
- sysroot,
- ]
- }
-}
-```
-
-## As a //build/config or //build/toolchain author
-
-The `default_toolchain` is declared in the `//build/config/BUILDCONFIG.gn`
-file. Usually the `default_toolchain` should be the toolchain for the
-`target_os` and `target_cpu`. The `current_toolchain` reflects the
-toolchain that is currently in effect for a rule.
-
-Be sure you understand the differences between `host_cpu`, `target_cpu`,
-`current_cpu`, and `toolchain_cpu` (and the os equivalents). The first
-two are set as described above. You are responsible for making sure that
-`current_cpu` is set appropriately in your toolchain definitions; if you
-are using the stock templates like `gcc_toolchain` and `msvc_toolchain`,
-that means you are responsible for making sure that `toolchain_cpu` and
-`toolchain_os` are set as appropriate in the template invocations.
diff --git a/chromium/tools/gn/docs/faq.md b/chromium/tools/gn/docs/faq.md
deleted file mode 100644
index 55d8aeffead..00000000000
--- a/chromium/tools/gn/docs/faq.md
+++ /dev/null
@@ -1,52 +0,0 @@
-# GN Frequently Asked Questions
-
-[TOC]
-
-## Where is the GN documentation?
-
-GN has extensive built-in help, so you can run `gn help`, but you can
-also see all of the help on [the reference page](reference.md). See
-also the [quick start](quick_start.md) guide and the [language and
-operation details](language.md).
-
-## Can I generate XCode or Visual Studio projects?
-
-You can generate skeleton (or wrapper) projects for Xcode, Visual Studio,
-QTCreator, and Eclipse that will list the files and targets in the
-build, but use Ninja to do the actual build. You cannot generate "real"
-projects that look like native ones like GYP could.
-
-Run `gn help gen` for more details.
-
-## How do I generate common build variants?
-
-In GN, args go with a build directory rather than being global in the
-environment. To edit the args for your `out/Default` build directory:
-
-```
-gn args out/Default
-```
-
-You can set variables in that file:
-
- * The default is a debug build. To do a release build add
- `is_debug = false`
- * The default is a static build. To do a component build add
- `is_component_build = true`
- * The default is a developer build. To do an official build, set
- `is_official_build = true`
- * The default is Chromium branding. To do Chrome branding, set
- `is_chrome_branded = true`
-
-## How do I do cross-compiles?
-
-GN has robust support for doing cross compiles and building things for
-multiple architectures in a single build.
-
-See [GNCrossCompiles](cross_compiles.md) for more info.
-
-## Can I control what targets are built by default?
-
-Yes! If you create a group target called "default" in the top-level (root)
-build file, i.e., "//:default", GN will tell Ninja to build that by
-default, rather than building everything.
diff --git a/chromium/tools/gn/docs/hacking.md b/chromium/tools/gn/docs/hacking.md
deleted file mode 100644
index be3f1328c30..00000000000
--- a/chromium/tools/gn/docs/hacking.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Hacking on the GN binary itself
-
-## Building GN itself
-
-GN is part of the Chromium tree, in [//tools/gn/](../). If you have a
-Chromium checkout, you already have the source and you can do `ninja -C
-out/Debug gn` to build it.
-
-To build gn using gn, run (in the root `src` directory):
-
-```
-gn gen out/Default
-ninja -C out/Default gn
-```
-
-Change `out/Default` as necessary to put the build directory where you
-want.
-
-## Running GN's unit tests
-
-```
-ninja -C out/Default gn_unittests && out/Default/gn_unittests
-```
diff --git a/chromium/tools/gn/docs/language.md b/chromium/tools/gn/docs/language.md
deleted file mode 100644
index dcc6c9ef4e9..00000000000
--- a/chromium/tools/gn/docs/language.md
+++ /dev/null
@@ -1,540 +0,0 @@
-# GN Language and Operation
-
-[TOC]
-
-## Introduction
-
-This page describes many of the language details and behaviors.
-
-### Use the built-in help!
-
-GN has an extensive built-in help system which provides a reference for
-every function and built-in variable. This page is more high-level.
-
-```
-gn help
-```
-
-You can also see the
-[slides](https://docs.google.com/presentation/d/15Zwb53JcncHfEwHpnG_PoIbbzQ3GQi_cpujYwbpcbZo/edit?usp=sharing)
-from a March, 2016 introduction to GN. The speaker notes contain the full
-content.
-
-### Design philosophy
-
- * Writing build files should not be a creative endeavour. Ideally two
- people should produce the same buildfile given the same
- requirements. There should be no flexibility unless it's absolutely
- needed. As many things should be fatal errors as possible.
-
- * The definition should read more like code than rules. I don't want
- to write or debug Prolog. But everybody on our team can write and
- debug C++ and Python.
-
- * The build language should be opinionated as to how the build should
- work. It should not necessarily be easy or even possible to express
- arbitrary things. We should be changing source and tooling to make
- the build simpler rather than making everything more complicated to
- conform to external requirements (within reason).
-
- * Be like Blaze when it makes sense (see "Differences and similarities
- to Blaze" below).
-
-## Language
-
-GN uses an extremely simple, dynamically typed language. The types are:
-
- * Boolean (`true`, `false`).
- * 64-bit signed integers.
- * Strings.
- * Lists (of any other types).
- * Scopes (sort of like a dictionary, only for built-in stuff).
-
-There are some built-in variables whose values depend on the current
-environment. See `gn help` for more.
-
-There are purposefully many omissions in the language. There are no
-user-defined function calls, for example (templates are the closest thing). As
-per the above design philosophy, if you need this kind of thing you're probably
-doing it wrong.
-
-The variable `sources` has a special rule: when assigning to it, a list
-of exclusion patterns is applied to it. This is designed to
-automatically filter out some types of files. See `gn help
-set_sources_assignment_filter` and `gn help label_pattern` for more.
-
-The full grammar for language nerds is available in `gn help grammar`.
-
-### Strings
-
-Strings are enclosed in double-quotes and use backslash as the escape
-character. The only escape sequences supported are:
-
- * `\"` (for literal quote)
- * `\$` (for literal dollars sign)
- * `\\` (for literal backslash)
-
-Any other use of a backslash is treated as a literal backslash. So, for
-example, `\b` used in patterns does not need to be escaped, nor do most Windows
-paths like `"C:\foo\bar.h"`.
-
-Simple variable substitution is supported via `$`, where the word
-following the dollars sign is replaced with the value of the variable.
-You can optionally surround the name with `{}` if there is not a
-non-variable-name character to terminate the variable name. More complex
-expressions are not supported, only variable name substitution.
-
-```
-a = "mypath"
-b = "$a/foo.cc" # b -> "mypath/foo.cc"
-c = "foo${a}bar.cc" # c -> "foomypathbar.cc"
-```
-
-You can encode 8-bit characters using "$0xFF" syntax, so a string with newlines
-(hex 0A) would `"look$0x0Alike$0x0Athis"`.
-
-### Lists
-
-There is no way to get the length of a list. If you find yourself
-wanting to do this kind of thing, you're trying to do too much work in
-the build.
-
-Lists support appending:
-
-```
-a = [ "first" ]
-a += [ "second" ] # [ "first", "second" ]
-a += [ "third", "fourth" ] # [ "first", "second", "third", "fourth" ]
-b = a + [ "fifth" ] # [ "first", "second", "third", "fourth", "fifth" ]
-```
-
-Appending a list to another list appends the items in the second list
-rather than appending the list as a nested member.
-
-You can remove items from a list:
-
-```
-a = [ "first", "second", "third", "first" ]
-b = a - [ "first" ] # [ "second", "third" ]
-a -= [ "second" ] # [ "first", "third", "fourth" ]
-```
-
-The - operator on a list searches for matches and removes all matching
-items. Subtracting a list from another list will remove each item in the
-second list.
-
-If no matching items are found, an error will be thrown, so you need to
-know in advance that the item is there before removing it. Given that
-there is no way to test for inclusion, the main use-case is to set up a
-master list of files or flags, and to remove ones that don't apply to
-the current build based on various conditions.
-
-Stylistically, prefer to only add to lists and have each source file or
-dependency appear once. This is the opposite of the advice Chrome-team used to
-give for GYP (GYP would prefer to list all files, and then remove the ones you
-didn't want in conditionals).
-
-Lists support zero-based subscripting to extract values:
-
-```
-a = [ "first", "second", "third" ]
-b = a[1] # -> "second"
-```
-
-The \[\] operator is read-only and can not be used to mutate the
-list. The primary use-case of this is when an external script returns
-several known values and you want to extract them.
-
-There are some cases where it's easy to overwrite a list when you mean
-to append to it instead. To help catch this case, it is an error to
-assign a nonempty list to a variable containing an existing nonempty
-list. If you want to get around this restriction, first assign the
-destination variable to the empty list.
-
-```
-a = [ "one" ]
-a = [ "two" ] # Error: overwriting nonempty list with a nonempty list.
-a = [] # OK
-a = [ "two" ] # OK
-```
-
-Note that execution of the build script is done without intrinsic
-knowledge of the meaning of the underlying data. This means that it
-doesn't know that `sources` is a list of file names, for example. So if
-you remove an item, it must match the literal string rather than
-specifying a different name that will resolve to the same file name.
-
-### Conditionals
-
-Conditionals look like C:
-
-```
- if (is_linux || (is_win && target_cpu == "x86")) {
- sources -= [ "something.cc" ]
- } else if (...) {
- ...
- } else {
- ...
- }
-```
-
-You can use them in most places, even around entire targets if the
-target should only be declared in certain circumstances.
-
-### Looping
-
-You can iterate over a list with `foreach`. This is discouraged. Most things
-the build should do can normally be expressed without doing this, and if you
-find it necessary it may be an indication you're doing too much work in the
-metabuild.
-
-```
-foreach(i, mylist) {
- print(i) # Note: i is a copy of each element, not a reference to it.
-}
-```
-
-### Function calls
-
-Simple function calls look like most other languages:
-
-```
-print("hello, world")
-assert(is_win, "This should only be executed on Windows")
-```
-
-Such functions are built-in and the user can not define new ones.
-
-Some functions take a block of code enclosed by `{ }` following them:
-
-```
-static_library("mylibrary") {
- sources = [ "a.cc" ]
-}
-```
-
-Most of these define targets. The user can define new functions like this
-with the template mechanism discussed below.
-
-Precisely, this expression means that the block becomes an argument to the
-function for the function to execute. Most of the block-style functions execute
-the block and treat the resulting scope as a dictionary of variables to read.
-
-### Scoping and execution
-
-Files and function calls followed by `{ }` blocks introduce new scopes. Scopes
-are nested. When you read a variable, the containing scopes will be searched in
-reverse order until a matching name is found. Variable writes always go to the
-innermost scope.
-
-There is no way to modify any enclosing scope other than the innermost
-one. This means that when you define a target, for example, nothing you
-do inside of the block will "leak out" into the rest of the file.
-
-`if`/`else`/`foreach` statements, even though they use `{ }`, do not introduce
-a new scope so changes will persist outside of the statement.
-
-## Naming things
-
-### File and directory names
-
-File and directory names are strings and are interpreted as relative to
-the current build file's directory. There are three possible forms:
-
-Relative names:
-
-```
-"foo.cc"
-"src/foo.cc"
-"../src/foo.cc"
-```
-
-Source-tree absolute names:
-
-```
-"//net/foo.cc"
-"//base/test/foo.cc"
-```
-
-System absolute names (rare, normally used for include directories):
-
-```
-"/usr/local/include/"
-"/C:/Program Files/Windows Kits/Include"
-```
-
-## Build configuration
-
-## Targets
-
-A target is a node in the build graph. It usually represents some kind
-of executable or library file that will be generated. Targets depend on
-other targets. The built-in target types (see `gn help <targettype>` for
-more help) are:
-
- * `action`: Run a script to generate a file.
- * `action_foreach`: Run a script once for each source file.
- * `bundle_data`: Declare data to go into a Mac/iOS bundle.
- * `create_bundle`: Creates a Mac/iOS bundle.
- * `executable`: Generates an executable file.
- * `group`: A virtual dependency node that refers to one or more other
- targets.
- * `shared_library`: A .dll or .so.
- * `loadable_module`: A .dll or .so loadable only at runtime.
- * `source_set`: A lightweight virtual static library (usually
- preferrable over a real static library since it will build faster).
- * `static_library`: A .lib or .a file (normally you'll want a
- `source_set` instead).
-
-You can extend this to make custom target types using templates (see below). In
-Chrome some of the more commonly-used templates are:
-
- * `component`: Either a source set or shared library, depending on the
- build type.
- * `test`: A test executable. On mobile this will create the appropriate
- native app type for tests.
- * `app`: Executable or Mac/iOS application.
- * `android_apk`: Make an APK. There are a _lot_ of other Android ones, see
- `//build/config/android/rules.gni`.
-
-## Configs
-
-Configs are named objects that specify sets of flags, include
-directories, and defines. They can be applied to a target and pushed to
-dependent targets.
-
-To define a config:
-
-```
-config("myconfig") {
- includes = [ "src/include" ]
- defines = [ "ENABLE_DOOM_MELON" ]
-}
-```
-
-To apply a config to a target:
-
-```
-executable("doom_melon") {
- configs = [ ":myconfig" ]
-}
-```
-
-It is common for the build config file to specify target defaults that
-set a default list of configs. Targets can add or remove to this list as
-needed. So in practice you would usually use `configs += ":myconfig"` to
-append to the list of defaults.
-
-See `gn help config` for more information about how configs are declared
-and applied.
-
-### Public configs
-
-A target can apply settings to other targets that depend on it. The most
-common example is a third party target that requires some defines or
-include directories for its headers to compile properly. You want these
-settings to apply both to the compile of the third party library itself,
-as well as all targets that use the library.
-
-To do this, you write a config with the settings you want to apply:
-
-```
-config("my_external_library_config") {
- includes = "."
- defines = [ "DISABLE_JANK" ]
-}
-```
-
-Then this config is added to the target as a "public" config. It will
-apply both to the target as well as targets that directly depend on it.
-
-```
-shared_library("my_external_library") {
- ...
- # Targets that depend on this get this config applied.
- public_configs = [ ":my_external_library_config" ]
-}
-```
-
-Dependent targets can in turn forward this up the dependency tree
-another level by adding your target as a "public" dependency.
-
-```
-static_library("intermediate_library") {
- ...
- # Targets that depend on this one also get the configs from "my external library".
- public_deps = [ ":my_external_library" ]
-}
-```
-
-A target can forward a config to all dependents until a link boundary is
-reached by setting it as an `all_dependent_config`. This is strongly
-discouraged as it can spray flags and defines over more of the build than
-necessary. Instead, use public_deps to control which flags apply where.
-
-In Chrome, prefer the build flag header system (`build/buildflag_header.gni`)
-for defines which prevents most screw-ups with compiler defines.
-
-## Templates
-
-Templates are GN's primary way to re-use code. Typically, a template
-would expand to one or more other target types.
-
-```
-# Declares a script that compiles IDL files to source, and then compiles those
-# source files.
-template("idl") {
- # Always base helper targets on target_name so they're unique. Target name
- # will be the string passed as the name when the template is invoked.
- idl_target_name = "${target_name}_generate"
- action_foreach(idl_target_name) {
- ...
- }
-
- # Your template should always define a target with the name target_name.
- # When other targets depend on your template invocation, this will be the
- # destination of that dependency.
- source_set(target_name) {
- ...
- deps = [ ":$idl_target_name" ] # Require the sources to be compiled.
- }
-}
-```
-
-Typically your template definition would go in a `.gni` file and users
-would import that file to see the template definition:
-
-```
-import("//tools/idl_compiler.gni")
-
-idl("my_interfaces") {
- sources = [ "a.idl", "b.idl" ]
-}
-```
-
-Declaring a template creates a closure around the variables in scope at
-that time. When the template is invoked, the magic variable `invoker` is
-used to read variables out of the invoking scope. The template would
-generally copy the values its interested in into its own scope:
-
-```
-template("idl") {
- source_set(target_name) {
- sources = invoker.sources
- }
-}
-```
-
-The current directory when a template executes will be that of the
-invoking build file rather than the template source file. This is so
-files passed in from the template invoker will be correct (this
-generally accounts for most file handling in a template). However, if
-the template has files itself (perhaps it generates an action that runs
-a script), you will want to use absolute paths ("//foo/...") to refer to
-these files to account for the fact that the current directory will be
-unpredictable during invocation. See `gn help template` for more
-information and more complete examples.
-
-## Other features
-
-### Imports
-
-You can import `.gni` files into the current scope with the `import`
-function. This is _not_ an include in the C++ sense. The imported file is
-executed independently and the resulting scope is copied into the current file
-(C++ executes the included file in the current context of when the
-include directive appeared). This allows the results of the import to be
-cached, and also prevents some of the more "creative" uses of includes like
-multiply-included files.
-
-Typically, a `.gni` would define build arguments and templates. See `gn
-help import` for more.
-
-Your `.gni` file can define temporary variables that are not exported files
-that include it by using a preceding underscore in the name like `_this`.
-
-### Path processing
-
-Often you will want to make a file name or a list of file names relative
-to a different directory. This is especially common when running
-scripts, which are executed with the build output directory as the
-current directory, while build files usually refer to files relative to
-their containing directory.
-
-You can use `rebase_path` to convert directories. See `gn help
-rebase_path` for more help and examples. Typical usage to convert a file
-name relative to the current directory to be relative to the root build
-directory would be: ``` new_paths = rebase_path("myfile.c",
-root_build_dir) ```
-
-### Patterns
-
-Patterns are used to generate the output file names for a given set of
-inputs for custom target types, and to automatically remove files from
-the `sources` variable (see `gn help set_sources_assignment_filter`).
-
-They are like simple regular expressions. See `gn help label_pattern`
-for more.
-
-### Executing scripts
-
-There are two ways to execute scripts. All external scripts in GN are in
-Python. The first way is as a build step. Such a script would take some
-input and generate some output as part of the build. Targets that invoke
-scripts are declared with the "action" target type (see `gn help
-action`).
-
-The second way to execute scripts is synchronously during build file
-execution. This is necessary in some cases to determine the set of files
-to compile, or to get certain system configurations that the build file
-might depend on. The build file can read the stdout of the script and
-act on it in different ways.
-
-Synchronous script execution is done by the `exec_script` function (see
-`gn help exec_script` for details and examples). Because synchronously
-executing a script requires that the current buildfile execution be
-suspended until a Python process completes execution, relying on
-external scripts is slow and should be minimized.
-
-To prevent abuse, files permitted to call `exec_script` can be whitelisted in
-the toplevel `.gn` file. Chrome does this to require additional code review
-for such additions. See `gn help dotfile`.
-
-You can synchronously read and write files which is discouraged but
-occasionally necessary when synchronously running scripts. The typical use-case
-would be to pass a list of file names longer than the command-line limits of
-the current platform. See `gn help read_file` and `gn help write_file` for how
-to read and write files. These functions should be avoided if at all possible.
-
-Actions that exceed command-line length limits can use response files to
-get around this limitation without synchronously writing files. See
-`gn help response_file_contents`.
-
-# Differences and similarities to Blaze
-
-Blaze is Google's internal build system, now publicly released as
-[Bazel](http://bazel.io/). It has inspired a number of other systems such as
-[Pants](http://www.pantsbuild.org/) and [Buck](http://facebook.github.io/buck/).
-
-In Google's homogeneous environment, the need for conditionals is very
-low and they can get by with a few hacks (`abi_deps`). Chrome uses
-conditionals all over the place and the need to add these is the main
-reason for the files looking different.
-
-GN also adds the concept of "configs" to manage some of the trickier
-dependency and configuration problems which likewise don't arise on the
-server. Blaze has a concept of a "configuration" which is like a GN
-toolchain, but built into the tool itself. The way that toolchains work
-in GN is a result of trying to separate this concept out into the build
-files in a clean way.
-
-GN keeps some GYP concept like "all dependent" settings which work a bit
-differently in Blaze. This is partially to make conversion from the existing
-GYP code easier, and the GYP constructs generally offer more fine-grained
-control (which is either good or bad, depending on the situation).
-
-GN also uses GYP names like "sources" instead of "srcs" since
-abbreviating this seems needlessly obscure, although it uses Blaze's
-"deps" since "dependencies" is so hard to type. Chromium also compiles
-multiple languages in one target so specifying the language type on the
-target name prefix was dropped (e.g. from `cc_library`).
diff --git a/chromium/tools/gn/docs/quick_start.md b/chromium/tools/gn/docs/quick_start.md
deleted file mode 100644
index 629b36d62c9..00000000000
--- a/chromium/tools/gn/docs/quick_start.md
+++ /dev/null
@@ -1,365 +0,0 @@
-# GN Quick Start guide
-
-[TOC]
-
-## Running GN
-
-You just run `gn` from the command line. There is a script in
-`depot_tools`, which is presumably in your PATH, with this name. The
-script will find the binary in the source tree containing the current
-directory and run it.
-
-## Setting up a build
-
-In GYP, the system would generate `Debug` and `Release` build
-directories for you and configure them accordingly. GN doesn't do this.
-Instead, you set up whatever build directory you want with whatever
-configuration you want. The Ninja files will be automatically
-regenerated if they're out of date when you build in that directory.
-
-To make a build directory:
-
-```
-gn gen out/my_build
-```
-
-## Passing build arguments
-
-Set build arguments on your build directory by running:
-
-```
-gn args out/my_build
-```
-
-This will bring up an editor. Type build args into that file like this:
-
-```
-is_component_build = true
-is_debug = false
-```
-
-You can see the list of available arguments and their default values by
-typing
-
-```
-gn args --list out/my_build
-```
-
-on the command line. Note that you have to specify the build directory
-for this command because the available arguments can change according
-to what's set.
-
-Chrome developers can also read the [Chrome-specific build
-configuration](http://www.chromium.org/developers/gn-build-configuration)
-instructions for more information.
-
-## Cross-compiling to a target OS or architecture
-
-Run `gn args out/Default` (substituting your build directory as needed) and
-add one or more of the following lines for common cross-compiling options.
-
-```
-target_os = "chromeos"
-target_os = "android"
-
-target_cpu = "arm"
-target_cpu = "x86"
-target_cpu = "x64"
-```
-
-See [GNCrossCompiles](cross_compiles.md) for more info.
-
-## Configuring goma
-
-Run `gn args out/Default` (substituting your build directory as needed).
-Add:
-
-```
-use_goma = true
-goma_dir = "~/foo/bar/goma"
-```
-
-If your goma is in the default location (`~/goma`) then you can omit the
-`goma_dir` line.
-
-## Configuring component mode
-
-This is a build arg like the goma flags. run `gn args out/Default` and add:
-
-```
-is_component_build = true
-```
-
-## Step-by-step
-
-### Adding a build file
-
-Create a `tools/gn/tutorial/BUILD.gn` file and enter the following:
-
-```
-executable("hello_world") {
- sources = [
- "hello_world.cc",
- ]
-}
-```
-
-There should already be a `hello_world.cc` file in that directory,
-containing what you expect. That's it! Now we just need to tell the
-build about this file. Open the `BUILD.gn` file in the root directory
-and add the label of this target to the dependencies of one of the root
-groups (a "group" target is a meta-target that is just a collection of
-other targets):
-
-```
-group("root") {
- deps = [
- ...
- "//url",
- "//tools/gn/tutorial:hello_world",
- ]
-}
-```
-
-You can see the label of your target is "//" (indicating the source
-root), followed by the directory name, a colon, and the target name.
-
-### Testing your addition
-
-From the command line in the source root directory:
-
-```
-gn gen out/Default
-ninja -C out/Default hello_world
-out/Default/hello_world
-```
-
-GN encourages target names for static libraries that aren't globally
-unique. To build one of these, you can pass the label with no leading
-"//" to ninja:
-
-```
-ninja -C out/Default tools/gn/tutorial:hello_world
-```
-
-### Declaring dependencies
-
-Let's make a static library that has a function to say hello to random
-people. There is a source file `hello.cc` in that directory which has a
-function to do this. Open the `tools/gn/tutorial/BUILD.gn` file and add
-the static library to the bottom of the existing file:
-
-```
-static_library("hello") {
- sources = [
- "hello.cc",
- ]
-}
-```
-
-Now let's add an executable that depends on this library:
-
-```
-executable("say_hello") {
- sources = [
- "say_hello.cc",
- ]
- deps = [
- ":hello",
- ]
-}
-```
-
-This executable includes one source file and depends on the previous
-static library. The static library is referenced by its label in the
-`deps`. You could have used the full label `//tools/gn/tutorial:hello`
-but if you're referencing a target in the same build file, you can use
-the shortcut `:hello`.
-
-### Test the static library version
-
-From the command line in the source root directory:
-
-```
-ninja -C out/Default say_hello
-out/Default/say_hello
-```
-
-Note that you **didn't** need to re-run GN. GN will automatically rebuild
-the ninja files when any build file has changed. You know this happens
-when ninja prints `[1/1] Regenerating ninja files` at the beginning of
-execution.
-
-### Compiler settings
-
-Our hello library has a new feature, the ability to say hello to two
-people at once. This feature is controlled by defining `TWO_PEOPLE`. We
-can add defines like so:
-
-```
-static_library("hello") {
- sources = [
- "hello.cc",
- ]
- defines = [
- "TWO_PEOPLE",
- ]
-}
-```
-
-### Putting settings in a config
-
-However, users of the library also need to know about this define, and
-putting it in the static library target defines it only for the files
-there. If somebody else includes `hello.h`, they won't see the new
-definition. To see the new definition, everybody will have to define
-`TWO_PEOPLE`.
-
-GN has a concept called a "config" which encapsulates settings. Let's
-create one that defines our preprocessor define:
-
-```
-config("hello_config") {
- defines = [
- "TWO_PEOPLE",
- ]
-}
-```
-
-To apply these settings to your target, you only need to add the
-config's label to the list of configs in the target:
-
-```
-static_library("hello") {
- ...
- configs += [
- ":hello_config",
- ]
-}
-```
-
-Note that you need "+=" here instead of "=" since the build
-configuration has a default set of configs applied to each target that
-set up the default build stuff. You want to add to this list rather than
-overwrite it. To see the default configs, you can use the `print`
-function in the build file or the `desc` command-line subcommand (see
-below for examples of both).
-
-### Dependent configs
-
-This nicely encapsulates our settings, but still requires everybody that
-uses our library to set the config on themselves. It would be nice if
-everybody that depends on our `hello` library can get this
-automatically. Change your library definition to:
-
-```
-static_library("hello") {
- sources = [
- "hello.cc",
- ]
- all_dependent_configs = [
- ":hello_config"
- ]
-}
-```
-
-This applies the `hello_config` to the `hello` target itself, plus all
-targets that transitively depend on the current one. Now everybody that
-depends on us will get our settings. You can also set `public_configs`
-which applies only to targets that directly depend on your target (not
-transitively).
-
-Now if you compile and run, you'll see the new version with two people:
-
-```
-> ninja -C out/Default say_hello
-ninja: Entering directory 'out/Default'
-[1/1] Regenerating ninja files
-[4/4] LINK say_hello
-> out/Default/say_hello
-Hello, Bill and Joy.
-```
-
-## Add a new build argument
-
-You declare which arguments you accept and specify default values via
-`declare_args`.
-
-```
-declare_args() {
- enable_teleporter = true
- enable_doom_melon = false
-}
-```
-
-See `gn help buildargs` for an overview of how this works.
-See `gn help declare_args` for specifics on declaring them.
-
-It is an error to declare a given argument more than once in a given scope, so
-care should be used in scoping and naming arguments.
-
-## Don't know what's going on?
-
-You can run GN in verbose mode to see lots of messages about what it's
-doing. Use `-v` for this.
-
-### Print debugging
-
-There is a `print` command which just writes to stdout:
-
-```
-static_library("hello") {
- ...
- print(configs)
-}
-```
-
-This will print all of the configs applying to your target (including
-the default ones).
-
-### The "desc" command
-
-You can run `gn desc <build_dir> <targetname>` to get information about
-a given target:
-
-```
-gn desc out/Default //tools/gn/tutorial:say_hello
-```
-
-will print out lots of exciting information. You can also print just one
-section. Lets say you wanted to know where your `TWO_PEOPLE` define
-came from on the `say_hello` target:
-
-```
-> gn desc out/Default //tools/gn/tutorial:say_hello defines --blame
-...lots of other stuff omitted...
- From //tools/gn/tutorial:hello_config
- (Added by //tools/gn/tutorial/BUILD.gn:12)
- TWO_PEOPLE
-```
-
-You can see that `TWO_PEOPLE` was defined by a config, and you can also
-see the which line caused that config to be applied to your target (in
-this case, the `all_dependent_configs` line).
-
-Another particularly interesting variation:
-
-```
-gn desc out/Default //base:base_i18n deps --tree
-```
-
-See `gn help desc` for more.
-
-### Performance
-
-You can see what took a long time by running it with the --time command
-line flag. This will output a summary of timings for various things.
-
-You can also make a trace of how the build files were executed:
-
-```
-gn --tracelog=mylog.trace
-```
-
-and you can load the resulting file in Chrome's `about:tracing` page to
-look at everything.
diff --git a/chromium/tools/gn/docs/reference.md b/chromium/tools/gn/docs/reference.md
deleted file mode 100644
index a98212012bd..00000000000
--- a/chromium/tools/gn/docs/reference.md
+++ /dev/null
@@ -1,6405 +0,0 @@
-# GN Reference
-
-*This page is automatically generated from* `gn help --markdown all`.
-
-## Contents
-
-* [Commands](#commands)
- * [analyze: Analyze which targets are affected by a list of files.](#analyze)
- * [args: Display or configure arguments declared by the build.](#args)
- * [check: Check header dependencies.](#check)
- * [clean: Cleans the output directory.](#clean)
- * [desc: Show lots of insightful information about a target or config.](#desc)
- * [format: Format .gn file.](#format)
- * [gen: Generate ninja files.](#gen)
- * [help: Does what you think.](#help)
- * [ls: List matching targets.](#ls)
- * [path: Find paths between two targets.](#path)
- * [refs: Find stuff referencing a target or file.](#refs)
-* [Target declarations](#targets)
- * [action: Declare a target that runs a script a single time.](#action)
- * [action_foreach: Declare a target that runs a script over a set of files.](#action_foreach)
- * [bundle_data: [iOS/macOS] Declare a target without output.](#bundle_data)
- * [copy: Declare a target that copies files.](#copy)
- * [create_bundle: [iOS/macOS] Build an iOS or macOS bundle.](#create_bundle)
- * [executable: Declare an executable target.](#executable)
- * [group: Declare a named group of targets.](#group)
- * [loadable_module: Declare a loadable module target.](#loadable_module)
- * [shared_library: Declare a shared library target.](#shared_library)
- * [source_set: Declare a source set target.](#source_set)
- * [static_library: Declare a static library target.](#static_library)
- * [target: Declare an target with the given programmatic type.](#target)
-* [Buildfile functions](#functions)
- * [assert: Assert an expression is true at generation time.](#assert)
- * [config: Defines a configuration object.](#config)
- * [declare_args: Declare build arguments.](#declare_args)
- * [defined: Returns whether an identifier is defined.](#defined)
- * [exec_script: Synchronously run a script and return the output.](#exec_script)
- * [foreach: Iterate over a list.](#foreach)
- * [forward_variables_from: Copies variables from a different scope.](#forward_variables_from)
- * [get_label_info: Get an attribute from a target's label.](#get_label_info)
- * [get_path_info: Extract parts of a file or directory name.](#get_path_info)
- * [get_target_outputs: [file list] Get the list of outputs from a target.](#get_target_outputs)
- * [getenv: Get an environment variable.](#getenv)
- * [import: Import a file into the current scope.](#import)
- * [not_needed: Mark variables from scope as not needed.](#not_needed)
- * [pool: Defines a pool object.](#pool)
- * [print: Prints to the console.](#print)
- * [process_file_template: Do template expansion over a list of files.](#process_file_template)
- * [read_file: Read a file into a variable.](#read_file)
- * [rebase_path: Rebase a file or directory to another location.](#rebase_path)
- * [set_default_toolchain: Sets the default toolchain name.](#set_default_toolchain)
- * [set_defaults: Set default values for a target type.](#set_defaults)
- * [set_sources_assignment_filter: Set a pattern to filter source files.](#set_sources_assignment_filter)
- * [split_list: Splits a list into N different sub-lists.](#split_list)
- * [template: Define a template rule.](#template)
- * [tool: Specify arguments to a toolchain tool.](#tool)
- * [toolchain: Defines a toolchain.](#toolchain)
- * [write_file: Write a file to disk.](#write_file)
-* [Built-in predefined variables](#predefined_variables)
- * [current_cpu: [string] The processor architecture of the current toolchain.](#current_cpu)
- * [current_os: [string] The operating system of the current toolchain.](#current_os)
- * [current_toolchain: [string] Label of the current toolchain.](#current_toolchain)
- * [default_toolchain: [string] Label of the default toolchain.](#default_toolchain)
- * [host_cpu: [string] The processor architecture that GN is running on.](#host_cpu)
- * [host_os: [string] The operating system that GN is running on.](#host_os)
- * [invoker: [string] The invoking scope inside a template.](#invoker)
- * [python_path: [string] Absolute path of Python.](#python_path)
- * [root_build_dir: [string] Directory where build commands are run.](#root_build_dir)
- * [root_gen_dir: [string] Directory for the toolchain's generated files.](#root_gen_dir)
- * [root_out_dir: [string] Root directory for toolchain output files.](#root_out_dir)
- * [target_cpu: [string] The desired cpu architecture for the build.](#target_cpu)
- * [target_gen_dir: [string] Directory for a target's generated files.](#target_gen_dir)
- * [target_name: [string] The name of the current target.](#target_name)
- * [target_os: [string] The desired operating system for the build.](#target_os)
- * [target_out_dir: [string] Directory for target output files.](#target_out_dir)
-* [Variables you set in targets](#target_variables)
- * [all_dependent_configs: [label list] Configs to be forced on dependents.](#all_dependent_configs)
- * [allow_circular_includes_from: [label list] Permit includes from deps.](#allow_circular_includes_from)
- * [arflags: [string list] Arguments passed to static_library archiver.](#arflags)
- * [args: [string list] Arguments passed to an action.](#args)
- * [asmflags: [string list] Flags passed to the assembler.](#asmflags)
- * [assert_no_deps: [label pattern list] Ensure no deps on these targets.](#assert_no_deps)
- * [bundle_contents_dir: Expansion of {{bundle_contents_dir}} in create_bundle.](#bundle_contents_dir)
- * [bundle_deps_filter: [label list] A list of labels that are filtered out.](#bundle_deps_filter)
- * [bundle_executable_dir: Expansion of {{bundle_executable_dir}} in create_bundle](#bundle_executable_dir)
- * [bundle_plugins_dir: Expansion of {{bundle_plugins_dir}} in create_bundle.](#bundle_plugins_dir)
- * [bundle_resources_dir: Expansion of {{bundle_resources_dir}} in create_bundle.](#bundle_resources_dir)
- * [bundle_root_dir: Expansion of {{bundle_root_dir}} in create_bundle.](#bundle_root_dir)
- * [cflags: [string list] Flags passed to all C compiler variants.](#cflags)
- * [cflags_c: [string list] Flags passed to the C compiler.](#cflags_c)
- * [cflags_cc: [string list] Flags passed to the C++ compiler.](#cflags_cc)
- * [cflags_objc: [string list] Flags passed to the Objective C compiler.](#cflags_objc)
- * [cflags_objcc: [string list] Flags passed to the Objective C++ compiler.](#cflags_objcc)
- * [check_includes: [boolean] Controls whether a target's files are checked.](#check_includes)
- * [code_signing_args: [string list] Arguments passed to code signing script.](#code_signing_args)
- * [code_signing_outputs: [file list] Output files for code signing step.](#code_signing_outputs)
- * [code_signing_script: [file name] Script for code signing.](#code_signing_script)
- * [code_signing_sources: [file list] Sources for code signing step.](#code_signing_sources)
- * [complete_static_lib: [boolean] Links all deps into a static library.](#complete_static_lib)
- * [configs: [label list] Configs applying to this target or config.](#configs)
- * [data: [file list] Runtime data file dependencies.](#data)
- * [data_deps: [label list] Non-linked dependencies.](#data_deps)
- * [defines: [string list] C preprocessor defines.](#defines)
- * [depfile: [string] File name for input dependencies for actions.](#depfile)
- * [deps: [label list] Private linked dependencies.](#deps)
- * [friend: [label pattern list] Allow targets to include private headers.](#friend)
- * [include_dirs: [directory list] Additional include directories.](#include_dirs)
- * [inputs: [file list] Additional compile-time dependencies.](#inputs)
- * [ldflags: [string list] Flags passed to the linker.](#ldflags)
- * [lib_dirs: [directory list] Additional library directories.](#lib_dirs)
- * [libs: [string list] Additional libraries to link.](#libs)
- * [output_dir: [directory] Directory to put output file in.](#output_dir)
- * [output_extension: [string] Value to use for the output's file extension.](#output_extension)
- * [output_name: [string] Name for the output file other than the default.](#output_name)
- * [output_prefix_override: [boolean] Don't use prefix for output name.](#output_prefix_override)
- * [outputs: [file list] Output files for actions and copy targets.](#outputs)
- * [partial_info_plist: [filename] Path plist from asset catalog compiler.](#partial_info_plist)
- * [pool: [string] Label of the pool used by the action.](#pool)
- * [precompiled_header: [string] Header file to precompile.](#precompiled_header)
- * [precompiled_header_type: [string] "gcc" or "msvc".](#precompiled_header_type)
- * [precompiled_source: [file name] Source file to precompile.](#precompiled_source)
- * [product_type: [string] Product type for Xcode projects.](#product_type)
- * [public: [file list] Declare public header files for a target.](#public)
- * [public_configs: [label list] Configs applied to dependents.](#public_configs)
- * [public_deps: [label list] Declare public dependencies.](#public_deps)
- * [response_file_contents: [string list] Contents of .rsp file for actions.](#response_file_contents)
- * [script: [file name] Script file for actions.](#script)
- * [sources: [file list] Source files for a target.](#sources)
- * [testonly: [boolean] Declares a target must only be used for testing.](#testonly)
- * [visibility: [label list] A list of labels that can depend on a target.](#visibility)
- * [write_runtime_deps: Writes the target's runtime_deps to the given path.](#write_runtime_deps)
- * [xcode_extra_attributes: [scope] Extra attributes for Xcode projects.](#xcode_extra_attributes)
- * [test_application_name: [string] Test application name for unit or ui test target.](#test_application_name)
-* [Other help topics](#other)
- * [all: Print all the help at once](#all)
- * [buildargs: How build arguments work.](#buildargs)
- * [dotfile: Info about the toplevel .gn file.](#dotfile)
- * [execution: Build graph and execution overview.](#execution)
- * [grammar: Language and grammar for GN build files.](#grammar)
- * [input_conversion: Processing input from exec_script and read_file.](#input_conversion)
- * [label_pattern: Matching more than one label.](#label_pattern)
- * [labels: About labels.](#labels)
- * [ninja_rules: How Ninja build rules are named.](#ninja_rules)
- * [nogncheck: Annotating includes for checking.](#nogncheck)
- * [runtime_deps: How runtime dependency computation works.](#runtime_deps)
- * [source_expansion: Map sources to outputs for scripts.](#source_expansion)
- * [switches: Show available command-line switches.](#switches)
-
-## <a name="commands"></a>Commands
-
-### <a name="analyze"></a>**gn analyze <out_dir> <input_path> <output_path>**
-
-```
- Analyze which targets are affected by a list of files.
-
- This command takes three arguments:
-
- out_dir is the path to the build directory.
-
- input_path is a path to a file containing a JSON object with three fields:
-
- - "files": A list of the filenames to check.
-
- - "test_targets": A list of the labels for targets that are needed to run
- the tests we wish to run.
-
- - "additional_compile_targets": A list of the labels for targets that we
- wish to rebuild, but aren't necessarily needed for testing. The important
- difference between this field and "test_targets" is that if an item in
- the additional_compile_targets list refers to a group, then any
- dependencies of that group will be returned if they are out of date, but
- the group itself does not need to be. If the dependencies themselves are
- groups, the same filtering is repeated. This filtering can be used to
- avoid rebuilding dependencies of a group that are unaffected by the input
- files. The list may also contain the string "all" to refer to a
- pseudo-group that contains every root target in the build graph.
-
- This filtering behavior is also known as "pruning" the list of compile
- targets.
-
- output_path is a path indicating where the results of the command are to be
- written. The results will be a file containing a JSON object with one or more
- of following fields:
-
- - "compile_targets": A list of the labels derived from the input
- compile_targets list that are affected by the input files. Due to the way
- the filtering works for compile targets as described above, this list may
- contain targets that do not appear in the input list.
-
- - "test_targets": A list of the labels from the input test_targets list that
- are affected by the input files. This list will be a proper subset of the
- input list.
-
- - "invalid_targets": A list of any names from the input that do not exist in
- the build graph. If this list is non-empty, the "error" field will also be
- set to "Invalid targets".
-
- - "status": A string containing one of three values:
-
- - "Found dependency"
- - "No dependency"
- - "Found dependency (all) "
-
- In the first case, the lists returned in compile_targets and test_targets
- should be passed to ninja to build. In the second case, nothing was
- affected and no build is necessary. In the third case, GN could not
- determine the correct answer and returned the input as the output in order
- to be safe.
-
- - "error": This will only be present if an error occurred, and will contain
- a string describing the error. This includes cases where the input file is
- not in the right format, or contains invalid targets.
-
- The command returns 1 if it is unable to read the input file or write the
- output file, or if there is something wrong with the build such that gen
- would also fail, and 0 otherwise. In particular, it returns 0 even if the
- "error" key is non-empty and a non-fatal error occurred. In other words, it
- tries really hard to always write something to the output JSON and convey
- errors that way rather than via return codes.
-```
-### <a name="args"></a>**gn args <out_dir> [\--list] [\--short] [\--args] [\--overrides-only]**
-
-```
- See also "gn help buildargs" for a more high-level overview of how
- build arguments work.
-```
-
-#### **Usage**
-
-```
- gn args <out_dir>
- Open the arguments for the given build directory in an editor. If the
- given build directory doesn't exist, it will be created and an empty args
- file will be opened in the editor. You would type something like this
- into that file:
- enable_doom_melon=false
- os="android"
-
- To find your editor on Posix, GN will search the environment variables in
- order: GN_EDITOR, VISUAL, and EDITOR. On Windows GN will open the command
- associated with .txt files.
-
- Note: you can edit the build args manually by editing the file "args.gn"
- in the build directory and then running "gn gen <out_dir>".
-
- gn args <out_dir> --list[=<exact_arg>] [--short] [--overrides-only] [--json]
- Lists all build arguments available in the current configuration, or, if
- an exact_arg is specified for the list flag, just that one build
- argument.
-
- The output will list the declaration location, current value for the
- build, default value (if different than the current value), and comment
- preceding the declaration.
-
- If --short is specified, only the names and current values will be
- printed.
-
- If --overrides-only is specified, only the names and current values of
- arguments that have been overridden (i.e. non-default arguments) will
- be printed. Overrides come from the <out_dir>/args.gn file and //.gn
-
- If --json is specified, the output will be emitted in json format.
- JSON schema for output:
- [
- {
- "name": variable_name,
- "current": {
- "value": overridden_value,
- "file": file_name,
- "line": line_no
- },
- "default": {
- "value": default_value,
- "file": file_name,
- "line": line_no
- },
- "comment": comment_string
- },
- ...
- ]
-```
-
-#### **Examples**
-
-```
- gn args out/Debug
- Opens an editor with the args for out/Debug.
-
- gn args out/Debug --list --short
- Prints all arguments with their default values for the out/Debug
- build.
-
- gn args out/Debug --list --short --overrides-only
- Prints overridden arguments for the out/Debug build.
-
- gn args out/Debug --list=target_cpu
- Prints information about the "target_cpu" argument for the "
- "out/Debug
- build.
-
- gn args --list --args="os=\"android\" enable_doom_melon=true"
- Prints all arguments with the default values for a build with the
- given arguments set (which may affect the values of other
- arguments).
-```
-### <a name="check"></a>**gn check <out_dir> [<label_pattern>] [\--force]**
-
-```
- GN's include header checker validates that the includes for C-like source
- files match the build dependency graph.
-
- "gn check" is the same thing as "gn gen" with the "--check" flag except that
- this command does not write out any build files. It's intended to be an easy
- way to manually trigger include file checking.
-
- The <label_pattern> can take exact labels or patterns that match more than
- one (although not general regular expressions). If specified, only those
- matching targets will be checked. See "gn help label_pattern" for details.
-```
-
-#### **Command-specific switches**
-
-```
- --force
- Ignores specifications of "check_includes = false" and checks all
- target's files that match the target label.
-```
-
-#### **What gets checked**
-
-```
- The .gn file may specify a list of targets to be checked. Only these targets
- will be checked if no label_pattern is specified on the command line.
- Otherwise, the command-line list is used instead. See "gn help dotfile".
-
- Targets can opt-out from checking with "check_includes = false" (see
- "gn help check_includes").
-
- For targets being checked:
-
- - GN opens all C-like source files in the targets to be checked and scans
- the top for includes.
-
- - Includes with a "nogncheck" annotation are skipped (see
- "gn help nogncheck").
-
- - Only includes using "quotes" are checked. <brackets> are assumed to be
- system includes.
-
- - Include paths are assumed to be relative to any of the "include_dirs" for
- the target (including the implicit current dir).
-
- - GN does not run the preprocessor so will not understand conditional
- includes.
-
- - Only includes matching known files in the build are checked: includes
- matching unknown paths are ignored.
-
- For an include to be valid:
-
- - The included file must be in the current target, or there must be a path
- following only public dependencies to a target with the file in it
- ("gn path" is a good way to diagnose problems).
-
- - There can be multiple targets with an included file: only one needs to be
- valid for the include to be allowed.
-
- - If there are only "sources" in a target, all are considered to be public
- and can be included by other targets with a valid public dependency path.
-
- - If a target lists files as "public", only those files are able to be
- included by other targets. Anything in the sources will be considered
- private and will not be includable regardless of dependency paths.
-
- - Outputs from actions are treated like public sources on that target.
-
- - A target can include headers from a target that depends on it if the
- other target is annotated accordingly. See "gn help
- allow_circular_includes_from".
-```
-
-#### **Advice on fixing problems**
-
-```
- If you have a third party project that is difficult to fix or doesn't care
- about include checks it's generally best to exclude that target from checking
- altogether via "check_includes = false".
-
- If you have conditional includes, make sure the build conditions and the
- preprocessor conditions match, and annotate the line with "nogncheck" (see
- "gn help nogncheck" for an example).
-
- If two targets are hopelessly intertwined, use the
- "allow_circular_includes_from" annotation. Ideally each should have identical
- dependencies so configs inherited from those dependencies are consistent (see
- "gn help allow_circular_includes_from").
-
- If you have a standalone header file or files that need to be shared between
- a few targets, you can consider making a source_set listing only those
- headers as public sources. With only header files, the source set will be a
- no-op from a build perspective, but will give a central place to refer to
- those headers. That source set's files will still need to pass "gn check" in
- isolation.
-
- In rare cases it makes sense to list a header in more than one target if it
- could be considered conceptually a member of both.
-```
-
-#### **Examples**
-
-```
- gn check out/Debug
- Check everything.
-
- gn check out/Default //foo:bar
- Check only the files in the //foo:bar target.
-
- gn check out/Default "//foo/*
- Check only the files in targets in the //foo directory tree.
-```
-### <a name="clean"></a>**gn clean <out_dir>**
-
-```
- Deletes the contents of the output directory except for args.gn and
- creates a Ninja build environment sufficient to regenerate the build.
-```
-### <a name="desc"></a>**gn desc <out_dir> <label or pattern> [<what to show>] [\--blame] "**
-#### **[\--format=json]**
-
-```
- Displays information about a given target or config. The build build
- parameters will be taken for the build in the given <out_dir>.
-
- The <label or pattern> can be a target label, a config label, or a label
- pattern (see "gn help label_pattern"). A label pattern will only match
- targets.
-```
-
-#### **Possibilities for <what to show>**
-
-```
- (If unspecified an overall summary will be displayed.)
-
- all_dependent_configs
- allow_circular_includes_from
- arflags [--blame]
- args
- cflags [--blame]
- cflags_cc [--blame]
- cflags_cxx [--blame]
- check_includes
- configs [--tree] (see below)
- defines [--blame]
- depfile
- deps [--all] [--tree] (see below)
- include_dirs [--blame]
- inputs
- ldflags [--blame]
- lib_dirs
- libs
- outputs
- public_configs
- public
- script
- sources
- testonly
- visibility
-
- runtime_deps
- Compute all runtime deps for the given target. This is a computed list
- and does not correspond to any GN variable, unlike most other values
- here.
-
- The output is a list of file names relative to the build directory. See
- "gn help runtime_deps" for how this is computed. This also works with
- "--blame" to see the source of the dependency.
-```
-
-#### **Shared flags**
-```
- --all-toolchains
- Normally only inputs in the default toolchain will be included.
- This switch will turn on matching all toolchains.
-
- For example, a file is in a target might be compiled twice:
- once in the default toolchain and once in a secondary one. Without
- this flag, only the default toolchain one will be matched by
- wildcards. With this flag, both will be matched.
-
- --format=json
- Format the output as JSON instead of text.
-```
-
-#### **Target flags**
-
-```
- --blame
- Used with any value specified on a config, this will name the config that
- cause that target to get the flag. This doesn't currently work for libs
- and lib_dirs because those are inherited and are more complicated to
- figure out the blame (patches welcome).
-```
-
-#### **Configs**
-
-```
- The "configs" section will list all configs that apply. For targets this will
- include configs specified in the "configs" variable of the target, and also
- configs pushed onto this target via public or "all dependent" configs.
-
- Configs can have child configs. Specifying --tree will show the hierarchy.
-```
-
-#### **Printing outputs**
-
-```
- The "outputs" section will list all outputs that apply, including the outputs
- computed from the tool definition (eg for "executable", "static_library", ...
- targets).
-```
-
-#### **Printing deps**
-
-```
- Deps will include all public, private, and data deps (TODO this could be
- clarified and enhanced) sorted in order applying. The following may be used:
-
- --all
- Collects all recursive dependencies and prints a sorted flat list. Also
- usable with --tree (see below).
- --as=(buildfile|label|output)
- How to print targets.
-
- buildfile
- Prints the build files where the given target was declared as
- file names.
- label (default)
- Prints the label of the target.
- output
- Prints the first output file for the target relative to the
- root build directory.
-
- --testonly=(true|false)
- Restrict outputs to targets with the testonly flag set
- accordingly. When unspecified, the target's testonly flags are
- ignored.
-
- --tree
- Print a dependency tree. By default, duplicates will be elided with "..."
- but when --all and -tree are used together, no eliding will be performed.
-
- The "deps", "public_deps", and "data_deps" will all be included in the
- tree.
-
- Tree output can not be used with the filtering or output flags: --as,
- --type, --testonly.
- --type=(action|copy|executable|group|loadable_module|shared_library|
- source_set|static_library)
- Restrict outputs to targets matching the given type. If
- unspecified, no filtering will be performed.
-```
-
-#### **Note**
-
-```
- This command will show the full name of directories and source files, but
- when directories and source paths are written to the build file, they will be
- adjusted to be relative to the build directory. So the values for paths
- displayed by this command won't match (but should mean the same thing).
-```
-
-#### **Examples**
-
-```
- gn desc out/Debug //base:base
- Summarizes the given target.
-
- gn desc out/Foo :base_unittests deps --tree
- Shows a dependency tree of the "base_unittests" project in
- the current directory.
-
- gn desc out/Debug //base defines --blame
- Shows defines set for the //base:base target, annotated by where
- each one was set from.
-```
-### <a name="format"></a>**gn format [\--dump-tree] (\--stdin | <build_file>)**
-
-```
- Formats .gn file to a standard format.
-
- The contents of some lists ('sources', 'deps', etc.) will be sorted to a
- canonical order. To suppress this, you can add a comment of the form "#
- NOSORT" immediately preceding the assignment. e.g.
-
- # NOSORT
- sources = [
- "z.cc",
- "a.cc",
- ]
-```
-
-#### **Arguments**
-
-```
- --dry-run
- Does not change or output anything, but sets the process exit code based
- on whether output would be different than what's on disk. This is useful
- for presubmit/lint-type checks.
- - Exit code 0: successful format, matches on disk.
- - Exit code 1: general failure (parse error, etc.)
- - Exit code 2: successful format, but differs from on disk.
-
- --dump-tree
- For debugging, dumps the parse tree to stdout and does not update the
- file or print formatted output.
-
- --stdin
- Read input from stdin and write to stdout rather than update a file
- in-place.
-```
-
-#### **Examples**
-```
- gn format //some/BUILD.gn
- gn format some\\BUILD.gn
- gn format /abspath/some/BUILD.gn
- gn format --stdin
-```
-### <a name="gen"></a>**gn gen [\--check] [<ide options>] <out_dir>**
-
-```
- Generates ninja files from the current tree and puts them in the given output
- directory.
-
- The output directory can be a source-repo-absolute path name such as:
- //out/foo
- Or it can be a directory relative to the current directory such as:
- out/foo
-
- "gn gen --check" is the same as running "gn check". See "gn help check"
- for documentation on that mode.
-
- See "gn help switches" for the common command-line switches.
-```
-
-#### **IDE options**
-
-```
- GN optionally generates files for IDE. Possibilities for <ide options>
-
- --ide=<ide_name>
- Generate files for an IDE. Currently supported values:
- "eclipse" - Eclipse CDT settings file.
- "vs" - Visual Studio project/solution files.
- (default Visual Studio version: 2017)
- "vs2013" - Visual Studio 2013 project/solution files.
- "vs2015" - Visual Studio 2015 project/solution files.
- "vs2017" - Visual Studio 2017 project/solution files.
- "xcode" - Xcode workspace/solution files.
- "qtcreator" - QtCreator project files.
- "json" - JSON file containing target information
-
- --filters=<path_prefixes>
- Semicolon-separated list of label patterns used to limit the set of
- generated projects (see "gn help label_pattern"). Only matching targets
- and their dependencies will be included in the solution. Only used for
- Visual Studio, Xcode and JSON.
-```
-
-#### **Visual Studio Flags**
-
-```
- --sln=<file_name>
- Override default sln file name ("all"). Solution file is written to the
- root build directory.
-
- --no-deps
- Don't include targets dependencies to the solution. Changes the way how
- --filters option works. Only directly matching targets are included.
-
- --winsdk=<sdk_version>
- Use the specified Windows 10 SDK version to generate project files.
- As an example, "10.0.15063.0" can be specified to use Creators Update SDK
- instead of the default one.
-
- --ninja-extra-args=<string>
- This string is passed without any quoting to the ninja invocation
- command-line. Can be used to configure ninja flags, like "-j".
-```
-
-#### **Xcode Flags**
-
-```
- --workspace=<file_name>
- Override defaut workspace file name ("all"). The workspace file is
- written to the root build directory.
-
- --ninja-extra-args=<string>
- This string is passed without any quoting to the ninja invocation
- command-line. Can be used to configure ninja flags, like "-j".
-
- --root-target=<target_name>
- Name of the target corresponding to "All" target in Xcode. If unset,
- "All" invokes ninja without any target and builds everything.
-```
-
-#### **QtCreator Flags**
-
-```
- --root-target=<target_name>
- Name of the root target for which the QtCreator project will be generated
- to contain files of it and its dependencies. If unset, the whole build
- graph will be emitted.
-```
-
-#### **Eclipse IDE Support**
-
-```
- GN DOES NOT generate Eclipse CDT projects. Instead, it generates a settings
- file which can be imported into an Eclipse CDT project. The XML file contains
- a list of include paths and defines. Because GN does not generate a full
- .cproject definition, it is not possible to properly define includes/defines
- for each file individually. Instead, one set of includes/defines is generated
- for the entire project. This works fairly well but may still result in a few
- indexer issues here and there.
-```
-
-#### **Generic JSON Output**
-
-```
- Dumps target information to a JSON file and optionally invokes a
- python script on the generated file. See the comments at the beginning
- of json_project_writer.cc and desc_builder.cc for an overview of the JSON
- file format.
-
- --json-file-name=<json_file_name>
- Overrides default file name (project.json) of generated JSON file.
-
- --json-ide-script=<path_to_python_script>
- Executes python script after the JSON file is generated. Path can be
- project absolute (//), system absolute (/) or relative, in which case the
- output directory will be base. Path to generated JSON file will be first
- argument when invoking script.
-
- --json-ide-script-args=<argument>
- Optional second argument that will passed to executed script.
-```
-### <a name="help"></a>**gn help <anything>**
-
-```
- Yo dawg, I heard you like help on your help so I put help on the help in the
- help.
-
- You can also use "all" as the parameter to get all help at once.
-```
-
-#### **Switches**
-
-```
- --markdown
- Format output in markdown syntax.
-```
-
-#### **Example**
-
-```
- gn help --markdown all
- Dump all help to stdout in markdown format.
-```
-### <a name="ls"></a>**gn ls <out_dir> [<label_pattern>] [\--all-toolchains] [\--as=...]**
-```
- [--type=...] [--testonly=...]
-
- Lists all targets matching the given pattern for the given build directory.
- By default, only targets in the default toolchain will be matched unless a
- toolchain is explicitly supplied.
-
- If the label pattern is unspecified, list all targets. The label pattern is
- not a general regular expression (see "gn help label_pattern"). If you need
- more complex expressions, pipe the result through grep.
-```
-
-#### **Options**
-
-```
- --as=(buildfile|label|output)
- How to print targets.
-
- buildfile
- Prints the build files where the given target was declared as
- file names.
- label (default)
- Prints the label of the target.
- output
- Prints the first output file for the target relative to the
- root build directory.
-
- --all-toolchains
- Normally only inputs in the default toolchain will be included.
- This switch will turn on matching all toolchains.
-
- For example, a file is in a target might be compiled twice:
- once in the default toolchain and once in a secondary one. Without
- this flag, only the default toolchain one will be matched by
- wildcards. With this flag, both will be matched.
-
- --testonly=(true|false)
- Restrict outputs to targets with the testonly flag set
- accordingly. When unspecified, the target's testonly flags are
- ignored.
-
- --type=(action|copy|executable|group|loadable_module|shared_library|
- source_set|static_library)
- Restrict outputs to targets matching the given type. If
- unspecified, no filtering will be performed.
-```
-
-#### **Examples**
-
-```
- gn ls out/Debug
- Lists all targets in the default toolchain.
-
- gn ls out/Debug "//base/*"
- Lists all targets in the directory base and all subdirectories.
-
- gn ls out/Debug "//base:*"
- Lists all targets defined in //base/BUILD.gn.
-
- gn ls out/Debug //base --as=output
- Lists the build output file for //base:base
-
- gn ls out/Debug --type=executable
- Lists all executables produced by the build.
-
- gn ls out/Debug "//base/*" --as=output | xargs ninja -C out/Debug
- Builds all targets in //base and all subdirectories.
-
- gn ls out/Debug //base --all-toolchains
- Lists all variants of the target //base:base (it may be referenced
- in multiple toolchains).
-```
-### <a name="path"></a>**gn path <out_dir> <target_one> <target_two>**
-
-```
- Finds paths of dependencies between two targets. Each unique path will be
- printed in one group, and groups will be separate by newlines. The two
- targets can appear in either order (paths will be found going in either
- direction).
-
- By default, a single path will be printed. If there is a path with only
- public dependencies, the shortest public path will be printed. Otherwise, the
- shortest path using either public or private dependencies will be printed. If
- --with-data is specified, data deps will also be considered. If there are
- multiple shortest paths, an arbitrary one will be selected.
-```
-
-#### **Interesting paths**
-
-```
- In a large project, there can be 100's of millions of unique paths between a
- very high level and a common low-level target. To make the output more useful
- (and terminate in a reasonable time), GN will not revisit sub-paths
- previously known to lead to the target.
-```
-
-#### **Options**
-
-```
- --all
- Prints all "interesting" paths found rather than just the first one.
- Public paths will be printed first in order of increasing length, followed
- by non-public paths in order of increasing length.
-
- --public
- Considers only public paths. Can't be used with --with-data.
-
- --with-data
- Additionally follows data deps. Without this flag, only public and private
- linked deps will be followed. Can't be used with --public.
-```
-
-#### **Example**
-
-```
- gn path out/Default //base //tools/gn
-```
-### <a name="refs"></a>**gn refs <out_dir> (<label_pattern>|<label>|<file>|@<response_file>)***
-```
- [--all] [--all-toolchains] [--as=...] [--testonly=...] [--type=...]
-
- Finds reverse dependencies (which targets reference something). The input is
- a list containing:
-
- - Target label: The result will be which targets depend on it.
-
- - Config label: The result will be which targets list the given config in
- its "configs" or "public_configs" list.
-
- - Label pattern: The result will be which targets depend on any target
- matching the given pattern. Patterns will not match configs. These are not
- general regular expressions, see "gn help label_pattern" for details.
-
- - File name: The result will be which targets list the given file in its
- "inputs", "sources", "public", "data", or "outputs". Any input that does
- not contain wildcards and does not match a target or a config will be
- treated as a file.
-
- - Response file: If the input starts with an "@", it will be interpreted as
- a path to a file containing a list of labels or file names, one per line.
- This allows us to handle long lists of inputs without worrying about
- command line limits.
-```
-
-#### **Options**
-
-```
- --all
- When used without --tree, will recurse and display all unique
- dependencies of the given targets. For example, if the input is a target,
- this will output all targets that depend directly or indirectly on the
- input. If the input is a file, this will output all targets that depend
- directly or indirectly on that file.
-
- When used with --tree, turns off eliding to show a complete tree.
- --all-toolchains
- Normally only inputs in the default toolchain will be included.
- This switch will turn on matching all toolchains.
-
- For example, a file is in a target might be compiled twice:
- once in the default toolchain and once in a secondary one. Without
- this flag, only the default toolchain one will be matched by
- wildcards. With this flag, both will be matched.
-
- --as=(buildfile|label|output)
- How to print targets.
-
- buildfile
- Prints the build files where the given target was declared as
- file names.
- label (default)
- Prints the label of the target.
- output
- Prints the first output file for the target relative to the
- root build directory.
-
- -q
- Quiet. If nothing matches, don't print any output. Without this option, if
- there are no matches there will be an informational message printed which
- might interfere with scripts processing the output.
- --testonly=(true|false)
- Restrict outputs to targets with the testonly flag set
- accordingly. When unspecified, the target's testonly flags are
- ignored.
-
- --tree
- Outputs a reverse dependency tree from the given target. Duplicates will
- be elided. Combine with --all to see a full dependency tree.
-
- Tree output can not be used with the filtering or output flags: --as,
- --type, --testonly.
- --type=(action|copy|executable|group|loadable_module|shared_library|
- source_set|static_library)
- Restrict outputs to targets matching the given type. If
- unspecified, no filtering will be performed.
-```
-
-#### **Examples (target input)**
-
-```
- gn refs out/Debug //tools/gn:gn
- Find all targets depending on the given exact target name.
-
- gn refs out/Debug //base:i18n --as=buildfiles | xargs gvim
- Edit all .gn files containing references to //base:i18n
-
- gn refs out/Debug //base --all
- List all targets depending directly or indirectly on //base:base.
-
- gn refs out/Debug "//base/*"
- List all targets depending directly on any target in //base or
- its subdirectories.
-
- gn refs out/Debug "//base:*"
- List all targets depending directly on any target in
- //base/BUILD.gn.
-
- gn refs out/Debug //base --tree
- Print a reverse dependency tree of //base:base
-```
-
-#### **Examples (file input)**
-
-```
- gn refs out/Debug //base/macros.h
- Print target(s) listing //base/macros.h as a source.
-
- gn refs out/Debug //base/macros.h --tree
- Display a reverse dependency tree to get to the given file. This
- will show how dependencies will reference that file.
-
- gn refs out/Debug //base/macros.h //base/at_exit.h --all
- Display all unique targets with some dependency path to a target
- containing either of the given files as a source.
-
- gn refs out/Debug //base/macros.h --testonly=true --type=executable
- --all --as=output
- Display the executable file names of all test executables
- potentially affected by a change to the given file.
-```
-## <a name="targets"></a>Target declarations
-
-### <a name="action"></a>**action**: Declare a target that runs a script a single time.
-
-```
- This target type allows you to run a script a single time to produce one or
- more output files. If you want to run a script once for each of a set of
- input files, see "gn help action_foreach".
-```
-
-#### **Inputs**
-
-```
- In an action the "sources" and "inputs" are treated the same: they're both
- input dependencies on script execution with no special handling. If you want
- to pass the sources to your script, you must do so explicitly by including
- them in the "args". Note also that this means there is no special handling of
- paths since GN doesn't know which of the args are paths and not. You will
- want to use rebase_path() to convert paths to be relative to the
- root_build_dir.
-
- You can dynamically write input dependencies (for incremental rebuilds if an
- input file changes) by writing a depfile when the script is run (see "gn help
- depfile"). This is more flexible than "inputs".
-
- If the command line length is very long, you can use response files to pass
- args to your script. See "gn help response_file_contents".
-
- It is recommended you put inputs to your script in the "sources" variable,
- and stuff like other Python files required to run your script in the "inputs"
- variable.
-
- The "deps" and "public_deps" for an action will always be
- completed before any part of the action is run so it can depend on
- the output of previous steps. The "data_deps" will be built if the
- action is built, but may not have completed before all steps of the
- action are started. This can give additional parallelism in the build
- for runtime-only dependencies.
-```
-
-#### **Outputs**
-
-```
- You should specify files created by your script by specifying them in the
- "outputs".
-
- The script will be executed with the given arguments with the current
- directory being that of the root build directory. If you pass files
- to your script, see "gn help rebase_path" for how to convert
- file names to be relative to the build directory (file names in the
- sources, outputs, and inputs will be all treated as relative to the
- current build file and converted as needed automatically).
-```
-
-#### **File name handling**
-
-```
- All output files must be inside the output directory of the build.
- You would generally use |$target_out_dir| or |$target_gen_dir| to
- reference the output or generated intermediate file directories,
- respectively.
-```
-
-#### **Variables**
-
-```
- args, data, data_deps, depfile, deps, inputs, outputs*, pool,
- response_file_contents, script*, sources
- * = required
-```
-
-#### **Example**
-
-```
- action("run_this_guy_once") {
- script = "doprocessing.py"
- sources = [ "my_configuration.txt" ]
- outputs = [ "$target_gen_dir/insightful_output.txt" ]
-
- # Our script imports this Python file so we want to rebuild if it changes.
- inputs = [ "helper_library.py" ]
-
- # Note that we have to manually pass the sources to our script if the
- # script needs them as inputs.
- args = [ "--out", rebase_path(target_gen_dir, root_build_dir) ] +
- rebase_path(sources, root_build_dir)
- }
-```
-### <a name="action_foreach"></a>**action_foreach**: Declare a target that runs a script over a set of files.
-
-```
- This target type allows you to run a script once-per-file over a set of
- sources. If you want to run a script once that takes many files as input, see
- "gn help action".
-```
-
-#### **Inputs**
-
-```
- The script will be run once per file in the "sources" variable. The "outputs"
- variable should specify one or more files with a source expansion pattern in
- it (see "gn help source_expansion"). The output file(s) for each script
- invocation should be unique. Normally you use "{{source_name_part}}" in each
- output file.
-
- If your script takes additional data as input, such as a shared configuration
- file or a Python module it uses, those files should be listed in the "inputs"
- variable. These files are treated as dependencies of each script invocation.
-
- If the command line length is very long, you can use response files to pass
- args to your script. See "gn help response_file_contents".
-
- You can dynamically write input dependencies (for incremental rebuilds if an
- input file changes) by writing a depfile when the script is run (see "gn help
- depfile"). This is more flexible than "inputs".
-
- The "deps" and "public_deps" for an action will always be
- completed before any part of the action is run so it can depend on
- the output of previous steps. The "data_deps" will be built if the
- action is built, but may not have completed before all steps of the
- action are started. This can give additional parallelism in the build
- for runtime-only dependencies.
-```
-
-#### **Outputs**
-
-```
- The script will be executed with the given arguments with the current
- directory being that of the root build directory. If you pass files
- to your script, see "gn help rebase_path" for how to convert
- file names to be relative to the build directory (file names in the
- sources, outputs, and inputs will be all treated as relative to the
- current build file and converted as needed automatically).
-```
-
-#### **File name handling**
-
-```
- All output files must be inside the output directory of the build.
- You would generally use |$target_out_dir| or |$target_gen_dir| to
- reference the output or generated intermediate file directories,
- respectively.
-```
-
-#### **Variables**
-
-```
- args, data, data_deps, depfile, deps, inputs, outputs*, pool,
- response_file_contents, script*, sources*
- * = required
-```
-
-#### **Example**
-
-```
- # Runs the script over each IDL file. The IDL script will generate both a .cc
- # and a .h file for each input.
- action_foreach("my_idl") {
- script = "idl_processor.py"
- sources = [ "foo.idl", "bar.idl" ]
-
- # Our script reads this file each time, so we need to list is as a
- # dependency so we can rebuild if it changes.
- inputs = [ "my_configuration.txt" ]
-
- # Transformation from source file name to output file names.
- outputs = [ "$target_gen_dir/{{source_name_part}}.h",
- "$target_gen_dir/{{source_name_part}}.cc" ]
-
- # Note that since "args" is opaque to GN, if you specify paths here, you
- # will need to convert it to be relative to the build directory using
- # rebase_path().
- args = [
- "{{source}}",
- "-o",
- rebase_path(relative_target_gen_dir, root_build_dir) +
- "/{{source_name_part}}.h" ]
- }
-```
-### <a name="bundle_data"></a>**bundle_data**: [iOS/macOS] Declare a target without output.
-
-```
- This target type allows to declare data that is required at runtime. It is
- used to inform "create_bundle" targets of the files to copy into generated
- bundle, see "gn help create_bundle" for help.
-
- The target must define a list of files as "sources" and a single "outputs".
- If there are multiple files, source expansions must be used to express the
- output. The output must reference a file inside of {{bundle_root_dir}}.
-
- This target can be used on all platforms though it is designed only to
- generate iOS/macOS bundle. In cross-platform projects, it is advised to put it
- behind iOS/macOS conditionals.
-
- See "gn help create_bundle" for more information.
-```
-
-#### **Variables**
-
-```
- sources*, outputs*, deps, data_deps, public_deps, visibility
- * = required
-```
-
-#### **Examples**
-
-```
- bundle_data("icudata") {
- sources = [ "sources/data/in/icudtl.dat" ]
- outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
- }
-
- bundle_data("base_unittests_bundle_data]") {
- sources = [ "test/data" ]
- outputs = [
- "{{bundle_resources_dir}}/{{source_root_relative_dir}}/" +
- "{{source_file_part}}"
- ]
- }
-
- bundle_data("material_typography_bundle_data") {
- sources = [
- "src/MaterialTypography.bundle/Roboto-Bold.ttf",
- "src/MaterialTypography.bundle/Roboto-Italic.ttf",
- "src/MaterialTypography.bundle/Roboto-Regular.ttf",
- "src/MaterialTypography.bundle/Roboto-Thin.ttf",
- ]
- outputs = [
- "{{bundle_resources_dir}}/MaterialTypography.bundle/"
- "{{source_file_part}}"
- ]
- }
-```
-### <a name="copy"></a>**copy**: Declare a target that copies files.
-
-#### **File name handling**
-
-```
- All output files must be inside the output directory of the build. You would
- generally use |$target_out_dir| or |$target_gen_dir| to reference the output
- or generated intermediate file directories, respectively.
-
- Both "sources" and "outputs" must be specified. Sources can include as many
- files as you want, but there can only be one item in the outputs list (plural
- is used for the name for consistency with other target types).
-
- If there is more than one source file, your output name should specify a
- mapping from each source file to an output file name using source expansion
- (see "gn help source_expansion"). The placeholders will look like
- "{{source_name_part}}", for example.
-```
-
-#### **Examples**
-
-```
- # Write a rule that copies a checked-in DLL to the output directory.
- copy("mydll") {
- sources = [ "mydll.dll" ]
- outputs = [ "$target_out_dir/mydll.dll" ]
- }
-
- # Write a rule to copy several files to the target generated files directory.
- copy("myfiles") {
- sources = [ "data1.dat", "data2.dat", "data3.dat" ]
-
- # Use source expansion to generate output files with the corresponding file
- # names in the gen dir. This will just copy each file.
- outputs = [ "$target_gen_dir/{{source_file_part}}" ]
- }
-```
-### <a name="create_bundle"></a>**create_bundle**: [ios/macOS] Build an iOS or macOS bundle.
-
-```
- This target generates an iOS or macOS bundle (which is a directory with a
- well-know structure). This target does not define any sources, instead they
- are computed from all "bundle_data" target this one depends on transitively
- (the recursion stops at "create_bundle" targets).
-
- The "bundle_*_dir" properties must be defined. They will be used for the
- expansion of {{bundle_*_dir}} rules in "bundle_data" outputs.
-
- This target can be used on all platforms though it is designed only to
- generate iOS or macOS bundle. In cross-platform projects, it is advised to put
- it behind iOS/macOS conditionals.
-
- If a create_bundle is specified as a data_deps for another target, the bundle
- is considered a leaf, and its public and private dependencies will not
- contribute to any data or data_deps. Required runtime dependencies should be
- placed in the bundle. A create_bundle can declare its own explicit data and
- data_deps, however.
-```
-
-#### **Code signing**
-
-```
- Some bundle needs to be code signed as part of the build (on iOS all
- application needs to be code signed to run on a device). The code signature
- can be configured via the code_signing_script variable.
-
- If set, code_signing_script is the path of a script that invoked after all
- files have been moved into the bundle. The script must not change any file in
- the bundle, but may add new files.
-
- If code_signing_script is defined, then code_signing_outputs must also be
- defined and non-empty to inform when the script needs to be re-run. The
- code_signing_args will be passed as is to the script (so path have to be
- rebased) and additional inputs may be listed with the variable
- code_signing_sources.
-```
-
-#### **Variables**
-
-```
- bundle_root_dir*, bundle_contents_dir*, bundle_resources_dir*,
- bundle_executable_dir*, bundle_plugins_dir*, bundle_deps_filter, deps,
- data_deps, public_deps, visibility, product_type, code_signing_args,
- code_signing_script, code_signing_sources, code_signing_outputs,
- xcode_extra_attributes, xcode_test_application_name, partial_info_plist
- * = required
-```
-
-#### **Example**
-
-```
- # Defines a template to create an application. On most platform, this is just
- # an alias for an "executable" target, but on iOS/macOS, it builds an
- # application bundle.
- template("app") {
- if (!is_ios && !is_mac) {
- executable(target_name) {
- forward_variables_from(invoker, "*")
- }
- } else {
- app_name = target_name
- gen_path = target_gen_dir
-
- action("${app_name}_generate_info_plist") {
- script = [ "//build/ios/ios_gen_plist.py" ]
- sources = [ "templates/Info.plist" ]
- outputs = [ "$gen_path/Info.plist" ]
- args = rebase_path(sources, root_build_dir) +
- rebase_path(outputs, root_build_dir)
- }
-
- bundle_data("${app_name}_bundle_info_plist") {
- deps = [ ":${app_name}_generate_info_plist" ]
- sources = [ "$gen_path/Info.plist" ]
- outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
- }
-
- executable("${app_name}_generate_executable") {
- forward_variables_from(invoker, "*", [
- "output_name",
- "visibility",
- ])
- output_name =
- rebase_path("$gen_path/$app_name", root_build_dir)
- }
-
- code_signing =
- defined(invoker.code_signing) && invoker.code_signing
-
- if (is_ios && !code_signing) {
- bundle_data("${app_name}_bundle_executable") {
- deps = [ ":${app_name}_generate_executable" ]
- sources = [ "$gen_path/$app_name" ]
- outputs = [ "{{bundle_executable_dir}}/$app_name" ]
- }
- }
-
- create_bundle("${app_name}.app") {
- product_type = "com.apple.product-type.application"
-
- if (is_ios) {
- bundle_root_dir = "${root_build_dir}/$target_name"
- bundle_contents_dir = bundle_root_dir
- bundle_resources_dir = bundle_contents_dir
- bundle_executable_dir = bundle_contents_dir
- bundle_plugins_dir = "${bundle_contents_dir}/Plugins"
-
- extra_attributes = {
- ONLY_ACTIVE_ARCH = "YES"
- DEBUG_INFORMATION_FORMAT = "dwarf"
- }
- } else {
- bundle_root_dir = "${root_build_dir}/target_name"
- bundle_contents_dir = "${bundle_root_dir}/Contents"
- bundle_resources_dir = "${bundle_contents_dir}/Resources"
- bundle_executable_dir = "${bundle_contents_dir}/MacOS"
- bundle_plugins_dir = "${bundle_contents_dir}/Plugins"
- }
- deps = [ ":${app_name}_bundle_info_plist" ]
- if (is_ios && code_signing) {
- deps += [ ":${app_name}_generate_executable" ]
- code_signing_script = "//build/config/ios/codesign.py"
- code_signing_sources = [
- invoker.entitlements_path,
- "$target_gen_dir/$app_name",
- ]
- code_signing_outputs = [
- "$bundle_root_dir/$app_name",
- "$bundle_root_dir/_CodeSignature/CodeResources",
- "$bundle_root_dir/embedded.mobileprovision",
- "$target_gen_dir/$app_name.xcent",
- ]
- code_signing_args = [
- "-i=" + ios_code_signing_identity,
- "-b=" + rebase_path(
- "$target_gen_dir/$app_name", root_build_dir),
- "-e=" + rebase_path(
- invoker.entitlements_path, root_build_dir),
- "-e=" + rebase_path(
- "$target_gen_dir/$app_name.xcent", root_build_dir),
- rebase_path(bundle_root_dir, root_build_dir),
- ]
- } else {
- deps += [ ":${app_name}_bundle_executable" ]
- }
- }
- }
- }
-```
-### <a name="executable"></a>**executable**: Declare an executable target.
-
-#### **Variables**
-
-```
- Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
- asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
- libs, precompiled_header, precompiled_source
- Deps: data_deps, deps, public_deps
- Dependent configs: all_dependent_configs, public_configs
- General: check_includes, configs, data, friend, inputs, output_name,
- output_extension, public, sources, testonly, visibility
-```
-### <a name="group"></a>**group**: Declare a named group of targets.
-
-```
- This target type allows you to create meta-targets that just collect a set of
- dependencies into one named target. Groups can additionally specify configs
- that apply to their dependents.
-```
-
-#### **Variables**
-
-```
- Deps: data_deps, deps, public_deps
- Dependent configs: all_dependent_configs, public_configs
-```
-
-#### **Example**
-
-```
- group("all") {
- deps = [
- "//project:runner",
- "//project:unit_tests",
- ]
- }
-```
-### <a name="loadable_module"></a>**loadable_module**: Declare a loadable module target.
-
-```
- This target type allows you to create an object file that is (and can only
- be) loaded and unloaded at runtime.
-
- A loadable module will be specified on the linker line for targets listing
- the loadable module in its "deps". If you don't want this (if you don't need
- to dynamically load the library at runtime), then you should use a
- "shared_library" target type instead.
-```
-
-#### **Variables**
-
-```
- Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
- asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
- libs, precompiled_header, precompiled_source
- Deps: data_deps, deps, public_deps
- Dependent configs: all_dependent_configs, public_configs
- General: check_includes, configs, data, friend, inputs, output_name,
- output_extension, public, sources, testonly, visibility
-```
-### <a name="shared_library"></a>**shared_library**: Declare a shared library target.
-
-```
- A shared library will be specified on the linker line for targets listing the
- shared library in its "deps". If you don't want this (say you dynamically
- load the library at runtime), then you should depend on the shared library
- via "data_deps" or, on Darwin platforms, use a "loadable_module" target type
- instead.
-```
-
-#### **Variables**
-
-```
- Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
- asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
- libs, precompiled_header, precompiled_source
- Deps: data_deps, deps, public_deps
- Dependent configs: all_dependent_configs, public_configs
- General: check_includes, configs, data, friend, inputs, output_name,
- output_extension, public, sources, testonly, visibility
-```
-### <a name="source_set"></a>**source_set**: Declare a source set target.
-
-```
- A source set is a collection of sources that get compiled, but are not linked
- to produce any kind of library. Instead, the resulting object files are
- implicitly added to the linker line of all targets that depend on the source
- set.
-
- In most cases, a source set will behave like a static library, except no
- actual library file will be produced. This will make the build go a little
- faster by skipping creation of a large static library, while maintaining the
- organizational benefits of focused build targets.
-
- The main difference between a source set and a static library is around
- handling of exported symbols. Most linkers assume declaring a function
- exported means exported from the static library. The linker can then do dead
- code elimination to delete code not reachable from exported functions.
-
- A source set will not do this code elimination since there is no link step.
- This allows you to link many sources sets into a shared library and have the
- "exported symbol" notation indicate "export from the final shared library and
- not from the intermediate targets." There is no way to express this concept
- when linking multiple static libraries into a shared library.
-```
-
-#### **Variables**
-
-```
- Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
- asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
- libs, precompiled_header, precompiled_source
- Deps: data_deps, deps, public_deps
- Dependent configs: all_dependent_configs, public_configs
- General: check_includes, configs, data, friend, inputs, output_name,
- output_extension, public, sources, testonly, visibility
-```
-### <a name="static_library"></a>**static_library**: Declare a static library target.
-
-```
- Make a ".a" / ".lib" file.
-
- If you only need the static library for intermediate results in the build,
- you should consider a source_set instead since it will skip the (potentially
- slow) step of creating the intermediate library file.
-```
-
-#### **Variables**
-
-```
- complete_static_lib
- Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
- asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
- libs, precompiled_header, precompiled_source
- Deps: data_deps, deps, public_deps
- Dependent configs: all_dependent_configs, public_configs
- General: check_includes, configs, data, friend, inputs, output_name,
- output_extension, public, sources, testonly, visibility
-```
-### <a name="target"></a>**target**: Declare an target with the given programmatic type.
-
-```
- target(target_type_string, target_name_string) { ... }
-
- The target() function is a way to invoke a built-in target or template with a
- type determined at runtime. This is useful for cases where the type of a
- target might not be known statically.
-
- Only templates and built-in target functions are supported for the
- target_type_string parameter. Arbitrary functions, configs, and toolchains
- are not supported.
-
- The call:
- target("source_set", "doom_melon") {
- Is equivalent to:
- source_set("doom_melon") {
-```
-
-#### **Example**
-
-```
- if (foo_build_as_shared) {
- my_type = "shared_library"
- } else {
- my_type = "source_set"
- }
-
- target(my_type, "foo") {
- ...
- }
-```
-## <a name="functions"></a>Buildfile functions
-
-### <a name="assert"></a>**assert**: Assert an expression is true at generation time.
-
-```
- assert(<condition> [, <error string>])
-
- If the condition is false, the build will fail with an error. If the
- optional second argument is provided, that string will be printed
- with the error message.
-```
-
-#### **Examples**
-
-```
- assert(is_win)
- assert(defined(sources), "Sources must be defined");
-```
-### <a name="config"></a>**config**: Defines a configuration object.
-
-```
- Configuration objects can be applied to targets and specify sets of compiler
- flags, includes, defines, etc. They provide a way to conveniently group sets
- of this configuration information.
-
- A config is referenced by its label just like a target.
-
- The values in a config are additive only. If you want to remove a flag you
- need to remove the corresponding config that sets it. The final set of flags,
- defines, etc. for a target is generated in this order:
-
- 1. The values specified directly on the target (rather than using a config.
- 2. The configs specified in the target's "configs" list, in order.
- 3. Public_configs from a breadth-first traversal of the dependency tree in
- the order that the targets appear in "deps".
- 4. All dependent configs from a breadth-first traversal of the dependency
- tree in the order that the targets appear in "deps".
-```
-
-#### **Variables valid in a config definition**
-```
- Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,
- asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,
- libs, precompiled_header, precompiled_source
- Nested configs: configs
-```
-
-#### **Variables on a target used to apply configs**
-
-```
- all_dependent_configs, configs, public_configs
-```
-
-#### **Example**
-
-```
- config("myconfig") {
- includes = [ "include/common" ]
- defines = [ "ENABLE_DOOM_MELON" ]
- }
-
- executable("mything") {
- configs = [ ":myconfig" ]
- }
-```
-### <a name="declare_args"></a>**declare_args**: Declare build arguments.
-
-```
- Introduces the given arguments into the current scope. If they are not
- specified on the command line or in a toolchain's arguments, the default
- values given in the declare_args block will be used. However, these defaults
- will not override command-line values.
-
- See also "gn help buildargs" for an overview.
-
- The precise behavior of declare args is:
-
- 1. The declare_args() block executes. Any variable defined in the enclosing
- scope is available for reading, but any variable defined earlier in
- the current scope is not (since the overrides haven't been applied yet).
-
- 2. At the end of executing the block, any variables set within that scope
- are saved globally as build arguments, with their current values being
- saved as the "default value" for that argument.
-
- 3. User-defined overrides are applied. Anything set in "gn args" now
- overrides any default values. The resulting set of variables is promoted
- to be readable from the following code in the file.
-
- This has some ramifications that may not be obvious:
-
- - You should not perform difficult work inside a declare_args block since
- this only sets a default value that may be discarded. In particular,
- don't use the result of exec_script() to set the default value. If you
- want to have a script-defined default, set some default "undefined" value
- like [], "", or -1, and after the declare_args block, call exec_script if
- the value is unset by the user.
-
- - Because you cannot read the value of a variable defined in the same
- block, if you need to make the default value of one arg depend
- on the possibly-overridden value of another, write two separate
- declare_args() blocks:
-
- declare_args() {
- enable_foo = true
- }
- declare_args() {
- # Bar defaults to same user-overridden state as foo.
- enable_bar = enable_foo
- }
-```
-
-#### **Example**
-
-```
- declare_args() {
- enable_teleporter = true
- enable_doom_melon = false
- }
-
- If you want to override the (default disabled) Doom Melon:
- gn --args="enable_doom_melon=true enable_teleporter=true"
- This also sets the teleporter, but it's already defaulted to on so it will
- have no effect.
-```
-### <a name="defined"></a>**defined**: Returns whether an identifier is defined.
-
-```
- Returns true if the given argument is defined. This is most useful in
- templates to assert that the caller set things up properly.
-
- You can pass an identifier:
- defined(foo)
- which will return true or false depending on whether foo is defined in the
- current scope.
-
- You can also check a named scope:
- defined(foo.bar)
- which will return true or false depending on whether bar is defined in the
- named scope foo. It will throw an error if foo is not defined or is not a
- scope.
-```
-
-#### **Example**
-
-```
- template("mytemplate") {
- # To help users call this template properly...
- assert(defined(invoker.sources), "Sources must be defined")
-
- # If we want to accept an optional "values" argument, we don't
- # want to dereference something that may not be defined.
- if (defined(invoker.values)) {
- values = invoker.values
- } else {
- values = "some default value"
- }
- }
-```
-### <a name="exec_script"></a>**exec_script**: Synchronously run a script and return the output.
-
-```
- exec_script(filename,
- arguments = [],
- input_conversion = "",
- file_dependencies = [])
-
- Runs the given script, returning the stdout of the script. The build
- generation will fail if the script does not exist or returns a nonzero exit
- code.
-
- The current directory when executing the script will be the root build
- directory. If you are passing file names, you will want to use the
- rebase_path() function to make file names relative to this path (see "gn help
- rebase_path").
-```
-
-#### **Arguments**:
-
-```
- filename:
- File name of python script to execute. Non-absolute names will be treated
- as relative to the current build file.
-
- arguments:
- A list of strings to be passed to the script as arguments. May be
- unspecified or the empty list which means no arguments.
-
- input_conversion:
- Controls how the file is read and parsed. See "gn help input_conversion".
-
- If unspecified, defaults to the empty string which causes the script
- result to be discarded. exec script will return None.
-
- dependencies:
- (Optional) A list of files that this script reads or otherwise depends
- on. These dependencies will be added to the build result such that if any
- of them change, the build will be regenerated and the script will be
- re-run.
-
- The script itself will be an implicit dependency so you do not need to
- list it.
-```
-
-#### **Example**
-
-```
- all_lines = exec_script(
- "myscript.py", [some_input], "list lines",
- [ rebase_path("data_file.txt", root_build_dir) ])
-
- # This example just calls the script with no arguments and discards the
- # result.
- exec_script("//foo/bar/myscript.py")
-```
-### <a name="foreach"></a>**foreach**: Iterate over a list.
-
-```
- foreach(<loop_var>, <list>) {
- <loop contents>
- }
-
- Executes the loop contents block over each item in the list, assigning the
- loop_var to each item in sequence. The <loop_var> will be a copy so assigning
- to it will not mutate the list. The loop will iterate over a copy of <list>
- so mutating it inside the loop will not affect iteration.
-
- The block does not introduce a new scope, so that variable assignments inside
- the loop will be visible once the loop terminates.
-
- The loop variable will temporarily shadow any existing variables with the
- same name for the duration of the loop. After the loop terminates the loop
- variable will no longer be in scope, and the previous value (if any) will be
- restored.
-```
-
-#### **Example**
-
-```
- mylist = [ "a", "b", "c" ]
- foreach(i, mylist) {
- print(i)
- }
-
- Prints:
- a
- b
- c
-```
-### <a name="forward_variables_from"></a>**forward_variables_from**: Copies variables from a different scope.
-
-```
- forward_variables_from(from_scope, variable_list_or_star,
- variable_to_not_forward_list = [])
-
- Copies the given variables from the given scope to the local scope if they
- exist. This is normally used in the context of templates to use the values of
- variables defined in the template invocation to a template-defined target.
-
- The variables in the given variable_list will be copied if they exist in the
- given scope or any enclosing scope. If they do not exist, nothing will happen
- and they be left undefined in the current scope.
-
- As a special case, if the variable_list is a string with the value of "*",
- all variables from the given scope will be copied. "*" only copies variables
- set directly on the from_scope, not enclosing ones. Otherwise it would
- duplicate all global variables.
-
- When an explicit list of variables is supplied, if the variable exists in the
- current (destination) scope already, an error will be thrown. If "*" is
- specified, variables in the current scope will be clobbered (the latter is
- important because most targets have an implicit configs list, which means it
- wouldn't work at all if it didn't clobber).
-
- The sources assignment filter (see "gn help set_sources_assignment_filter")
- is never applied by this function. It's assumed than any desired filtering
- was already done when sources was set on the from_scope.
-
- If variables_to_not_forward_list is non-empty, then it must contains a list
- of variable names that will not be forwarded. This is mostly useful when
- variable_list_or_star has a value of "*".
-```
-
-#### **Examples**
-
-```
- # This is a common action template. It would invoke a script with some given
- # parameters, and wants to use the various types of deps and the visibility
- # from the invoker if it's defined. It also injects an additional dependency
- # to all targets.
- template("my_test") {
- action(target_name) {
- forward_variables_from(invoker, [ "data_deps", "deps",
- "public_deps", "visibility" "
- "])
- # Add our test code to the dependencies.
- # "deps" may or may not be defined at this point.
- if (defined(deps)) {
- deps += [ "//tools/doom_melon" ]
- } else {
- deps = [ "//tools/doom_melon" ]
- }
- }
- }
-
- # This is a template around either a target whose type depends on a global
- # variable. It forwards all values from the invoker.
- template("my_wrapper") {
- target(my_wrapper_target_type, target_name) {
- forward_variables_from(invoker, "*")
- }
- }
-
- # A template that wraps another. It adds behavior based on one
- # variable, and forwards all others to the nested target.
- template("my_ios_test_app") {
- ios_test_app(target_name) {
- forward_variables_from(invoker, "*", ["test_bundle_name"])
- if (!defined(extra_substitutions)) {
- extra_substitutions = []
- }
- extra_substitutions += [ "BUNDLE_ID_TEST_NAME=$test_bundle_name" ]
- }
- }
-```
-### <a name="get_label_info"></a>**get_label_info**: Get an attribute from a target's label.
-
-```
- get_label_info(target_label, what)
-
- Given the label of a target, returns some attribute of that target. The
- target need not have been previously defined in the same file, since none of
- the attributes depend on the actual target definition, only the label itself.
-
- See also "gn help get_target_outputs".
-```
-
-#### **Possible values for the "what" parameter**
-
-```
- "name"
- The short name of the target. This will match the value of the
- "target_name" variable inside that target's declaration. For the label
- "//foo/bar:baz" this will return "baz".
-
- "dir"
- The directory containing the target's definition, with no slash at the
- end. For the label "//foo/bar:baz" this will return "//foo/bar".
-
- "target_gen_dir"
- The generated file directory for the target. This will match the value of
- the "target_gen_dir" variable when inside that target's declaration.
-
- "root_gen_dir"
- The root of the generated file tree for the target. This will match the
- value of the "root_gen_dir" variable when inside that target's
- declaration.
-
- "target_out_dir
- The output directory for the target. This will match the value of the
- "target_out_dir" variable when inside that target's declaration.
-
- "root_out_dir"
- The root of the output file tree for the target. This will match the
- value of the "root_out_dir" variable when inside that target's
- declaration.
-
- "label_no_toolchain"
- The fully qualified version of this label, not including the toolchain.
- For the input ":bar" it might return "//foo:bar".
-
- "label_with_toolchain"
- The fully qualified version of this label, including the toolchain. For
- the input ":bar" it might return "//foo:bar(//toolchain:x64)".
-
- "toolchain"
- The label of the toolchain. This will match the value of the
- "current_toolchain" variable when inside that target's declaration.
-```
-
-#### **Examples**
-
-```
- get_label_info(":foo", "name")
- # Returns string "foo".
-
- get_label_info("//foo/bar:baz", "target_gen_dir")
- # Returns string "//out/Debug/gen/foo/bar".
-```
-### <a name="get_path_info"></a>**get_path_info**: Extract parts of a file or directory name.
-
-```
- get_path_info(input, what)
-
- The first argument is either a string representing a file or directory name,
- or a list of such strings. If the input is a list the return value will be a
- list containing the result of applying the rule to each item in the input.
-```
-
-#### **Possible values for the "what" parameter**
-
-```
- "file"
- The substring after the last slash in the path, including the name and
- extension. If the input ends in a slash, the empty string will be
- returned.
- "foo/bar.txt" => "bar.txt"
- "bar.txt" => "bar.txt"
- "foo/" => ""
- "" => ""
-
- "name"
- The substring of the file name not including the extension.
- "foo/bar.txt" => "bar"
- "foo/bar" => "bar"
- "foo/" => ""
-
- "extension"
- The substring following the last period following the last slash, or the
- empty string if not found. The period is not included.
- "foo/bar.txt" => "txt"
- "foo/bar" => ""
-
- "dir"
- The directory portion of the name, not including the slash.
- "foo/bar.txt" => "foo"
- "//foo/bar" => "//foo"
- "foo" => "."
-
- The result will never end in a slash, so if the resulting is empty, the
- system ("/") or source ("//") roots, a "." will be appended such that it
- is always legal to append a slash and a filename and get a valid path.
-
- "out_dir"
- The output file directory corresponding to the path of the given file,
- not including a trailing slash.
- "//foo/bar/baz.txt" => "//out/Default/obj/foo/bar"
-
- "gen_dir"
- The generated file directory corresponding to the path of the given file,
- not including a trailing slash.
- "//foo/bar/baz.txt" => "//out/Default/gen/foo/bar"
-
- "abspath"
- The full absolute path name to the file or directory. It will be resolved
- relative to the current directory, and then the source- absolute version
- will be returned. If the input is system- absolute, the same input will
- be returned.
- "foo/bar.txt" => "//mydir/foo/bar.txt"
- "foo/" => "//mydir/foo/"
- "//foo/bar" => "//foo/bar" (already absolute)
- "/usr/include" => "/usr/include" (already absolute)
-
- If you want to make the path relative to another directory, or to be
- system-absolute, see rebase_path().
-```
-
-#### **Examples**
-```
- sources = [ "foo.cc", "foo.h" ]
- result = get_path_info(source, "abspath")
- # result will be [ "//mydir/foo.cc", "//mydir/foo.h" ]
-
- result = get_path_info("//foo/bar/baz.cc", "dir")
- # result will be "//foo/bar"
-
- # Extract the source-absolute directory name,
- result = get_path_info(get_path_info(path, "dir"), "abspath"
-```
-### <a name="get_target_outputs"></a>**get_target_outputs**: [file list] Get the list of outputs from a target.
-
-```
- get_target_outputs(target_label)
-
- Returns a list of output files for the named target. The named target must
- have been previously defined in the current file before this function is
- called (it can't reference targets in other files because there isn't a
- defined execution order, and it obviously can't reference targets that are
- defined after the function call).
-
- Only copy and action targets are supported. The outputs from binary targets
- will depend on the toolchain definition which won't necessarily have been
- loaded by the time a given line of code has run, and source sets and groups
- have no useful output file.
-```
-
-#### **Return value**
-
-```
- The names in the resulting list will be absolute file paths (normally like
- "//out/Debug/bar.exe", depending on the build directory).
-
- action targets: this will just return the files specified in the "outputs"
- variable of the target.
-
- action_foreach targets: this will return the result of applying the output
- template to the sources (see "gn help source_expansion"). This will be the
- same result (though with guaranteed absolute file paths), as
- process_file_template will return for those inputs (see "gn help
- process_file_template").
-
- binary targets (executables, libraries): this will return a list of the
- resulting binary file(s). The "main output" (the actual binary or library)
- will always be the 0th element in the result. Depending on the platform and
- output type, there may be other output files as well (like import libraries)
- which will follow.
-
- source sets and groups: this will return a list containing the path of the
- "stamp" file that Ninja will produce once all outputs are generated. This
- probably isn't very useful.
-```
-
-#### **Example**
-
-```
- # Say this action generates a bunch of C source files.
- action_foreach("my_action") {
- sources = [ ... ]
- outputs = [ ... ]
- }
-
- # Compile the resulting source files into a source set.
- source_set("my_lib") {
- sources = get_target_outputs(":my_action")
- }
-```
-### <a name="getenv"></a>**getenv**: Get an environment variable.
-
-```
- value = getenv(env_var_name)
-
- Returns the value of the given environment variable. If the value is not
- found, it will try to look up the variable with the "opposite" case (based on
- the case of the first letter of the variable), but is otherwise
- case-sensitive.
-
- If the environment variable is not found, the empty string will be returned.
- Note: it might be nice to extend this if we had the concept of "none" in the
- language to indicate lookup failure.
-```
-
-#### **Example**
-
-```
- home_dir = getenv("HOME")
-```
-### <a name="import"></a>**import**: Import a file into the current scope.
-
-```
- The import command loads the rules and variables resulting from executing the
- given file into the current scope.
-
- By convention, imported files are named with a .gni extension.
-
- An import is different than a C++ "include". The imported file is executed in
- a standalone environment from the caller of the import command. The results
- of this execution are cached for other files that import the same .gni file.
-
- Note that you can not import a BUILD.gn file that's otherwise used in the
- build. Files must either be imported or implicitly loaded as a result of deps
- rules, but not both.
-
- The imported file's scope will be merged with the scope at the point import
- was called. If there is a conflict (both the current scope and the imported
- file define some variable or rule with the same name but different value), a
- runtime error will be thrown. Therefore, it's good practice to minimize the
- stuff that an imported file defines.
-
- Variables and templates beginning with an underscore '_' are considered
- private and will not be imported. Imported files can use such variables for
- internal computation without affecting other files.
-```
-
-#### **Examples**
-
-```
- import("//build/rules/idl_compilation_rule.gni")
-
- # Looks in the current directory.
- import("my_vars.gni")
-```
-### <a name="not_needed"></a>**not_needed**: Mark variables from scope as not needed.
-
-```
- not_needed(variable_list_or_star, variable_to_ignore_list = [])
- not_needed(from_scope, variable_list_or_star,
- variable_to_ignore_list = [])
-
- Mark the variables in the current or given scope as not needed, which means
- you will not get an error about unused variables for these. The
- variable_to_ignore_list allows excluding variables from "all matches" if
- variable_list_or_star is "*".
-```
-
-#### **Example**
-
-```
- not_needed("*", [ "config" ])
- not_needed([ "data_deps", "deps" ])
- not_needed(invoker, "*", [ "config" ])
- not_needed(invoker, [ "data_deps", "deps" ])
-```
-### <a name="pool"></a>**pool**: Defines a pool object.
-
-```
- Pool objects can be applied to a tool to limit the parallelism of the
- build. This object has a single property "depth" corresponding to
- the number of tasks that may run simultaneously.
-
- As the file containing the pool definition may be executed in the
- context of more than one toolchain it is recommended to specify an
- explicit toolchain when defining and referencing a pool.
-
- A pool named "console" defined in the root build file represents Ninja's
- console pool. Targets using this pool will have access to the console's
- stdin and stdout, and output will not be buffered. This special pool must
- have a depth of 1. Pools not defined in the root must not be named "console".
- The console pool can only be defined for the default toolchain.
- Refer to the Ninja documentation on the console pool for more info.
-
- A pool is referenced by its label just like a target.
-```
-
-#### **Variables**
-
-```
- depth*
- * = required
-```
-
-#### **Example**
-
-```
- if (current_toolchain == default_toolchain) {
- pool("link_pool") {
- depth = 1
- }
- }
-
- toolchain("toolchain") {
- tool("link") {
- command = "..."
- pool = ":link_pool($default_toolchain)")
- }
- }
-```
-### <a name="print"></a>**print**: Prints to the console.
-
-```
- Prints all arguments to the console separated by spaces. A newline is
- automatically appended to the end.
-
- This function is intended for debugging. Note that build files are run in
- parallel so you may get interleaved prints. A buildfile may also be executed
- more than once in parallel in the context of different toolchains so the
- prints from one file may be duplicated or
- interleaved with itself.
-```
-
-#### **Examples**
-
-```
- print("Hello world")
-
- print(sources, deps)
-```
-### <a name="process_file_template"></a>**process_file_template**: Do template expansion over a list of files.
-
-```
- process_file_template(source_list, template)
-
- process_file_template applies a template list to a source file list,
- returning the result of applying each template to each source. This is
- typically used for computing output file names from input files.
-
- In most cases, get_target_outputs() will give the same result with shorter,
- more maintainable code. This function should only be used when that function
- can't be used (like there's no target or the target is defined in another
- build file).
-```
-
-#### **Arguments**
-
-```
- The source_list is a list of file names.
-
- The template can be a string or a list. If it is a list, multiple output
- strings are generated for each input.
-
- The template should contain source expansions to which each name in the
- source list is applied. See "gn help source_expansion".
-```
-
-#### **Example**
-
-```
- sources = [
- "foo.idl",
- "bar.idl",
- ]
- myoutputs = process_file_template(
- sources,
- [ "$target_gen_dir/{{source_name_part}}.cc",
- "$target_gen_dir/{{source_name_part}}.h" ])
-
- The result in this case will be:
- [ "//out/Debug/foo.cc"
- "//out/Debug/foo.h"
- "//out/Debug/bar.cc"
- "//out/Debug/bar.h" ]
-```
-### <a name="read_file"></a>**read_file**: Read a file into a variable.
-
-```
- read_file(filename, input_conversion)
-
- Whitespace will be trimmed from the end of the file. Throws an error if the
- file can not be opened.
-```
-
-#### **Arguments**
-
-```
- filename
- Filename to read, relative to the build file.
-
- input_conversion
- Controls how the file is read and parsed. See "gn help input_conversion".
-```
-
-#### **Example**
-
-```
- lines = read_file("foo.txt", "list lines")
-```
-### <a name="rebase_path"></a>**rebase_path**: Rebase a file or directory to another location.
-
-```
- converted = rebase_path(input,
- new_base = "",
- current_base = ".")
-
- Takes a string argument representing a file name, or a list of such strings
- and converts it/them to be relative to a different base directory.
-
- When invoking the compiler or scripts, GN will automatically convert sources
- and include directories to be relative to the build directory. However, if
- you're passing files directly in the "args" array or doing other manual
- manipulations where GN doesn't know something is a file name, you will need
- to convert paths to be relative to what your tool is expecting.
-
- The common case is to use this to convert paths relative to the current
- directory to be relative to the build directory (which will be the current
- directory when executing scripts).
-
- If you want to convert a file path to be source-absolute (that is, beginning
- with a double slash like "//foo/bar"), you should use the get_path_info()
- function. This function won't work because it will always make relative
- paths, and it needs to support making paths relative to the source root, so
- can't also generate source-absolute paths without more special-cases.
-```
-
-#### **Arguments**
-
-```
- input
- A string or list of strings representing file or directory names These
- can be relative paths ("foo/bar.txt"), system absolute paths
- ("/foo/bar.txt"), or source absolute paths ("//foo/bar.txt").
-
- new_base
- The directory to convert the paths to be relative to. This can be an
- absolute path or a relative path (which will be treated as being relative
- to the current BUILD-file's directory).
-
- As a special case, if new_base is the empty string (the default), all
- paths will be converted to system-absolute native style paths with system
- path separators. This is useful for invoking external programs.
-
- current_base
- Directory representing the base for relative paths in the input. If this
- is not an absolute path, it will be treated as being relative to the
- current build file. Use "." (the default) to convert paths from the
- current BUILD-file's directory.
-```
-
-#### **Return value**
-
-```
- The return value will be the same type as the input value (either a string or
- a list of strings). All relative and source-absolute file names will be
- converted to be relative to the requested output System-absolute paths will
- be unchanged.
-
- Whether an output path will end in a slash will match whether the
- corresponding input path ends in a slash. It will return "." or "./"
- (depending on whether the input ends in a slash) to avoid returning empty
- strings. This means if you want a root path ("//" or "/") not ending in a
- slash, you can add a dot ("//.").
-```
-
-#### **Example**
-
-```
- # Convert a file in the current directory to be relative to the build
- # directory (the current dir when executing compilers and scripts).
- foo = rebase_path("myfile.txt", root_build_dir)
- # might produce "../../project/myfile.txt".
-
- # Convert a file to be system absolute:
- foo = rebase_path("myfile.txt")
- # Might produce "D:\\source\\project\\myfile.txt" on Windows or
- # "/home/you/source/project/myfile.txt" on Linux.
-
- # Typical usage for converting to the build directory for a script.
- action("myscript") {
- # Don't convert sources, GN will automatically convert these to be relative
- # to the build directory when it constructs the command line for your
- # script.
- sources = [ "foo.txt", "bar.txt" ]
-
- # Extra file args passed manually need to be explicitly converted
- # to be relative to the build directory:
- args = [
- "--data",
- rebase_path("//mything/data/input.dat", root_build_dir),
- "--rel",
- rebase_path("relative_path.txt", root_build_dir)
- ] + rebase_path(sources, root_build_dir)
- }
-```
-### <a name="set_default_toolchain"></a>**set_default_toolchain**: Sets the default toolchain name.
-
-```
- set_default_toolchain(toolchain_label)
-
- The given label should identify a toolchain definition (see "gn help
- toolchain"). This toolchain will be used for all targets unless otherwise
- specified.
-
- This function is only valid to call during the processing of the build
- configuration file. Since the build configuration file is processed
- separately for each toolchain, this function will be a no-op when called
- under any non-default toolchains.
-
- For example, the default toolchain should be appropriate for the current
- environment. If the current environment is 32-bit and somebody references a
- target with a 64-bit toolchain, we wouldn't want processing of the build
- config file for the 64-bit toolchain to reset the default toolchain to
- 64-bit, we want to keep it 32-bits.
-```
-
-#### **Argument**
-
-```
- toolchain_label
- Toolchain name.
-```
-
-#### **Example**
-
-```
- # Set default toolchain only has an effect when run in the context of the
- # default toolchain. Pick the right one according to the current CPU
- # architecture.
- if (target_cpu == "x64") {
- set_default_toolchain("//toolchains:64")
- } else if (target_cpu == "x86") {
- set_default_toolchain("//toolchains:32")
- }
-```
-### <a name="set_defaults"></a>**set_defaults**: Set default values for a target type.
-
-```
- set_defaults(<target_type_name>) { <values...> }
-
- Sets the default values for a given target type. Whenever target_type_name is
- seen in the future, the values specified in set_default's block will be
- copied into the current scope.
-
- When the target type is used, the variable copying is very strict. If a
- variable with that name is already in scope, the build will fail with an
- error.
-
- set_defaults can be used for built-in target types ("executable",
- "shared_library", etc.) and custom ones defined via the "template" command.
- It can be called more than once and the most recent call in any scope will
- apply, but there is no way to refer to the previous defaults and modify them
- (each call to set_defaults must supply a complete list of all defaults it
- wants). If you want to share defaults, store them in a separate variable.
-```
-
-#### **Example**
-
-```
- set_defaults("static_library") {
- configs = [ "//tools/mything:settings" ]
- }
-
- static_library("mylib")
- # The configs will be auto-populated as above. You can remove it if
- # you don't want the default for a particular default:
- configs -= [ "//tools/mything:settings" ]
- }
-```
-### <a name="set_sources_assignment_filter"></a>**set_sources_assignment_filter**: Set a pattern to filter source files.
-
-```
- The sources assignment filter is a list of patterns that remove files from
- the list implicitly whenever the "sources" variable is assigned to. This will
- do nothing for non-lists.
-
- This is intended to be used to globally filter out files with
- platform-specific naming schemes when they don't apply, for example you may
- want to filter out all "*_win.cc" files on non-Windows platforms.
-
- Typically this will be called once in the master build config script to set
- up the filter for the current platform. Subsequent calls will overwrite the
- previous values.
-
- If you want to bypass the filter and add a file even if it might be filtered
- out, call set_sources_assignment_filter([]) to clear the list of filters.
- This will apply until the current scope exits
-```
-
-#### **How to use patterns**
-
-```
- File patterns are VERY limited regular expressions. They must match the
- entire input string to be counted as a match. In regular expression parlance,
- there is an implicit "^...$" surrounding your input. If you want to match a
- substring, you need to use wildcards at the beginning and end.
-
- There are only two special tokens understood by the pattern matcher.
- Everything else is a literal.
-
- - "*" Matches zero or more of any character. It does not depend on the
- preceding character (in regular expression parlance it is equivalent to
- ".*").
-
- - "\b" Matches a path boundary. This will match the beginning or end of a
- string, or a slash.
-```
-
-#### **Pattern examples**
-
-```
- "*asdf*"
- Matches a string containing "asdf" anywhere.
-
- "asdf"
- Matches only the exact string "asdf".
-
- "*.cc"
- Matches strings ending in the literal ".cc".
-
- "\bwin/*"
- Matches "win/foo" and "foo/win/bar.cc" but not "iwin/foo".
-```
-
-#### **Sources assignment example**
-
-```
- # Filter out all _win files.
- set_sources_assignment_filter([ "*_win.cc", "*_win.h" ])
- sources = [ "a.cc", "b_win.cc" ]
- print(sources)
- # Will print [ "a.cc" ]. b_win one was filtered out.
-```
-### <a name="split_list"></a>**split_list**: Splits a list into N different sub-lists.
-
-```
- result = split_list(input, n)
-
- Given a list and a number N, splits the list into N sub-lists of
- approximately equal size. The return value is a list of the sub-lists. The
- result will always be a list of size N. If N is greater than the number of
- elements in the input, it will be padded with empty lists.
-
- The expected use is to divide source files into smaller uniform chunks.
-```
-
-#### **Example**
-
-```
- The code:
- mylist = [1, 2, 3, 4, 5, 6]
- print(split_list(mylist, 3))
-
- Will print:
- [[1, 2], [3, 4], [5, 6]
-```
-### <a name="template"></a>**template**: Define a template rule.
-
-```
- A template defines a custom name that acts like a function. It provides a way
- to add to the built-in target types.
-
- The template() function is used to declare a template. To invoke the
- template, just use the name of the template like any other target type.
-
- Often you will want to declare your template in a special file that other
- files will import (see "gn help import") so your template rule can be shared
- across build files.
-```
-
-#### **Variables and templates**:
-
-```
- When you call template() it creates a closure around all variables currently
- in scope with the code in the template block. When the template is invoked,
- the closure will be executed.
-
- When the template is invoked, the code in the caller is executed and passed
- to the template code as an implicit "invoker" variable. The template uses
- this to read state out of the invoking code.
-
- One thing explicitly excluded from the closure is the "current directory"
- against which relative file names are resolved. The current directory will be
- that of the invoking code, since typically that code specifies the file
- names. This means all files internal to the template should use absolute
- names.
-
- A template will typically forward some or all variables from the invoking
- scope to a target that it defines. Often, such variables might be optional.
- Use the pattern:
-
- if (defined(invoker.deps)) {
- deps = invoker.deps
- }
-
- The function forward_variables_from() provides a shortcut to forward one or
- more or possibly all variables in this manner:
-
- forward_variables_from(invoker, ["deps", "public_deps"])
-```
-
-#### **Target naming**
-
-```
- Your template should almost always define a built-in target with the name the
- template invoker specified. For example, if you have an IDL template and
- somebody does:
- idl("foo") {...
- you will normally want this to expand to something defining a source_set or
- static_library named "foo" (among other things you may need). This way, when
- another target specifies a dependency on "foo", the static_library or
- source_set will be linked.
-
- It is also important that any other targets your template expands to have
- unique names, or you will get collisions.
-
- Access the invoking name in your template via the implicit "target_name"
- variable. This should also be the basis for how other targets that a template
- expands to ensure uniqueness.
-
- A typical example would be a template that defines an action to generate some
- source files, and a source_set to compile that source. Your template would
- name the source_set "target_name" because that's what you want external
- targets to depend on to link your code. And you would name the action
- something like "${target_name}_action" to make it unique. The source set
- would have a dependency on the action to make it run.
-```
-
-#### **Overriding builtin targets**
-
-```
- You can use template to redefine a built-in target in which case your template
- takes a precedence over the built-in one. All uses of the target from within
- the template definition will refer to the built-in target which makes it
- possible to extend the behavior of the built-in target:
-
- template("shared_library") {
- shared_library(shlib) {
- forward_variables_from(invoker, "*")
- ...
- }
- }
-```
-
-#### **Example of defining a template**
-
-```
- template("my_idl") {
- # Be nice and help callers debug problems by checking that the variables
- # the template requires are defined. This gives a nice message rather than
- # giving the user an error about an undefined variable in the file defining
- # the template
- #
- # You can also use defined() to give default values to variables
- # unspecified by the invoker.
- assert(defined(invoker.sources),
- "Need sources in $target_name listing the idl files.")
-
- # Name of the intermediate target that does the code gen. This must
- # incorporate the target name so it's unique across template
- # instantiations.
- code_gen_target_name = target_name + "_code_gen"
-
- # Intermediate target to convert IDL to C source. Note that the name is
- # based on the name the invoker of the template specified. This way, each
- # time the template is invoked we get a unique intermediate action name
- # (since all target names are in the global scope).
- action_foreach(code_gen_target_name) {
- # Access the scope defined by the invoker via the implicit "invoker"
- # variable.
- sources = invoker.sources
-
- # Note that we need an absolute path for our script file name. The
- # current directory when executing this code will be that of the invoker
- # (this is why we can use the "sources" directly above without having to
- # rebase all of the paths). But if we need to reference a script relative
- # to the template file, we'll need to use an absolute path instead.
- script = "//tools/idl/idl_code_generator.py"
-
- # Tell GN how to expand output names given the sources.
- # See "gn help source_expansion" for more.
- outputs = [ "$target_gen_dir/{{source_name_part}}.cc",
- "$target_gen_dir/{{source_name_part}}.h" ]
- }
-
- # Name the source set the same as the template invocation so instancing
- # this template produces something that other targets can link to in their
- # deps.
- source_set(target_name) {
- # Generates the list of sources, we get these from the action_foreach
- # above.
- sources = get_target_outputs(":$code_gen_target_name")
-
- # This target depends on the files produced by the above code gen target.
- deps = [ ":$code_gen_target_name" ]
- }
- }
-```
-
-#### **Example of invoking the resulting template**
-
-```
- # This calls the template code above, defining target_name to be
- # "foo_idl_files" and "invoker" to be the set of stuff defined in the curly
- # brackets.
- my_idl("foo_idl_files") {
- # Goes into the template as "invoker.sources".
- sources = [ "foo.idl", "bar.idl" ]
- }
-
- # Here is a target that depends on our template.
- executable("my_exe") {
- # Depend on the name we gave the template call above. Internally, this will
- # produce a dependency from executable to the source_set inside the
- # template (since it has this name), which will in turn depend on the code
- # gen action.
- deps = [ ":foo_idl_files" ]
- }
-```
-### <a name="tool"></a>**tool**: Specify arguments to a toolchain tool.
-
-#### **Usage**
-
-```
- tool(<tool type>) {
- <tool variables...>
- }
-```
-
-#### **Tool types**
-
-```
- Compiler tools:
- "cc": C compiler
- "cxx": C++ compiler
- "objc": Objective C compiler
- "objcxx": Objective C++ compiler
- "rc": Resource compiler (Windows .rc files)
- "asm": Assembler
-
- Linker tools:
- "alink": Linker for static libraries (archives)
- "solink": Linker for shared libraries
- "link": Linker for executables
-
- Other tools:
- "stamp": Tool for creating stamp files
- "copy": Tool to copy files.
- "action": Defaults for actions
-
- Platform specific tools:
- "copy_bundle_data": [iOS, macOS] Tool to copy files in a bundle.
- "compile_xcassets": [iOS, macOS] Tool to compile asset catalogs.
-```
-
-#### **Tool variables**
-
-```
- command [string with substitutions]
- Valid for: all tools except "action" (required)
-
- The command to run.
-
- default_output_dir [string with substitutions]
- Valid for: linker tools
-
- Default directory name for the output file relative to the
- root_build_dir. It can contain other substitution patterns. This will
- be the default value for the {{output_dir}} expansion (discussed below)
- but will be overridden by the "output_dir" variable in a target, if one
- is specified.
-
- GN doesn't do anything with this string other than pass it along,
- potentially with target-specific overrides. It is the tool's job to use
- the expansion so that the files will be in the right place.
-
- default_output_extension [string]
- Valid for: linker tools
-
- Extension for the main output of a linkable tool. It includes the
- leading dot. This will be the default value for the
- {{output_extension}} expansion (discussed below) but will be overridden
- by by the "output extension" variable in a target, if one is specified.
- Empty string means no extension.
-
- GN doesn't actually do anything with this extension other than pass it
- along, potentially with target-specific overrides. One would typically
- use the {{output_extension}} value in the "outputs" to read this value.
-
- Example: default_output_extension = ".exe"
-
- depfile [string with substitutions]
- Valid for: compiler tools (optional)
-
- If the tool can write ".d" files, this specifies the name of the
- resulting file. These files are used to list header file dependencies
- (or other implicit input dependencies) that are discovered at build
- time. See also "depsformat".
-
- Example: depfile = "{{output}}.d"
-
- depsformat [string]
- Valid for: compiler tools (when depfile is specified)
-
- Format for the deps outputs. This is either "gcc" or "msvc". See the
- ninja documentation for "deps" for more information.
-
- Example: depsformat = "gcc"
-
- description [string with substitutions, optional]
- Valid for: all tools
-
- What to print when the command is run.
-
- Example: description = "Compiling {{source}}"
-
- lib_switch [string, optional, link tools only]
- lib_dir_switch [string, optional, link tools only]
- Valid for: Linker tools except "alink"
-
- These strings will be prepended to the libraries and library search
- directories, respectively, because linkers differ on how specify them.
- If you specified:
- lib_switch = "-l"
- lib_dir_switch = "-L"
- then the "{{libs}}" expansion for [ "freetype", "expat"] would be
- "-lfreetype -lexpat".
-
- outputs [list of strings with substitutions]
- Valid for: Linker and compiler tools (required)
-
- An array of names for the output files the tool produces. These are
- relative to the build output directory. There must always be at least
- one output file. There can be more than one output (a linker might
- produce a library and an import library, for example).
-
- This array just declares to GN what files the tool will produce. It is
- your responsibility to specify the tool command that actually produces
- these files.
-
- If you specify more than one output for shared library links, you
- should consider setting link_output, depend_output, and
- runtime_outputs.
-
- Example for a compiler tool that produces .obj files:
- outputs = [
- "{{source_out_dir}}/{{source_name_part}}.obj"
- ]
-
- Example for a linker tool that produces a .dll and a .lib. The use of
- {{target_output_name}}, {{output_extension}} and {{output_dir}} allows
- the target to override these values.
- outputs = [
- "{{output_dir}}/{{target_output_name}}"
- "{{output_extension}}",
- "{{output_dir}}/{{target_output_name}}.lib",
- ]
-
- pool [label, optional]
- Valid for: all tools (optional)
-
- Label of the pool to use for the tool. Pools are used to limit the
- number of tasks that can execute concurrently during the build.
-
- See also "gn help pool".
-
- link_output [string with substitutions]
- depend_output [string with substitutions]
- Valid for: "solink" only (optional)
-
- These two files specify which of the outputs from the solink tool
- should be used for linking and dependency tracking. These should match
- entries in the "outputs". If unspecified, the first item in the
- "outputs" array will be used for all. See "Separate linking and
- dependencies for shared libraries" below for more.
-
- On Windows, where the tools produce a .dll shared library and a .lib
- import library, you will want the first two to be the import library
- and the third one to be the .dll file. On Linux, if you're not doing
- the separate linking/dependency optimization, all of these should be
- the .so output.
-
- output_prefix [string]
- Valid for: Linker tools (optional)
-
- Prefix to use for the output name. Defaults to empty. This prefix will
- be prepended to the name of the target (or the output_name if one is
- manually specified for it) if the prefix is not already there. The
- result will show up in the {{output_name}} substitution pattern.
-
- Individual targets can opt-out of the output prefix by setting:
- output_prefix_override = true
- (see "gn help output_prefix_override").
-
- This is typically used to prepend "lib" to libraries on
- Posix systems:
- output_prefix = "lib"
-
- precompiled_header_type [string]
- Valid for: "cc", "cxx", "objc", "objcxx"
-
- Type of precompiled headers. If undefined or the empty string,
- precompiled headers will not be used for this tool. Otherwise use "gcc"
- or "msvc".
-
- For precompiled headers to be used for a given target, the target (or a
- config applied to it) must also specify a "precompiled_header" and, for
- "msvc"-style headers, a "precompiled_source" value. If the type is
- "gcc", then both "precompiled_header" and "precompiled_source" must
- resolve to the same file, despite the different formats required for
- each."
-
- See "gn help precompiled_header" for more.
-
- restat [boolean]
- Valid for: all tools (optional, defaults to false)
-
- Requests that Ninja check the file timestamp after this tool has run to
- determine if anything changed. Set this if your tool has the ability to
- skip writing output if the output file has not changed.
-
- Normally, Ninja will assume that when a tool runs the output be new and
- downstream dependents must be rebuild. When this is set to trye, Ninja
- can skip rebuilding downstream dependents for input changes that don't
- actually affect the output.
-
- Example:
- restat = true
-
- rspfile [string with substitutions]
- Valid for: all tools except "action" (optional)
-
- Name of the response file. If empty, no response file will be
- used. See "rspfile_content".
-
- rspfile_content [string with substitutions]
- Valid for: all tools except "action" (required when "rspfile" is used)
-
- The contents to be written to the response file. This may include all
- or part of the command to send to the tool which allows you to get
- around OS command-line length limits.
-
- This example adds the inputs and libraries to a response file, but
- passes the linker flags directly on the command line:
- tool("link") {
- command = "link -o {{output}} {{ldflags}} @{{output}}.rsp"
- rspfile = "{{output}}.rsp"
- rspfile_content = "{{inputs}} {{solibs}} {{libs}}"
- }
-
- runtime_outputs [string list with substitutions]
- Valid for: linker tools
-
- If specified, this list is the subset of the outputs that should be
- added to runtime deps (see "gn help runtime_deps"). By default (if
- runtime_outputs is empty or unspecified), it will be the link_output.
-```
-
-#### **Expansions for tool variables**
-
-```
- All paths are relative to the root build directory, which is the current
- directory for running all tools. These expansions are available to all tools:
-
- {{label}}
- The label of the current target. This is typically used in the
- "description" field for link tools. The toolchain will be omitted from
- the label for targets in the default toolchain, and will be included
- for targets in other toolchains.
-
- {{label_name}}
- The short name of the label of the target. This is the part after the
- colon. For "//foo/bar:baz" this will be "baz". Unlike
- {{target_output_name}}, this is not affected by the "output_prefix" in
- the tool or the "output_name" set on the target.
-
- {{output}}
- The relative path and name of the output(s) of the current build step.
- If there is more than one output, this will expand to a list of all of
- them. Example: "out/base/my_file.o"
-
- {{target_gen_dir}}
- {{target_out_dir}}
- The directory of the generated file and output directories,
- respectively, for the current target. There is no trailing slash. See
- also {{output_dir}} for linker tools. Example: "out/base/test"
-
- {{target_output_name}}
- The short name of the current target with no path information, or the
- value of the "output_name" variable if one is specified in the target.
- This will include the "output_prefix" if any. See also {{label_name}}.
-
- Example: "libfoo" for the target named "foo" and an output prefix for
- the linker tool of "lib".
-
- Compiler tools have the notion of a single input and a single output, along
- with a set of compiler-specific flags. The following expansions are
- available:
-
- {{asmflags}}
- {{cflags}}
- {{cflags_c}}
- {{cflags_cc}}
- {{cflags_objc}}
- {{cflags_objcc}}
- {{defines}}
- {{include_dirs}}
- Strings correspond that to the processed flags/defines/include
- directories specified for the target.
- Example: "--enable-foo --enable-bar"
-
- Defines will be prefixed by "-D" and include directories will be
- prefixed by "-I" (these work with Posix tools as well as Microsoft
- ones).
-
- {{source}}
- The relative path and name of the current input file.
- Example: "../../base/my_file.cc"
-
- {{source_file_part}}
- The file part of the source including the extension (with no directory
- information).
- Example: "foo.cc"
-
- {{source_name_part}}
- The filename part of the source file with no directory or extension.
- Example: "foo"
-
- {{source_gen_dir}}
- {{source_out_dir}}
- The directory in the generated file and output directories,
- respectively, for the current input file. If the source file is in the
- same directory as the target is declared in, they will will be the same
- as the "target" versions above. Example: "gen/base/test"
-
- Linker tools have multiple inputs and (potentially) multiple outputs The
- static library tool ("alink") is not considered a linker tool. The following
- expansions are available:
-
- {{inputs}}
- {{inputs_newline}}
- Expands to the inputs to the link step. This will be a list of object
- files and static libraries.
- Example: "obj/foo.o obj/bar.o obj/somelibrary.a"
-
- The "_newline" version will separate the input files with newlines
- instead of spaces. This is useful in response files: some linkers can
- take a "-filelist" flag which expects newline separated files, and some
- Microsoft tools have a fixed-sized buffer for parsing each line of a
- response file.
-
- {{ldflags}}
- Expands to the processed set of ldflags and library search paths
- specified for the target.
- Example: "-m64 -fPIC -pthread -L/usr/local/mylib"
-
- {{libs}}
- Expands to the list of system libraries to link to. Each will be
- prefixed by the "lib_switch".
-
- As a special case to support Mac, libraries with names ending in
- ".framework" will be added to the {{libs}} with "-framework" preceding
- it, and the lib prefix will be ignored.
-
- Example: "-lfoo -lbar"
-
- {{output_dir}}
- The value of the "output_dir" variable in the target, or the the value
- of the "default_output_dir" value in the tool if the target does not
- override the output directory. This will be relative to the
- root_build_dir and will not end in a slash. Will be "." for output to
- the root_build_dir.
-
- This is subtly different than {{target_out_dir}} which is defined by GN
- based on the target's path and not overridable. {{output_dir}} is for
- the final output, {{target_out_dir}} is generally for object files and
- other outputs.
-
- Usually {{output_dir}} would be defined in terms of either
- {{target_out_dir}} or {{root_out_dir}}
-
- {{output_extension}}
- The value of the "output_extension" variable in the target, or the
- value of the "default_output_extension" value in the tool if the target
- does not specify an output extension.
- Example: ".so"
-
- {{solibs}}
- Extra libraries from shared library dependencies not specified in the
- {{inputs}}. This is the list of link_output files from shared libraries
- (if the solink tool specifies a "link_output" variable separate from
- the "depend_output").
-
- These should generally be treated the same as libs by your tool.
-
- Example: "libfoo.so libbar.so"
-
- The static library ("alink") tool allows {{arflags}} plus the common tool
- substitutions.
-
- The copy tool allows the common compiler/linker substitutions, plus
- {{source}} which is the source of the copy. The stamp tool allows only the
- common tool substitutions.
-
- The copy_bundle_data and compile_xcassets tools only allows the common tool
- substitutions. Both tools are required to create iOS/macOS bundles and need
- only be defined on those platforms.
-
- The copy_bundle_data tool will be called with one source and needs to copy
- (optionally optimizing the data representation) to its output. It may be
- called with a directory as input and it needs to be recursively copied.
-
- The compile_xcassets tool will be called with one or more source (each an
- asset catalog) that needs to be compiled to a single output. The following
- substitutions are available:
-
- {{inputs}}
- Expands to the list of .xcassets to use as input to compile the asset
- catalog.
-
- {{bundle_product_type}}
- Expands to the product_type of the bundle that will contain the
- compiled asset catalog. Usually corresponds to the product_type
- property of the corresponding create_bundle target.
-
- {{bundle_partial_info_plist}}
- Expands to the path to the partial Info.plist generated by the
- assets catalog compiler. Usually based on the target_name of
- the create_bundle target.
-```
-
-#### **Separate linking and dependencies for shared libraries**
-
-```
- Shared libraries are special in that not all changes to them require that
- dependent targets be re-linked. If the shared library is changed but no
- imports or exports are different, dependent code needn't be relinked, which
- can speed up the build.
-
- If your link step can output a list of exports from a shared library and
- writes the file only if the new one is different, the timestamp of this file
- can be used for triggering re-links, while the actual shared library would be
- used for linking.
-
- You will need to specify
- restat = true
- in the linker tool to make this work, so Ninja will detect if the timestamp
- of the dependency file has changed after linking (otherwise it will always
- assume that running a command updates the output):
-
- tool("solink") {
- command = "..."
- outputs = [
- "{{output_dir}}/{{target_output_name}}{{output_extension}}",
- "{{output_dir}}/{{target_output_name}}"
- "{{output_extension}}.TOC",
- ]
- link_output =
- "{{output_dir}}/{{target_output_name}}{{output_extension}}"
- depend_output =
- "{{output_dir}}/{{target_output_name}}"
- "{{output_extension}}.TOC"
- restat = true
- }
-```
-
-#### **Example**
-
-```
- toolchain("my_toolchain") {
- # Put these at the top to apply to all tools below.
- lib_switch = "-l"
- lib_dir_switch = "-L"
-
- tool("cc") {
- command = "gcc {{source}} -o {{output}}"
- outputs = [ "{{source_out_dir}}/{{source_name_part}}.o" ]
- description = "GCC {{source}}"
- }
- tool("cxx") {
- command = "g++ {{source}} -o {{output}}"
- outputs = [ "{{source_out_dir}}/{{source_name_part}}.o" ]
- description = "G++ {{source}}"
- }
- };
-```
-### <a name="toolchain"></a>**toolchain**: Defines a toolchain.
-
-```
- A toolchain is a set of commands and build flags used to compile the source
- code. The toolchain() function defines these commands.
-```
-
-#### **Toolchain overview**
-
-```
- You can have more than one toolchain in use at once in a build and a target
- can exist simultaneously in multiple toolchains. A build file is executed
- once for each toolchain it is referenced in so the GN code can vary all
- parameters of each target (or which targets exist) on a per-toolchain basis.
-
- When you have a simple build with only one toolchain, the build config file
- is loaded only once at the beginning of the build. It must call
- set_default_toolchain() (see "gn help set_default_toolchain") to tell GN the
- label of the toolchain definition to use. The "toolchain_args" section of the
- toolchain definition is ignored.
-
- When a target has a dependency on a target using different toolchain (see "gn
- help labels" for how to specify this), GN will start a build using that
- secondary toolchain to resolve the target. GN will load the build config file
- with the build arguments overridden as specified in the toolchain_args.
- Because the default toolchain is already known, calls to
- set_default_toolchain() are ignored.
-
- To load a file in an alternate toolchain, GN does the following:
-
- 1. Loads the file with the toolchain definition in it (as determined by the
- toolchain label).
- 2. Re-runs the master build configuration file, applying the arguments
- specified by the toolchain_args section of the toolchain definition.
- 3. Loads the destination build file in the context of the configuration file
- in the previous step.
-
- The toolchain configuration is two-way. In the default toolchain (i.e. the
- main build target) the configuration flows from the build config file to the
- toolchain. The build config file looks at the state of the build (OS type,
- CPU architecture, etc.) and decides which toolchain to use (via
- set_default_toolchain()). In secondary toolchains, the configuration flows
- from the toolchain to the build config file: the "toolchain_args" in the
- toolchain definition specifies the arguments to re-invoke the build.
-```
-
-#### **Functions and variables**
-
-```
- tool()
- The tool() function call specifies the commands commands to run for a given
- step. See "gn help tool".
-
- toolchain_args
- Overrides for build arguments to pass to the toolchain when invoking it.
- This is a variable of type "scope" where the variable names correspond to
- variables in declare_args() blocks.
-
- When you specify a target using an alternate toolchain, the master build
- configuration file is re-interpreted in the context of that toolchain.
- toolchain_args allows you to control the arguments passed into this
- alternate invocation of the build.
-
- Any default system arguments or arguments passed in via "gn args" will also
- be passed to the alternate invocation unless explicitly overridden by
- toolchain_args.
-
- The toolchain_args will be ignored when the toolchain being defined is the
- default. In this case, it's expected you want the default argument values.
-
- See also "gn help buildargs" for an overview of these arguments.
-
- deps
- Dependencies of this toolchain. These dependencies will be resolved before
- any target in the toolchain is compiled. To avoid circular dependencies
- these must be targets defined in another toolchain.
-
- This is expressed as a list of targets, and generally these targets will
- always specify a toolchain:
- deps = [ "//foo/bar:baz(//build/toolchain:bootstrap)" ]
-
- This concept is somewhat inefficient to express in Ninja (it requires a lot
- of duplicate of rules) so should only be used when absolutely necessary.
-```
-
-#### **Example of defining a toolchain**
-
-```
- toolchain("32") {
- tool("cc") {
- command = "gcc {{source}}"
- ...
- }
-
- toolchain_args = {
- use_doom_melon = true # Doom melon always required for 32-bit builds.
- current_cpu = "x86"
- }
- }
-
- toolchain("64") {
- tool("cc") {
- command = "gcc {{source}}"
- ...
- }
-
- toolchain_args = {
- # use_doom_melon is not overridden here, it will take the default.
- current_cpu = "x64"
- }
- }
-```
-
-#### **Example of cross-toolchain dependencies**
-
-```
- If a 64-bit target wants to depend on a 32-bit binary, it would specify a
- dependency using data_deps (data deps are like deps that are only needed at
- runtime and aren't linked, since you can't link a 32-bit and a 64-bit
- library).
-
- executable("my_program") {
- ...
- if (target_cpu == "x64") {
- # The 64-bit build needs this 32-bit helper.
- data_deps = [ ":helper(//toolchains:32)" ]
- }
- }
-
- if (target_cpu == "x86") {
- # Our helper library is only compiled in 32-bits.
- shared_library("helper") {
- ...
- }
- }
-```
-### <a name="write_file"></a>**write_file**: Write a file to disk.
-
-```
- write_file(filename, data)
-
- If data is a list, the list will be written one-item-per-line with no quoting
- or brackets.
-
- If the file exists and the contents are identical to that being written, the
- file will not be updated. This will prevent unnecessary rebuilds of targets
- that depend on this file.
-
- One use for write_file is to write a list of inputs to an script that might
- be too long for the command line. However, it is preferable to use response
- files for this purpose. See "gn help response_file_contents".
-
- TODO(brettw) we probably need an optional third argument to control list
- formatting.
-```
-
-#### **Arguments**
-
-```
- filename
- Filename to write. This must be within the output directory.
-
- data
- The list or string to write.
-```
-## <a name="predefined_variables"></a>Built-in predefined variables
-
-### <a name="current_cpu"></a>**current_cpu**: The processor architecture of the current toolchain.
-
-```
- The build configuration usually sets this value based on the value of
- "host_cpu" (see "gn help host_cpu") and then threads this through the
- toolchain definitions to ensure that it always reflects the appropriate
- value.
-
- This value is not used internally by GN for any purpose. It is set it to the
- empty string ("") by default but is declared so that it can be overridden on
- the command line if so desired.
-
- See "gn help target_cpu" for a list of common values returned.
-```
-### <a name="current_os"></a>**current_os**: The operating system of the current toolchain.
-
-```
- The build configuration usually sets this value based on the value of
- "target_os" (see "gn help target_os"), and then threads this through the
- toolchain definitions to ensure that it always reflects the appropriate
- value.
-
- This value is not used internally by GN for any purpose. It is set it to the
- empty string ("") by default but is declared so that it can be overridden on
- the command line if so desired.
-
- See "gn help target_os" for a list of common values returned.
-```
-### <a name="current_toolchain"></a>**current_toolchain**: Label of the current toolchain.
-
-```
- A fully-qualified label representing the current toolchain. You can use this
- to make toolchain-related decisions in the build. See also
- "default_toolchain".
-```
-
-#### **Example**
-
-```
- if (current_toolchain == "//build:64_bit_toolchain") {
- executable("output_thats_64_bit_only") {
- ...
-```
-### <a name="default_toolchain"></a>**default_toolchain**: [string] Label of the default toolchain.
-
-```
- A fully-qualified label representing the default toolchain, which may not
- necessarily be the current one (see "current_toolchain").
-```
-### <a name="host_cpu"></a>**host_cpu**: The processor architecture that GN is running on.
-
-```
- This is value is exposed so that cross-compile toolchains can access the host
- architecture when needed.
-
- The value should generally be considered read-only, but it can be overriden
- in order to handle unusual cases where there might be multiple plausible
- values for the host architecture (e.g., if you can do either 32-bit or 64-bit
- builds). The value is not used internally by GN for any purpose.
-```
-
-#### **Some possible values**
-
-```
- - "x64"
- - "x86"
-```
-### <a name="host_os"></a>**host_os**: [string] The operating system that GN is running on.
-
-```
- This value is exposed so that cross-compiles can access the host build
- system's settings.
-
- This value should generally be treated as read-only. It, however, is not used
- internally by GN for any purpose.
-```
-
-#### **Some possible values**
-
-```
- - "linux"
- - "mac"
- - "win"
-```
-### <a name="invoker"></a>**invoker**: [string] The invoking scope inside a template.
-
-```
- Inside a template invocation, this variable refers to the scope of the
- invoker of the template. Outside of template invocations, this variable is
- undefined.
-
- All of the variables defined inside the template invocation are accessible as
- members of the "invoker" scope. This is the way that templates read values
- set by the callers.
-
- This is often used with "defined" to see if a value is set on the invoking
- scope.
-
- See "gn help template" for more examples.
-```
-
-#### **Example**
-
-```
- template("my_template") {
- print(invoker.sources) # Prints [ "a.cc", "b.cc" ]
- print(defined(invoker.foo)) # Prints false.
- print(defined(invoker.bar)) # Prints true.
- }
-
- my_template("doom_melon") {
- sources = [ "a.cc", "b.cc" ]
- bar = 123
- }
-```
-### <a name="python_path"></a>**python_path**: Absolute path of Python.
-
-```
- Normally used in toolchain definitions if running some command requires
- Python. You will normally not need this when invoking scripts since GN
- automatically finds it for you.
-```
-### <a name="root_build_dir"></a>**root_build_dir**: [string] Directory where build commands are run.
-
-```
- This is the root build output directory which will be the current directory
- when executing all compilers and scripts.
-
- Most often this is used with rebase_path (see "gn help rebase_path") to
- convert arguments to be relative to a script's current directory.
-```
-### <a name="root_gen_dir"></a>**root_gen_dir**: Directory for the toolchain's generated files.
-
-```
- Absolute path to the root of the generated output directory tree for the
- current toolchain. An example would be "//out/Debug/gen" for the default
- toolchain, or "//out/Debug/arm/gen" for the "arm" toolchain.
-
- This is primarily useful for setting up include paths for generated files. If
- you are passing this to a script, you will want to pass it through
- rebase_path() (see "gn help rebase_path") to convert it to be relative to the
- build directory.
-
- See also "target_gen_dir" which is usually a better location for generated
- files. It will be inside the root generated dir.
-```
-### <a name="root_out_dir"></a>**root_out_dir**: [string] Root directory for toolchain output files.
-
-```
- Absolute path to the root of the output directory tree for the current
- toolchain. It will not have a trailing slash.
-
- For the default toolchain this will be the same as the root_build_dir. An
- example would be "//out/Debug" for the default toolchain, or
- "//out/Debug/arm" for the "arm" toolchain.
-
- This is primarily useful for setting up script calls. If you are passing this
- to a script, you will want to pass it through rebase_path() (see "gn help
- rebase_path") to convert it to be relative to the build directory.
-
- See also "target_out_dir" which is usually a better location for output
- files. It will be inside the root output dir.
-```
-
-#### **Example**
-
-```
- action("myscript") {
- # Pass the output dir to the script.
- args = [ "-o", rebase_path(root_out_dir, root_build_dir) ]
- }
-```
-### <a name="target_cpu"></a>**target_cpu**: The desired cpu architecture for the build.
-
-```
- This value should be used to indicate the desired architecture for the
- primary objects of the build. It will match the cpu architecture of the
- default toolchain, but not necessarily the current toolchain.
-
- In many cases, this is the same as "host_cpu", but in the case of
- cross-compiles, this can be set to something different. This value is
- different from "current_cpu" in that it does not change based on the current
- toolchain. When writing rules, "current_cpu" should be used rather than
- "target_cpu" most of the time.
-
- This value is not used internally by GN for any purpose, so it may be set to
- whatever value is needed for the build. GN defaults this value to the empty
- string ("") and the configuration files should set it to an appropriate value
- (e.g., setting it to the value of "host_cpu") if it is not overridden on the
- command line or in the args.gn file.
-```
-
-#### **Possible values**
-
-```
- - "x86"
- - "x64"
- - "arm"
- - "arm64"
- - "mipsel"
-```
-### <a name="target_gen_dir"></a>**target_gen_dir**: Directory for a target's generated files.
-
-```
- Absolute path to the target's generated file directory. This will be the
- "root_gen_dir" followed by the relative path to the current build file. If
- your file is in "//tools/doom_melon" then target_gen_dir would be
- "//out/Debug/gen/tools/doom_melon". It will not have a trailing slash.
-
- This is primarily useful for setting up include paths for generated files. If
- you are passing this to a script, you will want to pass it through
- rebase_path() (see "gn help rebase_path") to convert it to be relative to the
- build directory.
-
- See also "gn help root_gen_dir".
-```
-
-#### **Example**
-
-```
- action("myscript") {
- # Pass the generated output dir to the script.
- args = [ "-o", rebase_path(target_gen_dir, root_build_dir) ]"
- }
-```
-### <a name="target_name"></a>**target_name**: [string] The name of the current target.
-
-```
- Inside a target or template invocation, this variable refers to the name
- given to the target or template invocation. Outside of these, this variable
- is undefined.
-
- This is most often used in template definitions to name targets defined in
- the template based on the name of the invocation. This is necessary both to
- ensure generated targets have unique names and to generate a target with the
- exact name of the invocation that other targets can depend on.
-
- Be aware that this value will always reflect the innermost scope. So when
- defining a target inside a template, target_name will refer to the target
- rather than the template invocation. To get the name of the template
- invocation in this case, you should save target_name to a temporary variable
- outside of any target definitions.
-
- See "gn help template" for more examples.
-```
-
-#### **Example**
-
-```
- executable("doom_melon") {
- print(target_name) # Prints "doom_melon".
- }
-
- template("my_template") {
- print(target_name) # Prints "space_ray" when invoked below.
-
- executable(target_name + "_impl") {
- print(target_name) # Prints "space_ray_impl".
- }
- }
-
- my_template("space_ray") {
- }
-```
-### <a name="target_os"></a>**target_os**: The desired operating system for the build.
-
-```
- This value should be used to indicate the desired operating system for the
- primary object(s) of the build. It will match the OS of the default
- toolchain.
-
- In many cases, this is the same as "host_os", but in the case of
- cross-compiles, it may be different. This variable differs from "current_os"
- in that it can be referenced from inside any toolchain and will always return
- the initial value.
-
- This should be set to the most specific value possible. So, "android" or
- "chromeos" should be used instead of "linux" where applicable, even though
- Android and ChromeOS are both Linux variants. This can mean that one needs to
- write
-
- if (target_os == "android" || target_os == "linux") {
- # ...
- }
-
- and so forth.
-
- This value is not used internally by GN for any purpose, so it may be set to
- whatever value is needed for the build. GN defaults this value to the empty
- string ("") and the configuration files should set it to an appropriate value
- (e.g., setting it to the value of "host_os") if it is not set via the command
- line or in the args.gn file.
-```
-
-#### **Possible values**
-
-```
- - "android"
- - "chromeos"
- - "ios"
- - "linux"
- - "nacl"
- - "mac"
- - "win"
-```
-### <a name="target_out_dir"></a>**target_out_dir**: [string] Directory for target output files.
-
-```
- Absolute path to the target's generated file directory. If your current
- target is in "//tools/doom_melon" then this value might be
- "//out/Debug/obj/tools/doom_melon". It will not have a trailing slash.
-
- This is primarily useful for setting up arguments for calling scripts. If you
- are passing this to a script, you will want to pass it through rebase_path()
- (see "gn help rebase_path") to convert it to be relative to the build
- directory.
-
- See also "gn help root_out_dir".
-```
-
-#### **Example**
-
-```
- action("myscript") {
- # Pass the output dir to the script.
- args = [ "-o", rebase_path(target_out_dir, root_build_dir) ]"
-
- }
-```
-## <a name="target_variables"></a>Variables you set in targets
-
-### <a name="all_dependent_configs"></a>**all_dependent_configs**: Configs to be forced on dependents.
-
-```
- A list of config labels.
-
- All targets depending on this one, and recursively, all targets depending on
- those, will have the configs listed in this variable added to them. These
- configs will also apply to the current target.
-
- This addition happens in a second phase once a target and all of its
- dependencies have been resolved. Therefore, a target will not see these
- force-added configs in their "configs" variable while the script is running,
- and they can not be removed. As a result, this capability should generally
- only be used to add defines and include directories necessary to compile a
- target's headers.
-
- See also "public_configs".
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-```
-### <a name="allow_circular_includes_from"></a>**allow_circular_includes_from**: Permit includes from deps.
-
-```
- A list of target labels. Must be a subset of the target's "deps". These
- targets will be permitted to include headers from the current target despite
- the dependency going in the opposite direction.
-
- When you use this, both targets must be included in a final binary for it to
- link. To keep linker errors from happening, it is good practice to have all
- external dependencies depend only on one of the two targets, and to set the
- visibility on the other to enforce this. Thus the targets will always be
- linked together in any output.
-```
-
-#### **Details**
-
-```
- Normally, for a file in target A to include a file from target B, A must list
- B as a dependency. This invariant is enforced by the "gn check" command (and
- the --check flag to "gn gen" -- see "gn help check").
-
- Sometimes, two targets might be the same unit for linking purposes (two
- source sets or static libraries that would always be linked together in a
- final executable or shared library) and they each include headers from the
- other: you want A to be able to include B's headers, and B to include A's
- headers. This is not an ideal situation but is sometimes unavoidable.
-
- This list, if specified, lists which of the dependencies of the current
- target can include header files from the current target. That is, if A
- depends on B, B can only include headers from A if it is in A's
- allow_circular_includes_from list. Normally includes must follow the
- direction of dependencies, this flag allows them to go in the opposite
- direction.
-```
-
-#### **Danger**
-
-```
- In the above example, A's headers are likely to include headers from A's
- dependencies. Those dependencies may have public_configs that apply flags,
- defines, and include paths that make those headers work properly.
-
- With allow_circular_includes_from, B can include A's headers, and
- transitively from A's dependencies, without having the dependencies that
- would bring in the public_configs those headers need. The result may be
- errors or inconsistent builds.
-
- So when you use allow_circular_includes_from, make sure that any compiler
- settings, flags, and include directories are the same between both targets
- (consider putting such things in a shared config they can both reference).
- Make sure the dependencies are also the same (you might consider a group to
- collect such dependencies they both depend on).
-```
-
-#### **Example**
-
-```
- source_set("a") {
- deps = [ ":b", ":a_b_shared_deps" ]
- allow_circular_includes_from = [ ":b" ]
- ...
- }
-
- source_set("b") {
- deps = [ ":a_b_shared_deps" ]
- # Sources here can include headers from a despite lack of deps.
- ...
- }
-
- group("a_b_shared_deps") {
- public_deps = [ ":c" ]
- }
-```
-### <a name="arflags"></a>**arflags**: Arguments passed to static_library archiver.
-
-```
- A list of flags passed to the archive/lib command that creates static
- libraries.
-
- arflags are NOT pushed to dependents, so applying arflags to source sets or
- any other target type will be a no-op. As with ldflags, you could put the
- arflags in a config and set that as a public or "all dependent" config, but
- that will likely not be what you want. If you have a chain of static
- libraries dependent on each other, this can cause the flags to propagate up
- to other static libraries. Due to the nature of how arflags are typically
- used, you will normally want to apply them directly on static_library targets
- themselves.
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-```
-### <a name="args"></a>**args**: Arguments passed to an action.
-
-```
- For action and action_foreach targets, args is the list of arguments to pass
- to the script. Typically you would use source expansion (see "gn help
- source_expansion") to insert the source file names.
-
- See also "gn help action" and "gn help action_foreach".
-```
-### <a name="asmflags"></a>**asmflags**: Flags passed to the assembler.
-
-```
- A list of strings.
-
- "asmflags" are passed to any invocation of a tool that takes an .asm or .S
- file as input.
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-```
-### <a name="assert_no_deps"></a>**assert_no_deps**: Ensure no deps on these targets.
-
-```
- A list of label patterns.
-
- This list is a list of patterns that must not match any of the transitive
- dependencies of the target. These include all public, private, and data
- dependencies, and cross shared library boundaries. This allows you to express
- that undesirable code isn't accidentally added to downstream dependencies in
- a way that might otherwise be difficult to notice.
-
- Checking does not cross executable boundaries. If a target depends on an
- executable, it's assumed that the executable is a tool that is producing part
- of the build rather than something that is linked and distributed. This
- allows assert_no_deps to express what is distributed in the final target
- rather than depend on the internal build steps (which may include
- non-distributable code).
-
- See "gn help label_pattern" for the format of the entries in the list. These
- patterns allow blacklisting individual targets or whole directory
- hierarchies.
-
- Sometimes it is desirable to enforce that many targets have no dependencies
- on a target or set of targets. One efficient way to express this is to create
- a group with the assert_no_deps rule on it, and make that group depend on all
- targets you want to apply that assertion to.
-```
-
-#### **Example**
-
-```
- executable("doom_melon") {
- deps = [ "//foo:bar" ]
- ...
- assert_no_deps = [
- "//evil/*", # Don't link any code from the evil directory.
- "//foo:test_support", # This target is also disallowed.
- ]
- }
-```
-### <a name="bundle_contents_dir"></a>**bundle_contents_dir**: Expansion of {{bundle_contents_dir}} in
-```
- create_bundle.
-
- A string corresponding to a path in $root_build_dir.
-
- This string is used by the "create_bundle" target to expand the
- {{bundle_contents_dir}} of the "bundle_data" target it depends on. This must
- correspond to a path under "bundle_root_dir".
-
- See "gn help bundle_root_dir" for examples.
-```
-### <a name="bundle_deps_filter"></a>**bundle_deps_filter**: [label list] A list of labels that are filtered out.
-
-```
- A list of target labels.
-
- This list contains target label patterns that should be filtered out when
- creating the bundle. Any target matching one of those label will be removed
- from the dependencies of the create_bundle target.
-
- This is mostly useful when creating application extension bundle as the
- application extension has access to runtime resources from the application
- bundle and thus do not require a second copy.
-
- See "gn help create_bundle" for more information.
-```
-
-#### **Example**
-
-```
- create_bundle("today_extension") {
- deps = [
- "//base"
- ]
- bundle_root_dir = "$root_out_dir/today_extension.appex"
- bundle_deps_filter = [
- # The extension uses //base but does not use any function calling into
- # third_party/icu and thus does not need the icudtl.dat file.
- "//third_party/icu:icudata",
- ]
- }
-```
-### <a name="bundle_executable_dir"></a>**bundle_executable_dir**: Expansion of {{bundle_executable_dir}} in
-```
- create_bundle.
-
- A string corresponding to a path in $root_build_dir.
-
- This string is used by the "create_bundle" target to expand the
- {{bundle_executable_dir}} of the "bundle_data" target it depends on. This
- must correspond to a path under "bundle_root_dir".
-
- See "gn help bundle_root_dir" for examples.
-```
-### <a name="bundle_plugins_dir"></a>**bundle_plugins_dir**: Expansion of {{bundle_plugins_dir}} in create_bundle.
-
-```
- A string corresponding to a path in $root_build_dir.
-
- This string is used by the "create_bundle" target to expand the
- {{bundle_plugins_dir}} of the "bundle_data" target it depends on. This must
- correspond to a path under "bundle_root_dir".
-
- See "gn help bundle_root_dir" for examples.
-```
-### <a name="bundle_resources_dir"></a>**bundle_resources_dir**: Expansion of {{bundle_resources_dir}} in
-```
- create_bundle.
-
- A string corresponding to a path in $root_build_dir.
-
- This string is used by the "create_bundle" target to expand the
- {{bundle_resources_dir}} of the "bundle_data" target it depends on. This must
- correspond to a path under "bundle_root_dir".
-
- See "gn help bundle_root_dir" for examples.
-```
-### <a name="bundle_root_dir"></a>**bundle_root_dir**: Expansion of {{bundle_root_dir}} in create_bundle.
-
-```
- A string corresponding to a path in root_build_dir.
-
- This string is used by the "create_bundle" target to expand the
- {{bundle_root_dir}} of the "bundle_data" target it depends on. This must
- correspond to a path under root_build_dir.
-```
-
-#### **Example**
-
-```
- bundle_data("info_plist") {
- sources = [ "Info.plist" ]
- outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
- }
-
- create_bundle("doom_melon.app") {
- deps = [ ":info_plist" ]
- bundle_root_dir = "${root_build_dir}/doom_melon.app"
- bundle_contents_dir = "${bundle_root_dir}/Contents"
- bundle_resources_dir = "${bundle_contents_dir}/Resources"
- bundle_executable_dir = "${bundle_contents_dir}/MacOS"
- bundle_plugins_dir = "${bundle_contents_dir}/PlugIns"
- }
-```
-### <a name="cflags*"></a>**cflags***: Flags passed to the C compiler.
-
-```
- A list of strings.
-
- "cflags" are passed to all invocations of the C, C++, Objective C, and
- Objective C++ compilers.
-
- To target one of these variants individually, use "cflags_c", "cflags_cc",
- "cflags_objc", and "cflags_objcc", respectively. These variant-specific
- versions of cflags* will be appended on the compiler command line after
- "cflags".
-
- See also "asmflags" for flags for assembly-language files.
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-```
-### <a name="cflags*"></a>**cflags***: Flags passed to the C compiler.
-
-```
- A list of strings.
-
- "cflags" are passed to all invocations of the C, C++, Objective C, and
- Objective C++ compilers.
-
- To target one of these variants individually, use "cflags_c", "cflags_cc",
- "cflags_objc", and "cflags_objcc", respectively. These variant-specific
- versions of cflags* will be appended on the compiler command line after
- "cflags".
-
- See also "asmflags" for flags for assembly-language files.
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-```
-### <a name="cflags*"></a>**cflags***: Flags passed to the C compiler.
-
-```
- A list of strings.
-
- "cflags" are passed to all invocations of the C, C++, Objective C, and
- Objective C++ compilers.
-
- To target one of these variants individually, use "cflags_c", "cflags_cc",
- "cflags_objc", and "cflags_objcc", respectively. These variant-specific
- versions of cflags* will be appended on the compiler command line after
- "cflags".
-
- See also "asmflags" for flags for assembly-language files.
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-```
-### <a name="cflags*"></a>**cflags***: Flags passed to the C compiler.
-
-```
- A list of strings.
-
- "cflags" are passed to all invocations of the C, C++, Objective C, and
- Objective C++ compilers.
-
- To target one of these variants individually, use "cflags_c", "cflags_cc",
- "cflags_objc", and "cflags_objcc", respectively. These variant-specific
- versions of cflags* will be appended on the compiler command line after
- "cflags".
-
- See also "asmflags" for flags for assembly-language files.
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-```
-### <a name="cflags*"></a>**cflags***: Flags passed to the C compiler.
-
-```
- A list of strings.
-
- "cflags" are passed to all invocations of the C, C++, Objective C, and
- Objective C++ compilers.
-
- To target one of these variants individually, use "cflags_c", "cflags_cc",
- "cflags_objc", and "cflags_objcc", respectively. These variant-specific
- versions of cflags* will be appended on the compiler command line after
- "cflags".
-
- See also "asmflags" for flags for assembly-language files.
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-```
-### <a name="check_includes"></a>**check_includes**: [boolean] Controls whether a target's files are checked.
-
-```
- When true (the default), the "gn check" command (as well as "gn gen" with the
- --check flag) will check this target's sources and headers for proper
- dependencies.
-
- When false, the files in this target will be skipped by default. This does
- not affect other targets that depend on the current target, it just skips
- checking the includes of the current target's files.
-
- If there are a few conditionally included headers that trip up checking, you
- can exclude headers individually by annotating them with "nogncheck" (see "gn
- help nogncheck").
-
- The topic "gn help check" has general information on how checking works and
- advice on how to pass a check in problematic cases.
-```
-
-#### **Example**
-
-```
- source_set("busted_includes") {
- # This target's includes are messed up, exclude it from checking.
- check_includes = false
- ...
- }
-```
-### <a name="code_signing_args"></a>**code_signing_args**: [string list] Arguments passed to code signing script.
-
-```
- For create_bundle targets, code_signing_args is the list of arguments to pass
- to the code signing script. Typically you would use source expansion (see "gn
- help source_expansion") to insert the source file names.
-
- See also "gn help create_bundle".
-```
-### <a name="code_signing_outputs"></a>**code_signing_outputs**: [file list] Output files for code signing step.
-
-```
- Outputs from the code signing step of a create_bundle target. Must refer to
- files in the build directory.
-
- See also "gn help create_bundle".
-```
-### <a name="code_signing_script"></a>**code_signing_script**: [file name] Script for code signing."
-
-```
- An absolute or buildfile-relative file name of a Python script to run for a
- create_bundle target to perform code signing step.
-
- See also "gn help create_bundle".
-```
-### <a name="code_signing_sources"></a>**code_signing_sources**: [file list] Sources for code signing step.
-
-```
- A list of files used as input for code signing script step of a create_bundle
- target. Non-absolute paths will be resolved relative to the current build
- file.
-
- See also "gn help create_bundle".
-```
-### <a name="complete_static_lib"></a>**complete_static_lib**: [boolean] Links all deps into a static library.
-
-```
- A static library normally doesn't include code from dependencies, but instead
- forwards the static libraries and source sets in its deps up the dependency
- chain until a linkable target (an executable or shared library) is reached.
- The final linkable target only links each static library once, even if it
- appears more than once in its dependency graph.
-
- In some cases the static library might be the final desired output. For
- example, you may be producing a static library for distribution to third
- parties. In this case, the static library should include code for all
- dependencies in one complete package. However, complete static libraries
- themselves are never linked into other complete static libraries. All
- complete static libraries are for distribution and linking them in would
- cause code duplication in this case. If the static library is not for
- distribution, it should not be complete.
-
- GN treats non-complete static libraries as source sets when they are linked
- into complete static libraries. This is done because some tools like AR do
- not handle dependent static libraries properly. This makes it easier to write
- "alink" rules.
-
- In rare cases it makes sense to list a header in more than one target if it
- could be considered conceptually a member of both. libraries.
-```
-
-#### **Example**
-
-```
- static_library("foo") {
- complete_static_lib = true
- deps = [ "bar" ]
- }
-```
-### <a name="configs"></a>**configs**: Configs applying to this target or config.
-
-```
- A list of config labels.
-```
-
-#### **Configs on a target**
-
-```
- When used on a target, the include_dirs, defines, etc. in each config are
- appended in the order they appear to the compile command for each file in the
- target. They will appear after the include_dirs, defines, etc. that the
- target sets directly.
-
- Since configs apply after the values set on a target, directly setting a
- compiler flag will prepend it to the command line. If you want to append a
- flag instead, you can put that flag in a one-off config and append that
- config to the target's configs list.
-
- The build configuration script will generally set up the default configs
- applying to a given target type (see "set_defaults"). When a target is being
- defined, it can add to or remove from this list.
-```
-
-#### **Configs on a config**
-
-```
- It is possible to create composite configs by specifying configs on a config.
- One might do this to forward values, or to factor out blocks of settings from
- very large configs into more manageable named chunks.
-
- In this case, the composite config is expanded to be the concatenation of its
- own values, and in order, the values from its sub-configs *before* anything
- else happens. This has some ramifications:
-
- - A target has no visibility into a config's sub-configs. Target code only
- sees the name of the composite config. It can't remove sub-configs or opt
- in to only parts of it. The composite config may not even be defined
- before the target is.
-
- - You can get duplication of values if a config is listed twice, say, on a
- target and in a sub-config that also applies. In other cases, the configs
- applying to a target are de-duped. It's expected that if a config is
- listed as a sub-config that it is only used in that context. (Note that
- it's possible to fix this and de-dupe, but it's not normally relevant and
- complicates the implementation.)
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-```
-
-#### **Example**
-
-```
- # Configs on a target.
- source_set("foo") {
- # Don't use the default RTTI config that BUILDCONFIG applied to us.
- configs -= [ "//build:no_rtti" ]
-
- # Add some of our own settings.
- configs += [ ":mysettings" ]
- }
-
- # Create a default_optimization config that forwards to one of a set of more
- # specialized configs depending on build flags. This pattern is useful
- # because it allows a target to opt in to either a default set, or a more
- # specific set, while avoid duplicating the settings in two places.
- config("super_optimization") {
- cflags = [ ... ]
- }
- config("default_optimization") {
- if (optimize_everything) {
- configs = [ ":super_optimization" ]
- } else {
- configs = [ ":no_optimization" ]
- }
- }
-```
-### <a name="data"></a>**data**: Runtime data file dependencies.
-
-```
- Lists files or directories required to run the given target. These are
- typically data files or directories of data files. The paths are interpreted
- as being relative to the current build file. Since these are runtime
- dependencies, they do not affect which targets are built or when. To declare
- input files to a script, use "inputs".
-
- Appearing in the "data" section does not imply any special handling such as
- copying them to the output directory. This is just used for declaring runtime
- dependencies. Runtime dependencies can be queried using the "runtime_deps"
- category of "gn desc" or written during build generation via
- "--runtime-deps-list-file".
-
- GN doesn't require data files to exist at build-time. So actions that produce
- files that are in turn runtime dependencies can list those generated files
- both in the "outputs" list as well as the "data" list.
-
- By convention, directories are listed with a trailing slash:
- data = [ "test/data/" ]
- However, no verification is done on these so GN doesn't enforce this. The
- paths are just rebased and passed along when requested.
-
- Note: On iOS and macOS, create_bundle targets will not be recursed into when
- gathering data. See "gn help create_bundle" for details.
-
- See "gn help runtime_deps" for how these are used.
-```
-### <a name="data_deps"></a>**data_deps**: Non-linked dependencies.
-
-```
- A list of target labels.
-
- Specifies dependencies of a target that are not actually linked into the
- current target. Such dependencies will be built and will be available at
- runtime.
-
- This is normally used for things like plugins or helper programs that a
- target needs at runtime.
-
- Note: On iOS and macOS, create_bundle targets will not be recursed into when
- gathering data_deps. See "gn help create_bundle" for details.
-
- See also "gn help deps" and "gn help data".
-```
-
-#### **Example**
-
-```
- executable("foo") {
- deps = [ "//base" ]
- data_deps = [ "//plugins:my_runtime_plugin" ]
- }
-```
-### <a name="defines"></a>**defines**: C preprocessor defines.
-
-```
- A list of strings
-
- These strings will be passed to the C/C++ compiler as #defines. The strings
- may or may not include an "=" to assign a value.
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-```
-
-#### **Example**
-
-```
- defines = [ "AWESOME_FEATURE", "LOG_LEVEL=3" ]
-```
-### <a name="depfile"></a>**depfile**: [string] File name for input dependencies for actions.
-
-```
- If nonempty, this string specifies that the current action or action_foreach
- target will generate the given ".d" file containing the dependencies of the
- input. Empty or unset means that the script doesn't generate the files.
-
- A depfile should be used only when a target depends on files that are not
- already specified by a target's inputs and sources. Likewise, depfiles should
- specify only those dependencies not already included in sources or inputs.
-
- The .d file should go in the target output directory. If you have more than
- one source file that the script is being run over, you can use the output
- file expansions described in "gn help action_foreach" to name the .d file
- according to the input."
-
- The format is that of a Makefile and all paths must be relative to the root
- build directory. Only one output may be listed and it must match the first
- output of the action.
-
- Although depfiles are created by an action, they should not be listed in the
- action's "outputs" unless another target will use the file as an input.
-```
-
-#### **Example**
-
-```
- action_foreach("myscript_target") {
- script = "myscript.py"
- sources = [ ... ]
-
- # Locate the depfile in the output directory named like the
- # inputs but with a ".d" appended.
- depfile = "$relative_target_output_dir/{{source_name}}.d"
-
- # Say our script uses "-o <d file>" to indicate the depfile.
- args = [ "{{source}}", "-o", depfile ]
- }
-```
-### <a name="deps"></a>**deps**: Private linked dependencies.
-
-```
- A list of target labels.
-
- Specifies private dependencies of a target. Private dependencies are
- propagated up the dependency tree and linked to dependent targets, but do not
- grant the ability to include headers from the dependency. Public configs are
- not forwarded.
-```
-
-#### **Details of dependency propagation**
-
-```
- Source sets, shared libraries, and non-complete static libraries will be
- propagated up the dependency tree across groups, non-complete static
- libraries and source sets.
-
- Executables, shared libraries, and complete static libraries will link all
- propagated targets and stop propagation. Actions and copy steps also stop
- propagation, allowing them to take a library as an input but not force
- dependents to link to it.
-
- Propagation of all_dependent_configs and public_configs happens independently
- of target type. all_dependent_configs are always propagated across all types
- of targets, and public_configs are always propagated across public deps of
- all types of targets.
-
- Data dependencies are propagated differently. See "gn help data_deps" and
- "gn help runtime_deps".
-
- See also "public_deps".
-```
-### <a name="friend"></a>**friend**: Allow targets to include private headers.
-
-```
- A list of label patterns (see "gn help label_pattern") that allow dependent
- targets to include private headers. Applies to all binary targets.
-
- Normally if a target lists headers in the "public" list (see "gn help
- public"), other headers are implicitly marked as private. Private headers
- can not be included by other targets, even with a public dependency path.
- The "gn check" function performs this validation.
-
- A friend declaration allows one or more targets to include private headers.
- This is useful for things like unit tests that are closely associated with a
- target and require internal knowledge without opening up all headers to be
- included by all dependents.
-
- A friend target does not allow that target to include headers when no
- dependency exists. A public dependency path must still exist between two
- targets to include any headers from a destination target. The friend
- annotation merely allows the use of headers that would otherwise be
- prohibited because they are private.
-
- The friend annotation is matched only against the target containing the file
- with the include directive. Friend annotations are not propagated across
- public or private dependencies. Friend annotations do not affect visibility.
-```
-
-#### **Example**
-
-```
- static_library("lib") {
- # This target can include our private headers.
- friend = [ ":unit_tests" ]
-
- public = [
- "public_api.h", # Normal public API for dependent targets.
- ]
-
- # Private API and sources.
- sources = [
- "a_source_file.cc",
-
- # Normal targets that depend on this one won't be able to include this
- # because this target defines a list of "public" headers. Without the
- # "public" list, all headers are implicitly public.
- "private_api.h",
- ]
- }
-
- executable("unit_tests") {
- sources = [
- # This can include "private_api.h" from the :lib target because it
- # depends on that target and because of the friend annotation.
- "my_test.cc",
- ]
-
- deps = [
- ":lib", # Required for the include to be allowed.
- ]
- }
-```
-### <a name="include_dirs"></a>**include_dirs**: Additional include directories.
-
-```
- A list of source directories.
-
- The directories in this list will be added to the include path for the files
- in the affected target.
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-```
-
-#### **Example**
-
-```
- include_dirs = [ "src/include", "//third_party/foo" ]
-```
-### <a name="inputs"></a>**inputs**: Additional compile-time dependencies.
-
-```
- Inputs are compile-time dependencies of the current target. This means that
- all inputs must be available before compiling any of the sources or executing
- any actions.
-
- Inputs are typically only used for action and action_foreach targets.
-```
-
-#### **Inputs for actions**
-
-```
- For action and action_foreach targets, inputs should be the inputs to script
- that don't vary. These should be all .py files that the script uses via
- imports (the main script itself will be an implicit dependency of the action
- so need not be listed).
-
- For action targets, inputs and sources are treated the same, but from a style
- perspective, it's recommended to follow the same rule as action_foreach and
- put helper files in the inputs, and the data used by the script (if any) in
- sources.
-
- Note that another way to declare input dependencies from an action is to have
- the action write a depfile (see "gn help depfile"). This allows the script to
- dynamically write input dependencies, that might not be known until actually
- executing the script. This is more efficient than doing processing while
- running GN to determine the inputs, and is easier to keep in-sync than
- hardcoding the list.
-```
-
-#### **Script input gotchas**
-
-```
- It may be tempting to write a script that enumerates all files in a directory
- as inputs. Don't do this! Even if you specify all the files in the inputs or
- sources in the GN target (or worse, enumerate the files in an exec_script
- call when running GN, which will be slow), the dependencies will be broken.
-
- The problem happens if a file is ever removed because the inputs are not
- listed on the command line to the script. Because the script hasn't changed
- and all inputs are up to date, the script will not re-run and you will get a
- stale build. Instead, either list all inputs on the command line to the
- script, or if there are many, create a separate list file that the script
- reads. As long as this file is listed in the inputs, the build will detect
- when it has changed in any way and the action will re-run.
-```
-
-#### **Inputs for binary targets**
-
-```
- Any input dependencies will be resolved before compiling any sources or
- linking the target. Normally, all actions that a target depends on will be run
- before any files in a target are compiled. So if you depend on generated
- headers, you do not typically need to list them in the inputs section.
-
- Inputs for binary targets will be treated as implicit dependencies, meaning
- that changes in any of the inputs will force all sources in the target to be
- recompiled. If an input only applies to a subset of source files, you may
- want to split those into a separate target to avoid unnecessary recompiles.
-```
-
-#### **Example**
-
-```
- action("myscript") {
- script = "domything.py"
- inputs = [ "input.data" ]
- }
-```
-### <a name="ldflags"></a>**ldflags**: Flags passed to the linker.
-
-```
- A list of strings.
-
- These flags are passed on the command-line to the linker and generally
- specify various linking options. Most targets will not need these and will
- use "libs" and "lib_dirs" instead.
-
- ldflags are NOT pushed to dependents, so applying ldflags to source sets or
- static libraries will be a no-op. If you want to apply ldflags to dependent
- targets, put them in a config and set it in the all_dependent_configs or
- public_configs.
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-```
-### <a name="lib_dirs"></a>**lib_dirs**: Additional library directories.
-
-```
- A list of directories.
-
- Specifies additional directories passed to the linker for searching for the
- required libraries. If an item is not an absolute path, it will be treated as
- being relative to the current build file.
-
- libs and lib_dirs work differently than other flags in two respects.
- First, then are inherited across static library boundaries until a
- shared library or executable target is reached. Second, they are
- uniquified so each one is only passed once (the first instance of it
- will be the one used).
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-
- For "libs" and "lib_dirs" only, the values propagated from
- dependencies (as described above) are applied last assuming they
- are not already in the list.
-```
-
-#### **Example**
-
-```
- lib_dirs = [ "/usr/lib/foo", "lib/doom_melon" ]
-```
-### <a name="libs"></a>**libs**: Additional libraries to link.
-
-```
- A list of library names or library paths.
-
- These libraries will be linked into the final binary (executable or shared
- library) containing the current target.
-
- libs and lib_dirs work differently than other flags in two respects.
- First, then are inherited across static library boundaries until a
- shared library or executable target is reached. Second, they are
- uniquified so each one is only passed once (the first instance of it
- will be the one used).
-```
-
-#### **Types of libs**
-
-```
- There are several different things that can be expressed in libs:
-
- File paths
- Values containing '/' will be treated as references to files in the
- checkout. They will be rebased to be relative to the build directory and
- specified in the "libs" for linker tools. This facility should be used
- for libraries that are checked in to the version control. For libraries
- that are generated by the build, use normal GN deps to link them.
-
- System libraries
- Values not containing '/' will be treated as system library names. These
- will be passed unmodified to the linker and prefixed with the
- "lib_switch" attribute of the linker tool. Generally you would set the
- "lib_dirs" so the given library is found. Your BUILD.gn file should not
- specify the switch (like "-l"): this will be encoded in the "lib_switch"
- of the tool.
-
- Apple frameworks
- System libraries ending in ".framework" will be special-cased: the switch
- "-framework" will be prepended instead of the lib_switch, and the
- ".framework" suffix will be trimmed. This is to support the way Mac links
- framework dependencies.
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-
- For "libs" and "lib_dirs" only, the values propagated from
- dependencies (as described above) are applied last assuming they
- are not already in the list.
-```
-
-#### **Examples**
-
-```
- On Windows:
- libs = [ "ctl3d.lib" ]
-
- On Linux:
- libs = [ "ld" ]
-```
-### <a name="output_dir"></a>**output_dir**: [directory] Directory to put output file in.
-
-```
- For library and executable targets, overrides the directory for the final
- output. This must be in the root_build_dir or a child thereof.
-
- This should generally be in the root_out_dir or a subdirectory thereof (the
- root_out_dir will be the same as the root_build_dir for the default
- toolchain, and will be a subdirectory for other toolchains). Not putting the
- output in a subdirectory of root_out_dir can result in collisions between
- different toolchains, so you will need to take steps to ensure that your
- target is only present in one toolchain.
-
- Normally the toolchain specifies the output directory for libraries and
- executables (see "gn help tool"). You will have to consult that for the
- default location. The default location will be used if output_dir is
- undefined or empty.
-```
-
-#### **Example**
-
-```
- shared_library("doom_melon") {
- output_dir = "$root_out_dir/plugin_libs"
- ...
- }
-```
-### <a name="output_extension"></a>**output_extension**: Value to use for the output's file extension.
-
-```
- Normally the file extension for a target is based on the target type and the
- operating system, but in rare cases you will need to override the name (for
- example to use "libfreetype.so.6" instead of libfreetype.so on Linux).
-
- This value should not include a leading dot. If undefined, the default
- specified on the tool will be used. If set to the empty string, no output
- extension will be used.
-
- The output_extension will be used to set the "{{output_extension}}" expansion
- which the linker tool will generally use to specify the output file name. See
- "gn help tool".
-```
-
-#### **Example**
-
-```
- shared_library("freetype") {
- if (is_linux) {
- # Call the output "libfreetype.so.6"
- output_extension = "so.6"
- }
- ...
- }
-
- # On Windows, generate a "mysettings.cpl" control panel applet. Control panel
- # applets are actually special shared libraries.
- if (is_win) {
- shared_library("mysettings") {
- output_extension = "cpl"
- ...
- }
- }
-```
-### <a name="output_name"></a>**output_name**: Define a name for the output file other than the default.
-
-```
- Normally the output name of a target will be based on the target name, so the
- target "//foo/bar:bar_unittests" will generate an output file such as
- "bar_unittests.exe" (using Windows as an example).
-
- Sometimes you will want an alternate name to avoid collisions or if the
- internal name isn't appropriate for public distribution.
-
- The output name should have no extension or prefixes, these will be added
- using the default system rules. For example, on Linux an output name of "foo"
- will produce a shared library "libfoo.so". There is no way to override the
- output prefix of a linker tool on a per- target basis. If you need more
- flexibility, create a copy target to produce the file you want.
-
- This variable is valid for all binary output target types.
-```
-
-#### **Example**
-
-```
- static_library("doom_melon") {
- output_name = "fluffy_bunny"
- }
-```
-### <a name="output_prefix_override"></a>**output_prefix_override**: Don't use prefix for output name.
-
-```
- A boolean that overrides the output prefix for a target. Defaults to false.
-
- Some systems use prefixes for the names of the final target output file. The
- normal example is "libfoo.so" on Linux for a target named "foo".
-
- The output prefix for a given target type is specified on the linker tool
- (see "gn help tool"). Sometimes this prefix is undesired.
-
- See also "gn help output_extension".
-```
-
-#### **Example**
-
-```
- shared_library("doom_melon") {
- # Normally this will produce "libdoom_melon.so" on Linux. Setting this flag
- # will produce "doom_melon.so".
- output_prefix_override = true
- ...
- }
-```
-### <a name="outputs"></a>**outputs**: Output files for actions and copy targets.
-
-```
- Outputs is valid for "copy", "action", and "action_foreach" target types and
- indicates the resulting files. Outputs must always refer to files in the
- build directory.
-
- copy
- Copy targets should have exactly one entry in the outputs list. If there is
- exactly one source, this can be a literal file name or a source expansion.
- If there is more than one source, this must contain a source expansion to
- map a single input name to a single output name. See "gn help copy".
-
- action_foreach
- Action_foreach targets must always use source expansions to map input files
- to output files. There can be more than one output, which means that each
- invocation of the script will produce a set of files (presumably based on
- the name of the input file). See "gn help action_foreach".
-
- action
- Action targets (excluding action_foreach) must list literal output file(s)
- with no source expansions. See "gn help action".
-```
-### <a name="partial_info_plist"></a>**partial_info_plist**: [filename] Path plist from asset catalog compiler.
-
-```
- Valid for create_bundle target, corresponds to the path for the partial
- Info.plist created by the asset catalog compiler that needs to be merged
- with the application Info.plist (usually done by the code signing script).
-
- The file will be generated regardless of whether the asset compiler has
- been invoked or not. See "gn help create_bundle".
-```
-### <a name="pool"></a>**pool**: Label of the pool used by the action.
-
-```
- A fully-qualified label representing the pool that will be used for the
- action. Pools are defined using the pool() {...} declaration.
-```
-
-#### **Example**
-
-```
- action("action") {
- pool = "//build:custom_pool"
- ...
- }
-```
-### <a name="precompiled_header"></a>**precompiled_header**: [string] Header file to precompile.
-
-```
- Precompiled headers will be used when a target specifies this value, or a
- config applying to this target specifies this value. In addition, the tool
- corresponding to the source files must also specify precompiled headers (see
- "gn help tool"). The tool will also specify what type of precompiled headers
- to use, by setting precompiled_header_type to either "gcc" or "msvc".
-
- The precompiled header/source variables can be specified on a target or a
- config, but must be the same for all configs applying to a given target since
- a target can only have one precompiled header.
-
- If you use both C and C++ sources, the precompiled header and source file
- will be compiled once per language. You will want to make sure to wrap C++
- includes in __cplusplus #ifdefs so the file will compile in C mode.
-```
-
-#### **GCC precompiled headers**
-
-```
- When using GCC-style precompiled headers, "precompiled_source" contains the
- path of a .h file that is precompiled and then included by all source files
- in targets that set "precompiled_source".
-
- The value of "precompiled_header" is not used with GCC-style precompiled
- headers.
-```
-
-#### **MSVC precompiled headers**
-
-```
- When using MSVC-style precompiled headers, the "precompiled_header" value is
- a string corresponding to the header. This is NOT a path to a file that GN
- recognises, but rather the exact string that appears in quotes after
- an #include line in source code. The compiler will match this string against
- includes or forced includes (/FI).
-
- MSVC also requires a source file to compile the header with. This must be
- specified by the "precompiled_source" value. In contrast to the header value,
- this IS a GN-style file name, and tells GN which source file to compile to
- make the .pch file used for subsequent compiles.
-
- For example, if the toolchain specifies MSVC headers:
-
- toolchain("vc_x64") {
- ...
- tool("cxx") {
- precompiled_header_type = "msvc"
- ...
-
- You might make a config like this:
-
- config("use_precompiled_headers") {
- precompiled_header = "build/precompile.h"
- precompiled_source = "//build/precompile.cc"
-
- # Either your source files should #include "build/precompile.h"
- # first, or you can do this to force-include the header.
- cflags = [ "/FI$precompiled_header" ]
- }
-
- And then define a target that uses the config:
-
- executable("doom_melon") {
- configs += [ ":use_precompiled_headers" ]
- ...
-```
-### <a name="precompiled_header_type"></a>**precompiled_header_type**: [string] "gcc" or "msvc".
-
-```
- See "gn help precompiled_header".
-```
-### <a name="precompiled_source"></a>**precompiled_source**: [file name] Source file to precompile.
-
-```
- The source file that goes along with the precompiled_header when using
- "msvc"-style precompiled headers. It will be implicitly added to the sources
- of the target. See "gn help precompiled_header".
-```
-### <a name="product_type"></a>**product_type**: Product type for Xcode projects.
-
-```
- Correspond to the type of the product of a create_bundle target. Only
- meaningful to Xcode (used as part of the Xcode project generation).
-
- When generating Xcode project files, only create_bundle target with a
- non-empty product_type will have a corresponding target in Xcode project.
-```
-### <a name="public"></a>**public**: Declare public header files for a target.
-
-```
- A list of files that other targets can include. These permissions are checked
- via the "check" command (see "gn help check").
-
- If no public files are declared, other targets (assuming they have visibility
- to depend on this target) can include any file in the sources list. If this
- variable is defined on a target, dependent targets may only include files on
- this whitelist unless that target is marked as a friend (see "gn help
- friend").
-
- Header file permissions are also subject to visibility. A target must be
- visible to another target to include any files from it at all and the public
- headers indicate which subset of those files are permitted. See "gn help
- visibility" for more.
-
- Public files are inherited through the dependency tree. So if there is a
- dependency A -> B -> C, then A can include C's public headers. However, the
- same is NOT true of visibility, so unless A is in C's visibility list, the
- include will be rejected.
-
- GN only knows about files declared in the "sources" and "public" sections of
- targets. If a file is included that is not known to the build, it will be
- allowed.
-
- It is common for test targets to need to include private headers for their
- associated code. In this case, list the test target in the "friend" list of
- the target that owns the private header to allow the inclusion. See
- "gn help friend" for more.
-
- When a binary target has no explicit or implicit public headers (a "public"
- list is defined but is empty), GN assumes that the target can not propagate
- any compile-time dependencies up the dependency tree. In this case, the build
- can be parallelized more efficiently.
- Say there are dependencies:
- A (shared library) -> B (shared library) -> C (action).
- Normally C must complete before any source files in A can compile (because
- there might be generated includes). But when B explicitly declares no public
- headers, C can execute in parallel with A's compile steps. C must still be
- complete before any dependents link.
-```
-
-#### **Examples**
-
-```
- These exact files are public:
- public = [ "foo.h", "bar.h" ]
-
- No files are public (no targets may include headers from this one):
- # This allows starting compile in dependent targets earlier.
- public = []
-```
-### <a name="public_configs"></a>**public_configs**: Configs to be applied on dependents.
-
-```
- A list of config labels.
-
- Targets directly depending on this one will have the configs listed in this
- variable added to them. These configs will also apply to the current target.
-
- This addition happens in a second phase once a target and all of its
- dependencies have been resolved. Therefore, a target will not see these
- force-added configs in their "configs" variable while the script is running,
- and they can not be removed. As a result, this capability should generally
- only be used to add defines and include directories necessary to compile a
- target's headers.
-
- See also "all_dependent_configs".
-```
-
-#### **Ordering of flags and values**
-
-```
- 1. Those set on the current target (not in a config).
- 2. Those set on the "configs" on the target in order that the
- configs appear in the list.
- 3. Those set on the "all_dependent_configs" on the target in order
- that the configs appear in the list.
- 4. Those set on the "public_configs" on the target in order that
- those configs appear in the list.
- 5. all_dependent_configs pulled from dependencies, in the order of
- the "deps" list. This is done recursively. If a config appears
- more than once, only the first occurence will be used.
- 6. public_configs pulled from dependencies, in the order of the
- "deps" list. If a dependency is public, they will be applied
- recursively.
-```
-### <a name="public_deps"></a>**public_deps**: Declare public dependencies.
-
-```
- Public dependencies are like private dependencies (see "gn help deps") but
- additionally express that the current target exposes the listed deps as part
- of its public API.
-
- This has several ramifications:
-
- - public_configs that are part of the dependency are forwarded to direct
- dependents.
-
- - Public headers in the dependency are usable by dependents (includes do
- not require a direct dependency or visibility).
-
- - If the current target is a shared library, other shared libraries that it
- publicly depends on (directly or indirectly) are propagated up the
- dependency tree to dependents for linking.
-```
-
-#### **Discussion**
-
-```
- Say you have three targets: A -> B -> C. C's visibility may allow B to depend
- on it but not A. Normally, this would prevent A from including any headers
- from C, and C's public_configs would apply only to B.
-
- If B lists C in its public_deps instead of regular deps, A will now inherit
- C's public_configs and the ability to include C's public headers.
-
- Generally if you are writing a target B and you include C's headers as part
- of B's public headers, or targets depending on B should consider B and C to
- be part of a unit, you should use public_deps instead of deps.
-```
-
-#### **Example**
-
-```
- # This target can include files from "c" but not from
- # "super_secret_implementation_details".
- executable("a") {
- deps = [ ":b" ]
- }
-
- shared_library("b") {
- deps = [ ":super_secret_implementation_details" ]
- public_deps = [ ":c" ]
- }
-```
-### <a name="response_file_contents"></a>**response_file_contents**: Contents of a response file for actions.
-
-```
- Sometimes the arguments passed to a script can be too long for the system's
- command-line capabilities. This is especially the case on Windows where the
- maximum command-line length is less than 8K. A response file allows you to
- pass an unlimited amount of data to a script in a temporary file for an
- action or action_foreach target.
-
- If the response_file_contents variable is defined and non-empty, the list
- will be treated as script args (including possibly substitution patterns)
- that will be written to a temporary file at build time. The name of the
- temporary file will be substituted for "{{response_file_name}}" in the script
- args.
-
- The response file contents will always be quoted and escaped according to
- Unix shell rules. To parse the response file, the Python script should use
- "shlex.split(file_contents)".
-```
-
-#### **Example**
-
-```
- action("process_lots_of_files") {
- script = "process.py",
- inputs = [ ... huge list of files ... ]
-
- # Write all the inputs to a response file for the script. Also,
- # make the paths relative to the script working directory.
- response_file_contents = rebase_path(inputs, root_build_dir)
-
- # The script expects the name of the response file in --file-list.
- args = [
- "--enable-foo",
- "--file-list={{response_file_name}}",
- ]
- }
-```
-### <a name="script"></a>**script**: Script file for actions.
-
-```
- An absolute or buildfile-relative file name of a Python script to run for a
- action and action_foreach targets (see "gn help action" and "gn help
- action_foreach").
-```
-### <a name="sources"></a>**sources**: Source files for a target
-
-```
- A list of files. Non-absolute paths will be resolved relative to the current
- build file.
-```
-
-#### **Sources for binary targets**
-
-```
- For binary targets (source sets, executables, and libraries), the known file
- types will be compiled with the associated tools. Unknown file types and
- headers will be skipped. However, you should still list all C/C+ header files
- so GN knows about the existence of those files for the purposes of include
- checking.
-
- As a special case, a file ending in ".def" will be treated as a Windows
- module definition file. It will be appended to the link line with a
- preceding "/DEF:" string. There must be at most one .def file in a target
- and they do not cross dependency boundaries (so specifying a .def file in a
- static library or source set will have no effect on the executable or shared
- library they're linked into).
-```
-
-#### **Sources for non-binary targets**
-
-```
- action_foreach
- The sources are the set of files that the script will be executed over. The
- script will run once per file.
-
- action
- The sources will be treated the same as inputs. See "gn help inputs" for
- more information and usage advice.
-
- copy
- The source are the source files to copy.
-```
-### <a name="testonly"></a>**testonly**: Declares a target must only be used for testing.
-
-```
- Boolean. Defaults to false.
-
- When a target is marked "testonly = true", it must only be depended on by
- other test-only targets. Otherwise, GN will issue an error that the
- depenedency is not allowed.
-
- This feature is intended to prevent accidentally shipping test code in a
- final product.
-```
-
-#### **Example**
-
-```
- source_set("test_support") {
- testonly = true
- ...
- }
-```
-### <a name="visibility"></a>**visibility**: A list of labels that can depend on a target.
-
-```
- A list of labels and label patterns that define which targets can depend on
- the current one. These permissions are checked via the "check" command (see
- "gn help check").
-
- If visibility is not defined, it defaults to public ("*").
-
- If visibility is defined, only the targets with labels that match it can
- depend on the current target. The empty list means no targets can depend on
- the current target.
-
- Tip: Often you will want the same visibility for all targets in a BUILD file.
- In this case you can just put the definition at the top, outside of any
- target, and the targets will inherit that scope and see the definition.
-```
-
-#### **Patterns**
-
-```
- See "gn help label_pattern" for more details on what types of patterns are
- supported. If a toolchain is specified, only targets in that toolchain will
- be matched. If a toolchain is not specified on a pattern, targets in all
- toolchains will be matched.
-```
-
-#### **Examples**
-
-```
- Only targets in the current buildfile ("private"):
- visibility = [ ":*" ]
-
- No targets (used for targets that should be leaf nodes):
- visibility = []
-
- Any target ("public", the default):
- visibility = [ "*" ]
-
- All targets in the current directory and any subdirectory:
- visibility = [ "./*" ]
-
- Any target in "//bar/BUILD.gn":
- visibility = [ "//bar:*" ]
-
- Any target in "//bar/" or any subdirectory thereof:
- visibility = [ "//bar/*" ]
-
- Just these specific targets:
- visibility = [ ":mything", "//foo:something_else" ]
-
- Any target in the current directory and any subdirectory thereof, plus
- any targets in "//bar/" and any subdirectory thereof.
- visibility = [ "./*", "//bar/*" ]
-```
-### <a name="write_runtime_deps"></a>**write_runtime_deps**: Writes the target's runtime_deps to the given path.
-
-```
- Does not synchronously write the file, but rather schedules it to be written
- at the end of generation.
-
- If the file exists and the contents are identical to that being written, the
- file will not be updated. This will prevent unnecessary rebuilds of targets
- that depend on this file.
-
- Path must be within the output directory.
-
- See "gn help runtime_deps" for how the runtime dependencies are computed.
-
- The format of this file will list one file per line with no escaping. The
- files will be relative to the root_build_dir. The first line of the file will
- be the main output file of the target itself. The file contents will be the
- same as requesting the runtime deps be written on the command line (see "gn
- help --runtime-deps-list-file").
-```
-### <a name="xcode_extra_attributes"></a>**xcode_extra_attributes**: [scope] Extra attributes for Xcode projects.
-
-```
- The value defined in this scope will be copied to the EXTRA_ATTRIBUTES
- property of the generated Xcode project. They are only meaningful when
- generating with --ide=xcode.
-
- See "gn help create_bundle" for more information.
-```
-### <a name="test_application_name"></a>**test_application_name**: Test application name for unit or ui test target.
-
-```
- Each unit and ui test target must have a test application target, and this
- value is used to specify the relationship. Only meaningful to Xcode (used as
- part of the Xcode project generation).
-
- See "gn help create_bundle" for more information.
-```
-
-#### **Exmaple**
-
-```
- create_bundle("chrome_xctest") {
- test_application_name = "chrome"
- ...
- }
-```
-## <a name="other"></a>Other help topics
-
-### <a name="buildargs"></a>**Build Arguments Overview**
-
-```
- Build arguments are variables passed in from outside of the build that build
- files can query to determine how the build works.
-```
-
-#### **How build arguments are set**
-
-```
- First, system default arguments are set based on the current system. The
- built-in arguments are:
- - host_cpu
- - host_os
- - current_cpu
- - current_os
- - target_cpu
- - target_os
-
- Next, project-specific overrides are applied. These are specified inside
- the default_args variable of //.gn. See "gn help dotfile" for more.
-
- If specified, arguments from the --args command line flag are used. If that
- flag is not specified, args from previous builds in the build directory will
- be used (this is in the file args.gn in the build directory).
-
- Last, for targets being compiled with a non-default toolchain, the toolchain
- overrides are applied. These are specified in the toolchain_args section of a
- toolchain definition. The use-case for this is that a toolchain may be
- building code for a different platform, and that it may want to always
- specify Posix, for example. See "gn help toolchain" for more.
-
- If you specify an override for a build argument that never appears in a
- "declare_args" call, a nonfatal error will be displayed.
-```
-
-#### **Examples**
-
-```
- gn args out/FooBar
- Create the directory out/FooBar and open an editor. You would type
- something like this into that file:
- enable_doom_melon=false
- os="android"
-
- gn gen out/FooBar --args="enable_doom_melon=true os=\"android\""
- This will overwrite the build directory with the given arguments. (Note
- that the quotes inside the args command will usually need to be escaped
- for your shell to pass through strings values.)
-```
-
-#### **How build arguments are used**
-
-```
- If you want to use an argument, you use declare_args() and specify default
- values. These default values will apply if none of the steps listed in the
- "How build arguments are set" section above apply to the given argument, but
- the defaults will not override any of these.
-
- Often, the root build config file will declare global arguments that will be
- passed to all buildfiles. Individual build files can also specify arguments
- that apply only to those files. It is also useful to specify build args in an
- "import"-ed file if you want such arguments to apply to multiple buildfiles.
-```
-### <a name="dotfile"></a>**.gn file**
-
-```
- When gn starts, it will search the current directory and parent directories
- for a file called ".gn". This indicates the source root. You can override
- this detection by using the --root command-line argument
-
- The .gn file in the source root will be executed. The syntax is the same as a
- buildfile, but with very limited build setup-specific meaning.
-
- If you specify --root, by default GN will look for the file .gn in that
- directory. If you want to specify a different file, you can additionally pass
- --dotfile:
-
- gn gen out/Debug --root=/home/build --dotfile=/home/my_gn_file.gn
-```
-
-#### **Variables**
-
-```
- arg_file_template [optional]
- Path to a file containing the text that should be used as the default
- args.gn content when you run `gn args`.
-
- buildconfig [required]
- Path to the build config file. This file will be used to set up the
- build file execution environment for each toolchain.
-
- check_targets [optional]
- A list of labels and label patterns that should be checked when running
- "gn check" or "gn gen --check". If unspecified, all targets will be
- checked. If it is the empty list, no targets will be checked.
-
- The format of this list is identical to that of "visibility" so see "gn
- help visibility" for examples.
-
- exec_script_whitelist [optional]
- A list of .gn/.gni files (not labels) that have permission to call the
- exec_script function. If this list is defined, calls to exec_script will
- be checked against this list and GN will fail if the current file isn't
- in the list.
-
- This is to allow the use of exec_script to be restricted since is easy to
- use inappropriately. Wildcards are not supported. Files in the
- secondary_source tree (if defined) should be referenced by ignoring the
- secondary tree and naming them as if they are in the main tree.
-
- If unspecified, the ability to call exec_script is unrestricted.
-
- Example:
- exec_script_whitelist = [
- "//base/BUILD.gn",
- "//build/my_config.gni",
- ]
-
- root [optional]
- Label of the root build target. The GN build will start by loading the
- build file containing this target name. This defaults to "//:" which will
- cause the file //BUILD.gn to be loaded.
-
- script_executable [optional]
- Path to specific Python executable or potentially a different language
- interpreter that is used to execute scripts in action targets and
- exec_script calls.
-
- secondary_source [optional]
- Label of an alternate directory tree to find input files. When searching
- for a BUILD.gn file (or the build config file discussed above), the file
- will first be looked for in the source root. If it's not found, the
- secondary source root will be checked (which would contain a parallel
- directory hierarchy).
-
- This behavior is intended to be used when BUILD.gn files can't be checked
- in to certain source directories for whatever reason.
-
- The secondary source root must be inside the main source tree.
-
- default_args [optional]
- Scope containing the default overrides for declared arguments. These
- overrides take precedence over the default values specified in the
- declare_args() block, but can be overriden using --args or the
- args.gn file.
-
- This is intended to be used when subprojects declare arguments with
- default values that need to be changed for whatever reason.
-```
-
-#### **Example .gn file contents**
-
-```
- buildconfig = "//build/config/BUILDCONFIG.gn"
-
- check_targets = [
- "//doom_melon/*", # Check everything in this subtree.
- "//tools:mind_controlling_ant", # Check this specific target.
- ]
-
- root = "//:root"
-
- secondary_source = "//build/config/temporary_buildfiles/"
-
- default_args = {
- # Default to release builds for this project.
- is_debug = false
- is_component_build = false
- }
-```
-### <a name="execution"></a>**Build graph and execution overview**
-
-#### **Overall build flow**
-
-```
- 1. Look for ".gn" file (see "gn help dotfile") in the current directory and
- walk up the directory tree until one is found. Set this directory to be
- the "source root" and interpret this file to find the name of the build
- config file.
-
- 2. Execute the build config file identified by .gn to set up the global
- variables and default toolchain name. Any arguments, variables, defaults,
- etc. set up in this file will be visible to all files in the build.
-
- 3. Load the //BUILD.gn (in the source root directory).
-
- 4. Recursively evaluate rules and load BUILD.gn in other directories as
- necessary to resolve dependencies. If a BUILD file isn't found in the
- specified location, GN will look in the corresponding location inside
- the secondary_source defined in the dotfile (see "gn help dotfile").
-
- 5. When a target's dependencies are resolved, write out the `.ninja`
- file to disk.
-
- 6. When all targets are resolved, write out the root build.ninja file.
-```
-
-#### **Executing target definitions and templates**
-
-```
- Build files are loaded in parallel. This means it is impossible to
- interrogate a target from GN code for any information not derivable from its
- label (see "gn help label"). The exception is the get_target_outputs()
- function which requires the target being interrogated to have been defined
- previously in the same file.
-
- Targets are declared by their type and given a name:
-
- static_library("my_static_library") {
- ... target parameter definitions ...
- }
-
- There is also a generic "target" function for programmatically defined types
- (see "gn help target"). You can define new types using templates (see "gn
- help template"). A template defines some custom code that expands to one or
- more other targets.
-
- Before executing the code inside the target's { }, the target defaults are
- applied (see "gn help set_defaults"). It will inject implicit variable
- definitions that can be overridden by the target code as necessary. Typically
- this mechanism is used to inject a default set of configs that define the
- global compiler and linker flags.
-```
-
-#### **Which targets are built**
-
-```
- All targets encountered in the default toolchain (see "gn help toolchain")
- will have build rules generated for them, even if no other targets reference
- them. Their dependencies must resolve and they will be added to the implicit
- "all" rule (see "gn help ninja_rules").
-
- Targets in non-default toolchains will only be generated when they are
- required (directly or transitively) to build a target in the default
- toolchain.
-
- See also "gn help ninja_rules".
-```
-
-#### **Dependencies**
-
-```
- The only difference between "public_deps" and "deps" except for pushing
- configs around the build tree and allowing includes for the purposes of "gn
- check".
-
- A target's "data_deps" are guaranteed to be built whenever the target is
- built, but the ordering is not defined. The meaning of this is dependencies
- required at runtime. Currently data deps will be complete before the target
- is linked, but this is not semantically guaranteed and this is undesirable
- from a build performance perspective. Since we hope to change this in the
- future, do not rely on this behavior.
-```
-### <a name="grammar"></a>**Language and grammar for GN build files**
-
-#### **Tokens**
-
-```
- GN build files are read as sequences of tokens. While splitting the file
- into tokens, the next token is the longest sequence of characters that form a
- valid token.
-```
-
-#### **White space and comments**
-
-```
- White space is comprised of spaces (U+0020), horizontal tabs (U+0009),
- carriage returns (U+000D), and newlines (U+000A).
-
- Comments start at the character "#" and stop at the next newline.
-
- White space and comments are ignored except that they may separate tokens
- that would otherwise combine into a single token.
-```
-
-#### **Identifiers**
-
-```
- Identifiers name variables and functions.
-
- identifier = letter { letter | digit } .
- letter = "A" ... "Z" | "a" ... "z" | "_" .
- digit = "0" ... "9" .
-```
-
-#### **Keywords**
-
-```
- The following keywords are reserved and may not be used as identifiers:
-
- else false if true
-```
-
-#### **Integer literals**
-
-```
- An integer literal represents a decimal integer value.
-
- integer = [ "-" ] digit { digit } .
-
- Leading zeros and negative zero are disallowed.
-```
-
-#### **String literals**
-
-```
- A string literal represents a string value consisting of the quoted
- characters with possible escape sequences and variable expansions.
-
- string = `"` { char | escape | expansion } `"` .
- escape = `\` ( "$" | `"` | char ) .
- BracketExpansion = "{" ( identifier | ArrayAccess | ScopeAccess "
- ") "}" .
- Hex = "0x" [0-9A-Fa-f][0-9A-Fa-f]
- expansion = "$" ( identifier | BracketExpansion | Hex ) .
- char = /* any character except "$", `"`, or newline "
- "*/ .
-
- After a backslash, certain sequences represent special characters:
-
- \" U+0022 quotation mark
- \$ U+0024 dollar sign
- \\ U+005C backslash
-
- All other backslashes represent themselves.
-
- To insert an arbitrary byte value, use $0xFF. For example, to insert a
- newline character: "Line one$0x0ALine two".
-
- An expansion will evaluate the variable following the '$' and insert a
- stringified version of it into the result. For example, to concat two path
- components with a slash separating them:
- "$var_one/$var_two"
- Use the "${var_one}" format to be explicitly deliniate the variable for
- otherwise-ambiguous cases.
-```
-
-#### **Punctuation**
-
-```
- The following character sequences represent punctuation:
-
- + += == != ( )
- - -= < <= [ ]
- ! = > >= { }
- && || . ,
-```
-
-#### **Grammar**
-
-```
- The input tokens form a syntax tree following a context-free grammar:
-
- File = StatementList .
-
- Statement = Assignment | Call | Condition .
- LValue = identifier | ArrayAccess | ScopeAccess .
- Assignment = LValue AssignOp Expr .
- Call = identifier "(" [ ExprList ] ")" [ Block ] .
- Condition = "if" "(" Expr ")" Block
- [ "else" ( Condition | Block ) ] .
- Block = "{" StatementList "}" .
- StatementList = { Statement } .
-
- ArrayAccess = identifier "[" Expr "]" .
- ScopeAccess = identifier "." identifier .
- Expr = UnaryExpr | Expr BinaryOp Expr .
- UnaryExpr = PrimaryExpr | UnaryOp UnaryExpr .
- PrimaryExpr = identifier | integer | string | Call
- | ArrayAccess | ScopeAccess | Block
- | "(" Expr ")"
- | "[" [ ExprList [ "," ] ] "]" .
- ExprList = Expr { "," Expr } .
-
- AssignOp = "=" | "+=" | "-=" .
- UnaryOp = "!" .
- BinaryOp = "+" | "-" // highest priority
- | "<" | "<=" | ">" | ">="
- | "==" | "!="
- | "&&"
- | "||" . // lowest priority
-
- All binary operators are left-associative.
-```
-
-#### **Types**
-
-```
- The GN language is dynamically typed. The following types are used:
-
- - Boolean: Uses the keywords "true" and "false". There is no implicit
- conversion between booleans and integers.
-
- - Integers: All numbers in GN are signed 64-bit integers.
-
- - Strings: Strings are 8-bit with no enforced encoding. When a string is
- used to interact with other systems with particular encodings (like the
- Windows and Mac filesystems) it is assumed to be UTF-8. See "String
- literals" above for more.
-
- - Lists: Lists are arbitrary-length ordered lists of values. See "Lists"
- below for more.
-
- - Scopes: Scopes are like dictionaries that use variable names for keys. See
- "Scopes" below for more.
-```
-
-#### **Lists**
-
-```
- Lists are created with [] and using commas to separate items:
-
- mylist = [ 0, 1, 2, "some string" ]
-
- A comma after the last item is optional. Lists are dereferenced using 0-based
- indexing:
-
- mylist[0] += 1
- var = mylist[2]
-
- Lists can be concatenated using the '+' and '+=' operators. Bare values can
- not be concatenated with lists, to add a single item, it must be put into a
- list of length one.
-
- Items can be removed from lists using the '-' and '-=' operators. This will
- remove all occurrences of every item in the right-hand list from the
- left-hand list. It is an error to remove an item not in the list. This is to
- prevent common typos and to detect dead code that is removing things that no
- longer apply.
-
- It is an error to use '=' to replace a nonempty list with another nonempty
- list. This is to prevent accidentally overwriting data when in most cases
- '+=' was intended. To overwrite a list on purpose, first assign it to the
- empty list:
-
- mylist = []
- mylist = otherlist
-
- When assigning to a list named 'sources' using '=' or '+=', list items may be
- automatically filtered out. See "gn help set_sources_assignment_filter" for
- more.
-```
-
-#### **Scopes**
-
-```
- All execution happens in the context of a scope which holds the current state
- (like variables). With the exception of loops and conditions, '{' introduces
- a new scope that has a parent reference to the old scope.
-
- Variable reads recursively search all nested scopes until the variable is
- found or there are no more scopes. Variable writes always go into the current
- scope. This means that after the closing '}' (again excepting loops and
- conditions), all local variables will be restored to the previous values.
- This also means that "foo = foo" can do useful work by copying a variable
- into the current scope that was defined in a containing scope.
-
- Scopes can also be assigned to variables. Such scopes can be created by
- functions like exec_script, when invoking a template (the template code
- refers to the variables set by the invoking code by the implicitly-created
- "invoker" scope), or explicitly like:
-
- empty_scope = {}
- myvalues = {
- foo = 21
- bar = "something"
- }
-
- Inside such a scope definition can be any GN code including conditionals and
- function calls. After the close of the scope, it will contain all variables
- explicitly set by the code contained inside it. After this, the values can be
- read, modified, or added to:
-
- myvalues.foo += 2
- empty_scope.new_thing = [ 1, 2, 3 ]
-```
-### <a name="input_conversion"></a>**input_conversion**: Specifies how to transform input to a variable.
-
-```
- input_conversion is an argument to read_file and exec_script that specifies
- how the result of the read operation should be converted into a variable.
-
- "" (the default)
- Discard the result and return None.
-
- "list lines"
- Return the file contents as a list, with a string for each line. The
- newlines will not be present in the result. The last line may or may not
- end in a newline.
-
- After splitting, each individual line will be trimmed of whitespace on
- both ends.
-
- "scope"
- Execute the block as GN code and return a scope with the resulting values
- in it. If the input was:
- a = [ "hello.cc", "world.cc" ]
- b = 26
- and you read the result into a variable named "val", then you could
- access contents the "." operator on "val":
- sources = val.a
- some_count = val.b
-
- "string"
- Return the file contents into a single string.
-
- "value"
- Parse the input as if it was a literal rvalue in a buildfile. Examples of
- typical program output using this mode:
- [ "foo", "bar" ] (result will be a list)
- or
- "foo bar" (result will be a string)
- or
- 5 (result will be an integer)
-
- Note that if the input is empty, the result will be a null value which
- will produce an error if assigned to a variable.
-
- "json"
- Parse the input as a JSON and convert it to equivalent GN rvalue. The data
- type mapping is:
- a string in JSON maps to string in GN
- an integer in JSON maps to integer in GN
- a float in JSON is unsupported and will result in an error
- an object in JSON maps to scope in GN
- an array in JSON maps to list in GN
- a boolean in JSON maps to boolean in GN
- a null in JSON is unsupported and will result in an error
-
- Nota that the dictionary keys have to be valid GN identifiers otherwise
- they will produce an error.
-
- "trim ..."
- Prefixing any of the other transformations with the word "trim" will
- result in whitespace being trimmed from the beginning and end of the
- result before processing.
-
- Examples: "trim string" or "trim list lines"
-
- Note that "trim value" is useless because the value parser skips
- whitespace anyway.
-```
-### <a name="label_pattern"></a>**Label patterns**
-
-```
- A label pattern is a way of expressing one or more labels in a portion of the
- source tree. They are not general regular expressions.
-
- They can take the following forms only:
-
- - Explicit (no wildcard):
- "//foo/bar:baz"
- ":baz"
-
- - Wildcard target names:
- "//foo/bar:*" (all targets in the //foo/bar/BUILD.gn file)
- ":*" (all targets in the current build file)
-
- - Wildcard directory names ("*" is only supported at the end)
- "*" (all targets)
- "//foo/bar/*" (all targets in any subdir of //foo/bar)
- "./*" (all targets in the current build file or sub dirs)
-
- Any of the above forms can additionally take an explicit toolchain. In this
- case, the toolchain must be fully qualified (no wildcards are supported in
- the toolchain name).
-
- "//foo:bar(//build/toochain:mac)"
- An explicit target in an explicit toolchain.
-
- ":*(//build/toolchain/linux:32bit)"
- All targets in the current build file using the 32-bit Linux toolchain.
-
- "//foo/*(//build/toolchain:win)"
- All targets in //foo and any subdirectory using the Windows
- toolchain.
-```
-### <a name="labels"></a>**About labels**
-
-```
- Everything that can participate in the dependency graph (targets, configs,
- and toolchains) are identified by labels. A common label looks like:
-
- //base/test:test_support
-
- This consists of a source-root-absolute path, a colon, and a name. This means
- to look for the thing named "test_support" in "base/test/BUILD.gn".
-
- You can also specify system absolute paths if necessary. Typically such
- paths would be specified via a build arg so the developer can specify where
- the component is on their system.
-
- /usr/local/foo:bar (Posix)
- /C:/Program Files/MyLibs:bar (Windows)
-```
-
-#### **Toolchains**
-
-```
- A canonical label includes the label of the toolchain being used. Normally,
- the toolchain label is implicitly inherited from the current execution
- context, but you can override this to specify cross-toolchain dependencies:
-
- //base/test:test_support(//build/toolchain/win:msvc)
-
- Here GN will look for the toolchain definition called "msvc" in the file
- "//build/toolchain/win" to know how to compile this target.
-```
-
-#### **Relative labels**
-
-```
- If you want to refer to something in the same buildfile, you can omit
- the path name and just start with a colon. This format is recommended for
- all same-file references.
-
- :base
-
- Labels can be specified as being relative to the current directory.
- Stylistically, we prefer to use absolute paths for all non-file-local
- references unless a build file needs to be run in different contexts (like a
- project needs to be both standalone and pulled into other projects in
- difference places in the directory hierarchy).
-
- source/plugin:myplugin
- ../net:url_request
-```
-
-#### **Implicit names**
-
-```
- If a name is unspecified, it will inherit the directory name. Stylistically,
- we prefer to omit the colon and name when possible:
-
- //net -> //net:net
- //tools/gn -> //tools/gn:gn
-```
-### <a name="ninja_rules"></a>**Ninja build rules**
-
-#### **The "all" and "default" rules**
-
-```
- All generated targets (see "gn help execution") will be added to an implicit
- build rule called "all" so "ninja all" will always compile everything. The
- default rule will be used by Ninja if no specific target is specified (just
- typing "ninja"). If there is a target named "default" in the root build file,
- it will be the default build rule, otherwise the implicit "all" rule will be
- used.
-```
-
-#### **Phony rules**
-
-```
- GN generates Ninja "phony" rules for targets in the default toolchain. The
- phony rules can collide with each other and with the names of generated files
- so are generated with the following priority:
-
- 1. Actual files generated by the build always take precedence.
-
- 2. Targets in the toplevel //BUILD.gn file.
-
- 3. Targets in toplevel directories matching the names of the directories.
- So "ninja foo" can be used to compile "//foo:foo". This only applies to
- the first level of directories since usually these are the most
- important (so this won't apply to "//foo/bar:bar").
-
- 4. The short names of executables if there is only one executable with that
- short name. Use "ninja doom_melon" to compile the
- "//tools/fruit:doom_melon" executable.
-
- 5. The short names of all targets if there is only one target with that
- short name.
-
- 6. Full label name with no leading slashes. So you can use
- "ninja tools/fruit:doom_melon" to build "//tools/fruit:doom_melon".
-
- 7. Labels with an implicit name part (when the short names match the
- directory). So you can use "ninja foo/bar" to compile "//foo/bar:bar".
-
- These "phony" rules are provided only for running Ninja since this matches
- people's historical expectations for building. For consistency with the rest
- of the program, GN introspection commands accept explicit labels.
-
- To explicitly compile a target in a non-default toolchain, you must give
- Ninja the exact name of the output file relative to the build directory.
-```
-### <a name="nogncheck"></a>**nogncheck**: Skip an include line from checking.
-
-```
- GN's header checker helps validate that the includes match the build
- dependency graph. Sometimes an include might be conditional or otherwise
- problematic, but you want to specifically allow it. In this case, it can be
- whitelisted.
-
- Include lines containing the substring "nogncheck" will be excluded from
- header checking. The most common case is a conditional include:
-
- #if defined(ENABLE_DOOM_MELON)
- #include "tools/doom_melon/doom_melon.h" // nogncheck
- #endif
-
- If the build file has a conditional dependency on the corresponding target
- that matches the conditional include, everything will always link correctly:
-
- source_set("mytarget") {
- ...
- if (enable_doom_melon) {
- defines = [ "ENABLE_DOOM_MELON" ]
- deps += [ "//tools/doom_melon" ]
- }
-
- But GN's header checker does not understand preprocessor directives, won't
- know it matches the build dependencies, and will flag this include as
- incorrect when the condition is false.
-```
-
-#### **More information**
-
-```
- The topic "gn help check" has general information on how checking works and
- advice on fixing problems. Targets can also opt-out of checking, see
- "gn help check_includes".
-```
-### <a name="runtime_deps"></a>**Runtime dependencies**
-
-```
- Runtime dependencies of a target are exposed via the "runtime_deps" category
- of "gn desc" (see "gn help desc") or they can be written at build generation
- time via write_runtime_deps(), or --runtime-deps-list-file (see "gn help
- --runtime-deps-list-file").
-
- To a first approximation, the runtime dependencies of a target are the set of
- "data" files, data directories, and the shared libraries from all transitive
- dependencies. Executables, shared libraries, and loadable modules are
- considered runtime dependencies of themselves.
-```
-
-#### **Executables**
-
-```
- Executable targets and those executable targets' transitive dependencies are
- not considered unless that executable is listed in "data_deps". Otherwise, GN
- assumes that the executable (and everything it requires) is a build-time
- dependency only.
-```
-
-#### **Actions and copies**
-
-```
- Action and copy targets that are listed as "data_deps" will have all of their
- outputs and data files considered as runtime dependencies. Action and copy
- targets that are "deps" or "public_deps" will have only their data files
- considered as runtime dependencies. These targets can list an output file in
- both the "outputs" and "data" lists to force an output file as a runtime
- dependency in all cases.
-
- The different rules for deps and data_deps are to express build-time (deps)
- vs. run-time (data_deps) outputs. If GN counted all build-time copy steps as
- data dependencies, there would be a lot of extra stuff, and if GN counted all
- run-time dependencies as regular deps, the build's parallelism would be
- unnecessarily constrained.
-
- This rule can sometimes lead to unintuitive results. For example, given the
- three targets:
- A --[data_deps]--> B --[deps]--> ACTION
- GN would say that A does not have runtime deps on the result of the ACTION,
- which is often correct. But the purpose of the B target might be to collect
- many actions into one logic unit, and the "data"-ness of A's dependency is
- lost. Solutions:
-
- - List the outputs of the action in its data section (if the results of
- that action are always runtime files).
- - Have B list the action in data_deps (if the outputs of the actions are
- always runtime files).
- - Have B list the action in both deps and data deps (if the outputs might be
- used in both contexts and you don't care about unnecessary entries in the
- list of files required at runtime).
- - Split B into run-time and build-time versions with the appropriate "deps"
- for each.
-```
-
-#### **Static libraries and source sets**
-
-```
- The results of static_library or source_set targets are not considered
- runtime dependencies since these are assumed to be intermediate targets only.
- If you need to list a static library as a runtime dependency, you can
- manually compute the .a/.lib file name for the current platform and list it
- in the "data" list of a target (possibly on the static library target
- itself).
-```
-
-#### **Multiple outputs**
-
-```
- Linker tools can specify which of their outputs should be considered when
- computing the runtime deps by setting runtime_outputs. If this is unset on
- the tool, the default will be the first output only.
-```
-### <a name="source_expansion"></a>**How Source Expansion Works**
-
-```
- Source expansion is used for the action_foreach and copy target types to map
- source file names to output file names or arguments.
-
- To perform source expansion in the outputs, GN maps every entry in the
- sources to every entry in the outputs list, producing the cross product of
- all combinations, expanding placeholders (see below).
-
- Source expansion in the args works similarly, but performing the placeholder
- substitution produces a different set of arguments for each invocation of the
- script.
-
- If no placeholders are found, the outputs or args list will be treated as a
- static list of literal file names that do not depend on the sources.
-
- See "gn help copy" and "gn help action_foreach" for more on how this is
- applied.
-```
-
-#### **Placeholders**
-
-```
- This section discusses only placeholders for actions. There are other
- placeholders used in the definition of tools. See "gn help tool" for those.
-
- {{source}}
- The name of the source file including directory (*). This will generally
- be used for specifying inputs to a script in the "args" variable.
- "//foo/bar/baz.txt" => "../../foo/bar/baz.txt"
-
- {{source_file_part}}
- The file part of the source including the extension.
- "//foo/bar/baz.txt" => "baz.txt"
-
- {{source_name_part}}
- The filename part of the source file with no directory or extension. This
- will generally be used for specifying a transformation from a source file
- to a destination file with the same name but different extension.
- "//foo/bar/baz.txt" => "baz"
-
- {{source_dir}}
- The directory (*) containing the source file with no trailing slash.
- "//foo/bar/baz.txt" => "../../foo/bar"
-
- {{source_root_relative_dir}}
- The path to the source file's directory relative to the source root, with
- no leading "//" or trailing slashes. If the path is system-absolute,
- (beginning in a single slash) this will just return the path with no
- trailing slash. This value will always be the same, regardless of whether
- it appears in the "outputs" or "args" section.
- "//foo/bar/baz.txt" => "foo/bar"
-
- {{source_gen_dir}}
- The generated file directory (*) corresponding to the source file's path.
- This will be different than the target's generated file directory if the
- source file is in a different directory than the BUILD.gn file.
- "//foo/bar/baz.txt" => "gen/foo/bar"
-
- {{source_out_dir}}
- The object file directory (*) corresponding to the source file's path,
- relative to the build directory. this us be different than the target's
- out directory if the source file is in a different directory than the
- build.gn file.
- "//foo/bar/baz.txt" => "obj/foo/bar"
-
- {{source_target_relative}}
- The path to the source file relative to the target's directory. This will
- generally be used for replicating the source directory layout in the
- output directory. This can only be used in actions and it is an error to
- use in process_file_template where there is no "target".
- "//foo/bar/baz.txt" => "baz.txt"
-```
-
-#### **(*) Note on directories**
-
-```
- Paths containing directories (except the source_root_relative_dir) will be
- different depending on what context the expansion is evaluated in. Generally
- it should "just work" but it means you can't concatenate strings containing
- these values with reasonable results.
-
- Details: source expansions can be used in the "outputs" variable, the "args"
- variable, and in calls to "process_file_template". The "args" are passed to a
- script which is run from the build directory, so these directories will
- relative to the build directory for the script to find. In the other cases,
- the directories will be source- absolute (begin with a "//") because the
- results of those expansions will be handled by GN internally.
-```
-
-#### **Examples**
-
-```
- Non-varying outputs:
- action("hardcoded_outputs") {
- sources = [ "input1.idl", "input2.idl" ]
- outputs = [ "$target_out_dir/output1.dat",
- "$target_out_dir/output2.dat" ]
- }
- The outputs in this case will be the two literal files given.
-
- Varying outputs:
- action_foreach("varying_outputs") {
- sources = [ "input1.idl", "input2.idl" ]
- outputs = [ "{{source_gen_dir}}/{{source_name_part}}.h",
- "{{source_gen_dir}}/{{source_name_part}}.cc" ]
- }
- Performing source expansion will result in the following output names:
- //out/Debug/obj/mydirectory/input1.h
- //out/Debug/obj/mydirectory/input1.cc
- //out/Debug/obj/mydirectory/input2.h
- //out/Debug/obj/mydirectory/input2.cc
-```
-## <a name="switches"></a>Command Line Switches
-
-**Available global switches
-** Do "gn help --the_switch_you_want_help_on" for more. Individual
- commands may take command-specific switches not listed here. See the
- help on your specific command for more.
-
-```
- * [--args: Specifies build arguments overrides.](#--args)
- * [--color: Force colored output.](#--color)
- * [--dotfile: Override the name of the ".gn" file.](#--dotfile)
- * [--fail-on-unused-args: Treat unused build args as fatal errors.](#--fail-on-unused-args)
- * [--markdown: Write help output in the Markdown format.](#--markdown)
- * [--nocolor: Force non-colored output.](#--nocolor)
- * [-q: Quiet mode. Don't print output on success.](#-q)
- * [--root: Explicitly specify source root.](#--root)
- * [--runtime-deps-list-file: Save runtime dependencies for targets in file.](#--runtime-deps-list-file)
- * [--script-executable: Set the executable used to execute scripts.](#--script-executable)
- * [--threads: Specify number of worker threads.](#--threads)
- * [--time: Outputs a summary of how long everything took.](#--time)
- * [--tracelog: Writes a Chrome-compatible trace log to the given file.](#--tracelog)
- * [-v: Verbose logging.](#-v)
- * [--version: Prints the GN version number and exits.](#--version)
-```
-
diff --git a/chromium/tools/gn/docs/standalone.md b/chromium/tools/gn/docs/standalone.md
deleted file mode 100644
index 29d62360f7f..00000000000
--- a/chromium/tools/gn/docs/standalone.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# Introduction
-
-This page is about how to design a project that can build independently
-with GN but also be brought into the Chrome build.
-
-GN is in principle no different than GYP in that there is some core
-configuration that must be the same between both the standalone build
-and the Chrome build. However, GN is much more explicit in its naming
-and configuration, so the similarities between the two builds are also
-much more explicit and there is less flexibility in how things are
-configured.
-
-# What you need for a minimal GN build
-
-Requirements:
-
- * A master build config file. Chrome's is `//build/config/BUILDCONFIG.gn`
- * A separate build file for the toolchain definition. It's not a good idea
- to put these in a BUILD.gn file shared with any target definitions for
- complex reasons. Chrome's are in `//build/toolchain/<platform>/BUILD.gn`.
- * A `BUILD.gn` file in the root directory. This will be loaded after the
- build config file to start the build.
-
-You may want a `.gn` file in the root directory. When you run GN it
-recursively looks up the directory tree until it finds this file, and it
-treats the containing directory as the "source root". This file also
-defines the location of the master build config file:
-
- * See Chrome's `src/.gn` file.
- * Unlike Chrome, you probably don't need to define a secondary root.
- * see `gn help dotfile` for more.
-
-Adding a `.gn` file in a repository that is pulled into Chrome means
-that then running GN in your subdirectory will configure a build for
-your subproject rather than for all of Chrome. This could be an
-advantage or a disadvantage.
-
-If you are in a directory with such a file and you want to not use it
-(e.g., to do the full Chrome build instead), you can use the command-line
-flags `--root` and `--dotfile` to set the values you want.
-
-If you want a completely standalone build that has nothing to do with Chrome
-and doesn't use Chrome's `//build` files, you can look at an example in
-[//tools/gn/example](../example).
diff --git a/chromium/tools/gn/docs/style_guide.md b/chromium/tools/gn/docs/style_guide.md
deleted file mode 100644
index 466f8727e0d..00000000000
--- a/chromium/tools/gn/docs/style_guide.md
+++ /dev/null
@@ -1,286 +0,0 @@
-# GN Style Guide
-
-[TOC]
-
-## Naming and ordering within the file
-
-### Location of build files
-
-It usually makes sense to have more build files closer to the code than
-fewer ones at the top level; this is in contrast with what we did with
-GYP. This makes things easier to find, and also makes the set of owners
-required for reviews smaller since changes are more focused to particular
-subdirectories.
-
-### Targets
-
- * Most BUILD files should have a target with the same name as the
- directory. This target should be the first target.
- * Other targets should be in some logical order -- usually
- more important targets will be first, and unit tests will follow the
- corresponding target. If there's no clear ordering, consider
- alphabetical order.
- * Test support libraries should be static libraries named "test\_support".
- For example, "//ui/compositor:test\_support". Test support libraries should
- include as public deps the non-test-support version of the library
- so tests need only depend on the test\_support target (rather than
- both).
-
-Naming advice
-
- * Targets and configs should be named using lowercase with underscores
- separating words, unless there is a strong reason to do otherwise.
- * Source sets, groups, and static libraries do not need globally unique names.
- Prefer to give such targets short, non-redundant names without worrying
- about global uniqueness. For example, it looks much better to write a
- dependency as `"//mojo/public/bindings"` rather than
- `"//mojo/public/bindings:mojo_bindings"
- * Shared libraries (and by extension, components) must have globally unique
- output names. Give such targets short non-unique names above, and then
- provide a globally unique `output_name` for that target.
- * Executables and tests should be given a globally unique name. Technically
- only the output names must be unique, but since only the output names
- appear in the shell and on bots, it's much less confusing if the name
- matches the other places the executable appears.
-
-### Configs
-
- * A config associated with a single target should be named the same as
- the target with `_config` following it.
- * A config should appear immediately before the corresponding target
- that uses it.
-
-### Example
-
-Example for the `src/foo/BUILD.gn` file:
-
-```
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Config for foo is named foo_config and immediately precedes it in the file.
-config("foo_config") {
-}
-
-# Target matching path name is the first target.
-executable("foo") {
-}
-
-# Test for foo follows it.
-test("foo_unittests") {
-}
-
-config("bar_config") {
-}
-
-source_set("bar") {
-}
-```
-
-## Ordering within a target
-
- 1. `output_name` / `visibility` / `testonly`
- 2. `sources`
- 3. `cflags`, `include_dirs`, `defines`, `configs` etc. in whatever
- order makes sense to you.
- 4. `public_deps`
- 5. `deps`
-
-### Conditions
-
-Simple conditions affecting just one variable (e.g. adding a single
-source or adding a flag for one particular OS) can go beneath the
-variable they affect. More complicated conditions affecting more than
-one thing should go at the bottom.
-
-Conditions should be written to minimize the number of conditional blocks.
-
-## Formatting and indenting
-
-GN contains a built-in code formatter which defines the formatting style.
-Some additional notes:
-
- * Variables are `lower_case_with_underscores`.
- * Comments should be complete sentences with periods at the end.
- * Compiler flags and such should always be commented with what they do
- and why the flag is needed.
-
-### Sources
-
-Prefer to list sources only once. It is OK to conditionally include sources
-rather than listing them all at the top and then conditionally excluding them
-when they don't apply. Conditional inclusion is often clearer since a file is
-only listed once and it's easier to reason about when reading.
-
-```
- sources = [
- "main.cc",
- ]
- if (use_aura) {
- sources += [ "thing_aura.cc" ]
- }
- if (use_gtk) {
- sources += [ "thing_gtk.cc" ]
- }
-```
-
-### Deps
-
- * Deps should be in alphabetical order.
- * Deps within the current file should be written first and not
- qualified with the file name (just `:foo`).
- * Other deps should always use fully-qualified path names unless
- relative ones are required for some reason.
-
-```
- deps = [
- ":a_thing",
- ":mystatic",
- "//foo/bar:other_thing",
- "//foo/baz:that_thing",
- ]
-```
-
-### Import
-
-Use fully-qualified paths for imports:
-
-```
-import("//foo/bar/baz.gni") # Even if this file is in the foo/bar directory
-```
-
-## Usage
-
-### Source sets versus static libraries
-
-Source sets and static libraries can be used interchangeably in most cases. If
-you're unsure what to use, a source set is almost never wrong and is less likely
-to cause problems.
-
-Static libraries follow different linking rules. When a static library is
-included in a link, only the object files that contain unresolved symbols will
-be brought into the build. Source sets result in every object file being added
-to the link line of the final binary.
-
- * If you're eventually linking code into a component, shared library, or
- loadable module, you normally need to use source sets. This is because
- object files with no symbols referenced from within the shared library will
- not be linked into the final library at all. This omission will happen even
- if that object file has a symbol marked for export that targets dependent
- on that shared library need. This will result in undefined symbols when
- linking later targets.
-
- * Unit tests (and anything else with static initializers with side effects)
- must use source sets. The gtest TEST macros create static initializers
- that register the test. But since no code references symbols in the object
- file, linking a test into a static library and then into a test executable
- means the tests will get stripped.
-
- * Static libraries involve duplicating all of the data in the object files
- that comprise it. This takes more disk space and for certain very large
- libraries in configurations with very large object files can cause
- internal limits on the size of static libraries to be exceeded. Source
- sets do not have this limitation. Some targets switch between source sets
- and static libraries depending on the build configuration to avoid this
- problem.
-
- * Source sets can have no sources, while static libraries will give strange
- platform-specific errors if they have no sources. If a target has only
- headers (for include checking purposes) or conditionally has no sources on
- sone platforms, use a source set.
-
- * In cases where a lot of the symbols are not needed for a particular link
- (this especially happens when linking test binaries), putting that code in
- a static library can dramatically increase linking performance. This is
- because the object files not needed for the link are never considered in
- the first place, rather than forcing the linker to strip the unused code
- in a later pass when nothing references it.
-
-### Loadable modules versus shared libraries versus components
-
-A component is a Chrome primitive (rather than a built-in GN concept) that
-expands either to a shared library or a static library / source set depending
-on the value of the `is_component_build` variable. This allows release builds
-to be linked statically in a large binary, but for developers to use shared
-libraries for most operations.
-
-A shared library will be listed on the link line of dependent targets and will
-be loaded automatically by the operating system when the application starts
-and symbols automatically resolved. A loadable module will not be linked
-directly and the application must manually load it.
-
-On Windows and Linux shared libraries and loadable modules result in the same
-type of file (`.dll` and `.so`, respectively). The only difference is in how
-they are linked to dependent targets. On these platforms, having a `deps`
-dependency on a loadable module is the same as having a `data_deps`
-(non-linked) dependency on a shared library.
-
-On Mac, these targets have different formats: a shared library will generate a
-`.dylib` file and a loadable module will generate a `.so` file.
-
-Use loadable modules for things like plugins. Shared libraries should be
-seldom-used outside of components because most Chrome code is shipped to the
-end-user as a small number of large binaries. In the case of plugin-like
-libraries, it's good practice to use both a loadable module for the target type
-(even for platforms where it doesn't matter) and data deps for targets that
-depend on it so it's clear from both places that how the library will be linked
-and loaded.
-
-## Build arguments
-
-### Scope
-
-Build arguments should be scoped to a unit of behavior, e.g. enabling a feature.
-Typically an argument would be declared in an imported file to share it with
-the subset of the build that could make use of it.
-
-Chrome has many legacy flags in `//build/config/features.gni`,
-`//build/config/ui.gni`. These locations are deprecated. Feature flags should
-go along with the code for the feature. Many browser-level features can go
-somewhere in `//chrome/` without lower-level code knowing about it. Some
-UI environment flags can go into `//ui/`, and many flags can also go with
-the corresponding code in `//components/`. You can write a `.gni` file in
-components and have build files in chrome or content import it if necessary.
-
-The way to think about things in the `//build` directory is that this is
-DEPSed into various projects like V8 and WebRTC. Build flags specific to
-code outside of the build directory shouldn't be in the build directory, and
-V8 shouldn't get feature defines for Chrome features.
-
-New feature defines should use the buildflag system. See
-`//build/buildflag_header.gni` which allows preprocessor defines to be
-modularized without many of the disadvantages that made us use global defines
-in the past.
-
-### Type
-
-Arguments support all the [GN language types](language.md#Language).
-
-In the vast majority of cases `boolean` is the preferred type, since most
-arguments are enabling or disabling features or includes.
-
-`String`s are typically used for filepaths. They are also used for enumerated
-types, though `integer`s are sometimes used as well.
-
-### Naming conventions
-
-While there are no hard and fast rules around argument naming there are
-many common conventions. If you ever want to see the current list of argument
-names and default values for your current checkout use
-`gn args out/Debug --list --short`.
-
-`use_foo` - indicates dependencies or major codepaths to include (e.g.
-`use_open_ssl`, `use_ozone`, `use_cups`)
-
-`enable_foo` - indicates feature or tools to be enabled (e.g.
-`enable_google_now`, `enable_nacl`, `enable_remoting`, `enable_pdf`)
-
-`disable_foo` - _NOT_ recommended, use `enable_foo` instead with swapped default
-value
-
-`is_foo` - usually a global state descriptor (e.g. `is_chrome_branded`,
-`is_desktop_linux`); poor choice for non-globals
-
-`foo_use_bar` - prefixes can be used to indicate a limited scope for an argument
-(e.g. `rtc_use_h264`, `v8_use_snapshot`)
diff --git a/chromium/tools/gn/docs/update_binaries.md b/chromium/tools/gn/docs/update_binaries.md
deleted file mode 100644
index d3e3bbce7cc..00000000000
--- a/chromium/tools/gn/docs/update_binaries.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# How to update the GN binaries that Chromium uses.
-
-Any committer should be able to do a roll by running
-[//tools/gn/bin/roll_gn.py](../bin/roll_gn.py) on Linux or Mac.
-
diff --git a/chromium/tools/gn/eclipse_writer.cc b/chromium/tools/gn/eclipse_writer.cc
deleted file mode 100644
index 720231b4015..00000000000
--- a/chromium/tools/gn/eclipse_writer.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/eclipse_writer.h"
-
-#include <fstream>
-#include <memory>
-
-#include "base/files/file_path.h"
-#include "tools/gn/builder.h"
-#include "tools/gn/config_values_extractors.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/loader.h"
-#include "tools/gn/xml_element_writer.h"
-
-namespace {
-
-// Escapes |unescaped| for use in XML element content.
-std::string EscapeForXML(const std::string& unescaped) {
- std::string result;
- result.reserve(unescaped.length());
- for (const char c : unescaped) {
- if (c == '<')
- result += "&lt;";
- else if (c == '>')
- result += "&gt;";
- else if (c == '&')
- result += "&amp;";
- else
- result.push_back(c);
- }
- return result;
-}
-
-} // namespace
-
-EclipseWriter::EclipseWriter(const BuildSettings* build_settings,
- const Builder& builder,
- std::ostream& out)
- : build_settings_(build_settings), builder_(builder), out_(out) {
- languages_.push_back("C++ Source File");
- languages_.push_back("C Source File");
- languages_.push_back("Assembly Source File");
- languages_.push_back("GNU C++");
- languages_.push_back("GNU C");
- languages_.push_back("Assembly");
-}
-
-EclipseWriter::~EclipseWriter() = default;
-
-// static
-bool EclipseWriter::RunAndWriteFile(
- const BuildSettings* build_settings,
- const Builder& builder,
- Err* err) {
- base::FilePath file = build_settings->GetFullPath(build_settings->build_dir())
- .AppendASCII("eclipse-cdt-settings.xml");
- std::ofstream file_out;
- file_out.open(FilePathToUTF8(file).c_str(),
- std::ios_base::out | std::ios_base::binary);
- if (file_out.fail()) {
- *err =
- Err(Location(), "Couldn't open eclipse-cdt-settings.xml for writing");
- return false;
- }
-
- EclipseWriter gen(build_settings, builder, file_out);
- gen.Run();
- return true;
-}
-
-void EclipseWriter::Run() {
- GetAllIncludeDirs();
- GetAllDefines();
- WriteCDTSettings();
-}
-
-void EclipseWriter::GetAllIncludeDirs() {
- std::vector<const Target*> targets = builder_.GetAllResolvedTargets();
- for (const Target* target : targets) {
- if (!UsesDefaultToolchain(target))
- continue;
-
- for (ConfigValuesIterator it(target); !it.done(); it.Next()) {
- for (const SourceDir& include_dir : it.cur().include_dirs()) {
- include_dirs_.insert(
- FilePathToUTF8(build_settings_->GetFullPath(include_dir)));
- }
- }
- }
-}
-
-void EclipseWriter::GetAllDefines() {
- std::vector<const Target*> targets = builder_.GetAllResolvedTargets();
- for (const Target* target : targets) {
- if (!UsesDefaultToolchain(target))
- continue;
-
- for (ConfigValuesIterator it(target); !it.done(); it.Next()) {
- for (const std::string& define : it.cur().defines()) {
- size_t equal_pos = define.find('=');
- std::string define_key;
- std::string define_value;
- if (equal_pos == std::string::npos) {
- define_key = define;
- } else {
- define_key = define.substr(0, equal_pos);
- define_value = define.substr(equal_pos + 1);
- }
- defines_[define_key] = define_value;
- }
- }
- }
-}
-
-bool EclipseWriter::UsesDefaultToolchain(const Target* target) const {
- return target->toolchain()->label() ==
- builder_.loader()->GetDefaultToolchain();
-}
-
-void EclipseWriter::WriteCDTSettings() {
- out_ << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
- XmlElementWriter cdt_properties_element(out_, "cdtprojectproperties",
- XmlAttributes());
-
- {
- const char* kIncludesSectionName =
- "org.eclipse.cdt.internal.ui.wizards.settingswizards.IncludePaths";
- std::unique_ptr<XmlElementWriter> section_element =
- cdt_properties_element.SubElement(
- "section", XmlAttributes("name", kIncludesSectionName));
-
- section_element->SubElement(
- "language", XmlAttributes("name", "holder for library settings"));
-
- for (const std::string& language : languages_) {
- std::unique_ptr<XmlElementWriter> language_element =
- section_element->SubElement("language",
- XmlAttributes("name", language));
- for (const std::string& include_dir : include_dirs_) {
- language_element
- ->SubElement("includepath",
- XmlAttributes("workspace_path", "false"))
- ->Text(EscapeForXML(include_dir));
- }
- }
- }
-
- {
- const char* kMacrosSectionName =
- "org.eclipse.cdt.internal.ui.wizards.settingswizards.Macros";
- std::unique_ptr<XmlElementWriter> section_element =
- cdt_properties_element.SubElement(
- "section", XmlAttributes("name", kMacrosSectionName));
-
- section_element->SubElement(
- "language", XmlAttributes("name", "holder for library settings"));
-
- for (const std::string& language : languages_) {
- std::unique_ptr<XmlElementWriter> language_element =
- section_element->SubElement("language",
- XmlAttributes("name", language));
- for (const auto& key_val : defines_) {
- std::unique_ptr<XmlElementWriter> macro_element =
- language_element->SubElement("macro");
- macro_element->SubElement("name")->Text(EscapeForXML(key_val.first));
- macro_element->SubElement("value")->Text(EscapeForXML(key_val.second));
- }
- }
- }
-}
diff --git a/chromium/tools/gn/eclipse_writer.h b/chromium/tools/gn/eclipse_writer.h
deleted file mode 100644
index e15254fbadb..00000000000
--- a/chromium/tools/gn/eclipse_writer.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_ECLIPSE_WRITER_H_
-#define TOOLS_GN_ECLIPSE_WRITER_H_
-
-#include <iosfwd>
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-
-class BuildSettings;
-class Builder;
-class Err;
-class Target;
-
-class EclipseWriter {
- public:
- static bool RunAndWriteFile(const BuildSettings* build_settings,
- const Builder& builder,
- Err* err);
-
- private:
- EclipseWriter(const BuildSettings* build_settings,
- const Builder& builder,
- std::ostream& out);
- ~EclipseWriter();
-
- void Run();
-
- // Populates |include_dirs_| with the include dirs of all the targets for the
- // default toolchain.
- void GetAllIncludeDirs();
-
- // Populates |defines_| with the defines of all the targets for the default
- // toolchain.
- void GetAllDefines();
-
- // Returns true if |target| uses the default toolchain.
- bool UsesDefaultToolchain(const Target* target) const;
-
- // Writes the XML settings file.
- void WriteCDTSettings();
-
- const BuildSettings* build_settings_;
- const Builder& builder_;
-
- // The output stream for the settings file.
- std::ostream& out_;
-
- // Eclipse languages for which the include dirs and defines apply.
- std::vector<std::string> languages_;
-
- // The include dirs of all the targets which use the default toolchain.
- std::set<std::string> include_dirs_;
-
- // The defines of all the targets which use the default toolchain.
- std::map<std::string, std::string> defines_;
-
- DISALLOW_COPY_AND_ASSIGN(EclipseWriter);
-};
-
-#endif // TOOLS_GN_ECLIPSE_WRITER_H_
diff --git a/chromium/tools/gn/err.cc b/chromium/tools/gn/err.cc
deleted file mode 100644
index bdd6f4cb52c..00000000000
--- a/chromium/tools/gn/err.cc
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/err.h"
-
-#include <stddef.h>
-
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/standard_out.h"
-#include "tools/gn/tokenizer.h"
-#include "tools/gn/value.h"
-
-namespace {
-
-std::string GetNthLine(const base::StringPiece& data, int n) {
- size_t line_off = Tokenizer::ByteOffsetOfNthLine(data, n);
- size_t end = line_off + 1;
- while (end < data.size() && !Tokenizer::IsNewline(data, end))
- end++;
- return data.substr(line_off, end - line_off).as_string();
-}
-
-void FillRangeOnLine(const LocationRange& range, int line_number,
- std::string* line) {
- // Only bother if the range's begin or end overlaps the line. If the entire
- // line is highlighted as a result of this range, it's not very helpful.
- if (range.begin().line_number() != line_number &&
- range.end().line_number() != line_number)
- return;
-
- // Watch out, the char offsets in the location are 1-based, so we have to
- // subtract 1.
- int begin_char;
- if (range.begin().line_number() < line_number)
- begin_char = 0;
- else
- begin_char = range.begin().column_number() - 1;
-
- int end_char;
- if (range.end().line_number() > line_number)
- end_char = static_cast<int>(line->size()); // Ending is non-inclusive.
- else
- end_char = range.end().column_number() - 1;
-
- CHECK(end_char >= begin_char);
- CHECK(begin_char >= 0 && begin_char <= static_cast<int>(line->size()));
- CHECK(end_char >= 0 && end_char <= static_cast<int>(line->size()));
- for (int i = begin_char; i < end_char; i++)
- line->at(i) = '-';
-}
-
-// The line length is used to clip the maximum length of the markers we'll
-// make if the error spans more than one line (like unterminated literals).
-void OutputHighlighedPosition(const Location& location,
- const Err::RangeList& ranges,
- size_t line_length) {
- // Make a buffer of the line in spaces.
- std::string highlight;
- highlight.resize(line_length);
- for (size_t i = 0; i < line_length; i++)
- highlight[i] = ' ';
-
- // Highlight all the ranges on the line.
- for (const auto& range : ranges)
- FillRangeOnLine(range, location.line_number(), &highlight);
-
- // Allow the marker to be one past the end of the line for marking the end.
- highlight.push_back(' ');
- CHECK(location.column_number() - 1 >= 0 &&
- location.column_number() - 1 < static_cast<int>(highlight.size()));
- highlight[location.column_number() - 1] = '^';
-
- // Trim unused spaces from end of line.
- while (!highlight.empty() && highlight[highlight.size() - 1] == ' ')
- highlight.resize(highlight.size() - 1);
-
- highlight += "\n";
- OutputString(highlight, DECORATION_BLUE);
-}
-
-} // namespace
-
-Err::Err() : has_error_(false) {
-}
-
-Err::Err(const Location& location,
- const std::string& msg,
- const std::string& help)
- : has_error_(true),
- location_(location),
- message_(msg),
- help_text_(help) {
-}
-
-Err::Err(const LocationRange& range,
- const std::string& msg,
- const std::string& help)
- : has_error_(true),
- location_(range.begin()),
- message_(msg),
- help_text_(help) {
- ranges_.push_back(range);
-}
-
-Err::Err(const Token& token,
- const std::string& msg,
- const std::string& help)
- : has_error_(true),
- location_(token.location()),
- message_(msg),
- help_text_(help) {
- ranges_.push_back(token.range());
-}
-
-Err::Err(const ParseNode* node,
- const std::string& msg,
- const std::string& help_text)
- : has_error_(true),
- message_(msg),
- help_text_(help_text) {
- // Node will be null in certain tests.
- if (node) {
- LocationRange range = node->GetRange();
- location_ = range.begin();
- ranges_.push_back(range);
- }
-}
-
-Err::Err(const Value& value,
- const std::string msg,
- const std::string& help_text)
- : has_error_(true),
- message_(msg),
- help_text_(help_text) {
- if (value.origin()) {
- LocationRange range = value.origin()->GetRange();
- location_ = range.begin();
- ranges_.push_back(range);
- }
-}
-
-Err::Err(const Err& other) = default;
-
-Err::~Err() = default;
-
-void Err::PrintToStdout() const {
- InternalPrintToStdout(false, true);
-}
-
-void Err::PrintNonfatalToStdout() const {
- InternalPrintToStdout(false, false);
-}
-
-void Err::AppendSubErr(const Err& err) {
- sub_errs_.push_back(err);
-}
-
-void Err::InternalPrintToStdout(bool is_sub_err, bool is_fatal) const {
- DCHECK(has_error_);
-
- if (!is_sub_err) {
- if (is_fatal)
- OutputString("ERROR ", DECORATION_RED);
- else
- OutputString("WARNING ", DECORATION_RED);
- }
-
- // File name and location.
- const InputFile* input_file = location_.file();
- std::string loc_str = location_.Describe(true);
- if (!loc_str.empty()) {
- if (is_sub_err)
- loc_str.insert(0, "See ");
- else
- loc_str.insert(0, "at ");
- loc_str.append(": ");
- }
- OutputString(loc_str + message_ + "\n");
-
- // Quoted line.
- if (input_file) {
- std::string line = GetNthLine(input_file->contents(),
- location_.line_number());
- if (!base::ContainsOnlyChars(line, base::kWhitespaceASCII)) {
- OutputString(line + "\n", DECORATION_DIM);
- OutputHighlighedPosition(location_, ranges_, line.size());
- }
- }
-
- // Optional help text.
- if (!help_text_.empty())
- OutputString(help_text_ + "\n");
-
- // Sub errors.
- for (const auto& sub_err : sub_errs_)
- sub_err.InternalPrintToStdout(true, is_fatal);
-}
diff --git a/chromium/tools/gn/err.h b/chromium/tools/gn/err.h
deleted file mode 100644
index 90f31509310..00000000000
--- a/chromium/tools/gn/err.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_ERR_H_
-#define TOOLS_GN_ERR_H_
-
-#include <string>
-#include <vector>
-
-#include "tools/gn/location.h"
-#include "tools/gn/token.h"
-
-class ParseNode;
-class Value;
-
-// Result of doing some operation. Check has_error() to see if an error
-// occurred.
-//
-// An error has a location and a message. Below that, is some optional help
-// text to go with the annotation of the location.
-//
-// An error can also have sub-errors which are additionally printed out
-// below. They can provide additional context.
-class Err {
- public:
- using RangeList = std::vector<LocationRange>;
-
- // Indicates no error.
- Err();
-
- // Error at a single point.
- Err(const Location& location,
- const std::string& msg,
- const std::string& help = std::string());
-
- // Error at a given range.
- Err(const LocationRange& range,
- const std::string& msg,
- const std::string& help = std::string());
-
- // Error at a given token.
- Err(const Token& token,
- const std::string& msg,
- const std::string& help_text = std::string());
-
- // Error at a given node.
- Err(const ParseNode* node,
- const std::string& msg,
- const std::string& help_text = std::string());
-
- // Error at a given value.
- Err(const Value& value,
- const std::string msg,
- const std::string& help_text = std::string());
-
- Err(const Err& other);
-
- ~Err();
-
- bool has_error() const { return has_error_; }
- const Location& location() const { return location_; }
- const std::string& message() const { return message_; }
- const std::string& help_text() const { return help_text_; }
-
- void AppendRange(const LocationRange& range) { ranges_.push_back(range); }
- const RangeList& ranges() const { return ranges_; }
-
- void AppendSubErr(const Err& err);
-
- void PrintToStdout() const;
-
- // Prints to standard out but uses a "WARNING" messaging instead of the
- // normal "ERROR" messaging. This is a property of the printing system rather
- // than of the Err class because there is no expectation that code calling a
- // function that take an Err check that the error is nonfatal and continue.
- // Generally all Err objects with has_error() set are fatal.
- //
- // In some very specific cases code will detect a condition and print a
- // nonfatal error to the screen instead of returning it. In these cases, that
- // code can decide at printing time whether it will continue (and use this
- // method) or not (and use PrintToStdout()).
- void PrintNonfatalToStdout() const;
-
- private:
- void InternalPrintToStdout(bool is_sub_err, bool is_fatal) const;
-
- bool has_error_;
- Location location_;
-
- std::vector<LocationRange> ranges_;
-
- std::string message_;
- std::string help_text_;
-
- std::vector<Err> sub_errs_;
-};
-
-#endif // TOOLS_GN_ERR_H_
diff --git a/chromium/tools/gn/escape.cc b/chromium/tools/gn/escape.cc
deleted file mode 100644
index 685a100e749..00000000000
--- a/chromium/tools/gn/escape.cc
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/escape.h"
-
-#include <stddef.h>
-
-#include "base/logging.h"
-#include "build/build_config.h"
-
-namespace {
-
-// A "1" in this lookup table means that char is valid in the Posix shell.
-const char kShellValid[0x80] = {
-// 00-1f: all are invalid
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-// ' ' ! " # $ % & ' ( ) * + , - . /
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
-// 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0,
-// @ A B C D E F G H I J K L M N O
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-// P Q R S T U V W X Y Z [ \ ] ^ _
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
-// ` a b c d e f g h i j k l m n o
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-// p q r s t u v w x y z { | } ~
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
-
-// Append one character to the given string, escaping it for Ninja.
-//
-// Ninja's escaping rules are very simple. We always escape colons even
-// though they're OK in many places, in case the resulting string is used on
-// the left-hand-side of a rule.
-inline void NinjaEscapeChar(char ch, std::string* dest) {
- if (ch == '$' || ch == ' ' || ch == ':')
- dest->push_back('$');
- dest->push_back(ch);
-}
-
-void EscapeStringToString_Ninja(const base::StringPiece& str,
- const EscapeOptions& options,
- std::string* dest,
- bool* needed_quoting) {
- for (const auto& elem : str)
- NinjaEscapeChar(elem, dest);
-}
-
-void EscapeStringToString_NinjaPreformatted(const base::StringPiece& str,
- std::string* dest) {
- // Only Ninja-escape $.
- for (const auto& elem : str) {
- if (elem == '$')
- dest->push_back('$');
- dest->push_back(elem);
- }
-}
-
-// Escape for CommandLineToArgvW and additionally escape Ninja characters.
-//
-// The basic algorithm is if the string doesn't contain any parse-affecting
-// characters, don't do anything (other than the Ninja processing). If it does,
-// quote the string, and backslash-escape all quotes and backslashes.
-// See:
-// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx
-// http://blogs.msdn.com/b/oldnewthing/archive/2010/09/17/10063629.aspx
-void EscapeStringToString_WindowsNinjaFork(const base::StringPiece& str,
- const EscapeOptions& options,
- std::string* dest,
- bool* needed_quoting) {
- // We assume we don't have any whitespace chars that aren't spaces.
- DCHECK(str.find_first_of("\r\n\v\t") == std::string::npos);
-
- if (str.find_first_of(" \"") == std::string::npos) {
- // Simple case, don't quote.
- EscapeStringToString_Ninja(str, options, dest, needed_quoting);
- } else {
- if (!options.inhibit_quoting)
- dest->push_back('"');
-
- for (size_t i = 0; i < str.size(); i++) {
- // Count backslashes in case they're followed by a quote.
- size_t backslash_count = 0;
- while (i < str.size() && str[i] == '\\') {
- i++;
- backslash_count++;
- }
- if (i == str.size()) {
- // Backslashes at end of string. Backslash-escape all of them since
- // they'll be followed by a quote.
- dest->append(backslash_count * 2, '\\');
- } else if (str[i] == '"') {
- // 0 or more backslashes followed by a quote. Backslash-escape the
- // backslashes, then backslash-escape the quote.
- dest->append(backslash_count * 2 + 1, '\\');
- dest->push_back('"');
- } else {
- // Non-special Windows character, just escape for Ninja. Also, add any
- // backslashes we read previously, these are literals.
- dest->append(backslash_count, '\\');
- NinjaEscapeChar(str[i], dest);
- }
- }
-
- if (!options.inhibit_quoting)
- dest->push_back('"');
- if (needed_quoting)
- *needed_quoting = true;
- }
-}
-
-void EscapeStringToString_PosixNinjaFork(const base::StringPiece& str,
- const EscapeOptions& options,
- std::string* dest,
- bool* needed_quoting) {
- for (const auto& elem : str) {
- if (elem == '$' || elem == ' ') {
- // Space and $ are special to both Ninja and the shell. '$' escape for
- // Ninja, then backslash-escape for the shell.
- dest->push_back('\\');
- dest->push_back('$');
- dest->push_back(elem);
- } else if (elem == ':') {
- // Colon is the only other Ninja special char, which is not special to
- // the shell.
- dest->push_back('$');
- dest->push_back(':');
- } else if (static_cast<unsigned>(elem) >= 0x80 ||
- !kShellValid[static_cast<int>(elem)]) {
- // All other invalid shell chars get backslash-escaped.
- dest->push_back('\\');
- dest->push_back(elem);
- } else {
- // Everything else is a literal.
- dest->push_back(elem);
- }
- }
-}
-
-void EscapeStringToString(const base::StringPiece& str,
- const EscapeOptions& options,
- std::string* dest,
- bool* needed_quoting) {
- switch (options.mode) {
- case ESCAPE_NONE:
- dest->append(str.data(), str.size());
- break;
- case ESCAPE_NINJA:
- EscapeStringToString_Ninja(str, options, dest, needed_quoting);
- break;
- case ESCAPE_NINJA_COMMAND:
- switch (options.platform) {
- case ESCAPE_PLATFORM_CURRENT:
-#if defined(OS_WIN)
- EscapeStringToString_WindowsNinjaFork(str, options, dest,
- needed_quoting);
-#else
- EscapeStringToString_PosixNinjaFork(str, options, dest,
- needed_quoting);
-#endif
- break;
- case ESCAPE_PLATFORM_WIN:
- EscapeStringToString_WindowsNinjaFork(str, options, dest,
- needed_quoting);
- break;
- case ESCAPE_PLATFORM_POSIX:
- EscapeStringToString_PosixNinjaFork(str, options, dest,
- needed_quoting);
- break;
- default:
- NOTREACHED();
- }
- break;
- case ESCAPE_NINJA_PREFORMATTED_COMMAND:
- EscapeStringToString_NinjaPreformatted(str, dest);
- break;
- default:
- NOTREACHED();
- }
-}
-
-} // namespace
-
-std::string EscapeString(const base::StringPiece& str,
- const EscapeOptions& options,
- bool* needed_quoting) {
- std::string result;
- result.reserve(str.size() + 4); // Guess we'll add a couple of extra chars.
- EscapeStringToString(str, options, &result, needed_quoting);
- return result;
-}
-
-void EscapeStringToStream(std::ostream& out,
- const base::StringPiece& str,
- const EscapeOptions& options) {
- std::string escaped;
- EscapeStringToString(str, options, &escaped, nullptr);
- if (!escaped.empty())
- out.write(escaped.data(), escaped.size());
-}
diff --git a/chromium/tools/gn/escape.h b/chromium/tools/gn/escape.h
deleted file mode 100644
index 838de943709..00000000000
--- a/chromium/tools/gn/escape.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_ESCAPE_H_
-#define TOOLS_GN_ESCAPE_H_
-
-#include <iosfwd>
-
-#include "base/strings/string_piece.h"
-
-enum EscapingMode {
- // No escaping.
- ESCAPE_NONE,
-
- // Ninja string escaping.
- ESCAPE_NINJA,
-
- // For writing commands to ninja files. This assumes the output is "one
- // thing" like a filename, so will escape or quote spaces as necessary for
- // both Ninja and the shell to keep that thing together.
- ESCAPE_NINJA_COMMAND,
-
- // For writing preformatted shell commands to Ninja files. This assumes the
- // output already has the proper quoting and may include special shell
- // shell characters which we want to pass to the shell (like when writing
- // tool commands). Only Ninja "$" are escaped.
- ESCAPE_NINJA_PREFORMATTED_COMMAND,
-};
-
-enum EscapingPlatform {
- // Do escaping for the current platform.
- ESCAPE_PLATFORM_CURRENT,
-
- // Force escaping for the given platform.
- ESCAPE_PLATFORM_POSIX,
- ESCAPE_PLATFORM_WIN,
-};
-
-struct EscapeOptions {
- EscapeOptions()
- : mode(ESCAPE_NONE),
- platform(ESCAPE_PLATFORM_CURRENT),
- inhibit_quoting(false) {
- }
-
- EscapingMode mode;
-
- // Controls how "fork" escaping is done. You will generally want to keep the
- // default "current" platform.
- EscapingPlatform platform;
-
- // When the escaping mode is ESCAPE_SHELL, the escaper will normally put
- // quotes around things with spaces. If this value is set to true, we'll
- // disable the quoting feature and just add the spaces.
- //
- // This mode is for when quoting is done at some higher-level. Defaults to
- // false. Note that Windows has strange behavior where the meaning of the
- // backslashes changes according to if it is followed by a quote. The
- // escaping rules assume that a double-quote will be appended to the result.
- bool inhibit_quoting;
-};
-
-// Escapes the given input, returnining the result.
-//
-// If needed_quoting is non-null, whether the string was or should have been
-// (if inhibit_quoting was set) quoted will be written to it. This value should
-// be initialized to false by the caller and will be written to only if it's
-// true (the common use-case is for chaining calls).
-std::string EscapeString(const base::StringPiece& str,
- const EscapeOptions& options,
- bool* needed_quoting);
-
-// Same as EscapeString but writes the results to the given stream, saving a
-// copy.
-void EscapeStringToStream(std::ostream& out,
- const base::StringPiece& str,
- const EscapeOptions& options);
-
-#endif // TOOLS_GN_ESCAPE_H_
diff --git a/chromium/tools/gn/escape_unittest.cc b/chromium/tools/gn/escape_unittest.cc
deleted file mode 100644
index 8d7ba8a2f84..00000000000
--- a/chromium/tools/gn/escape_unittest.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/escape.h"
-
-TEST(Escape, Ninja) {
- EscapeOptions opts;
- opts.mode = ESCAPE_NINJA;
- std::string result = EscapeString("asdf: \"$\\bar", opts, nullptr);
- EXPECT_EQ("asdf$:$ \"$$\\bar", result);
-}
-
-TEST(Escape, WindowsCommand) {
- EscapeOptions opts;
- opts.mode = ESCAPE_NINJA_COMMAND;
- opts.platform = ESCAPE_PLATFORM_WIN;
-
- // Regular string is passed, even if it has backslashes.
- EXPECT_EQ("foo\\bar", EscapeString("foo\\bar", opts, nullptr));
-
- // Spaces means the string is quoted, normal backslahes untouched.
- bool needs_quoting = false;
- EXPECT_EQ("\"foo\\$ bar\"", EscapeString("foo\\ bar", opts, &needs_quoting));
- EXPECT_TRUE(needs_quoting);
-
- // Inhibit quoting.
- needs_quoting = false;
- opts.inhibit_quoting = true;
- EXPECT_EQ("foo\\$ bar", EscapeString("foo\\ bar", opts, &needs_quoting));
- EXPECT_TRUE(needs_quoting);
- opts.inhibit_quoting = false;
-
- // Backslashes at the end of the string get escaped.
- EXPECT_EQ("\"foo$ bar\\\\\\\\\"", EscapeString("foo bar\\\\", opts, nullptr));
-
- // Backslashes preceding quotes are escaped, and the quote is escaped.
- EXPECT_EQ("\"foo\\\\\\\"$ bar\"", EscapeString("foo\\\" bar", opts, nullptr));
-}
-
-TEST(Escape, PosixCommand) {
- EscapeOptions opts;
- opts.mode = ESCAPE_NINJA_COMMAND;
- opts.platform = ESCAPE_PLATFORM_POSIX;
-
- // : and $ ninja escaped with $. Then Shell-escape backslashes and quotes.
- EXPECT_EQ("a$:\\$ \\\"\\$$\\\\b", EscapeString("a: \"$\\b", opts, nullptr));
-
- // Some more generic shell chars.
- EXPECT_EQ("a_\\;\\<\\*b", EscapeString("a_;<*b", opts, nullptr));
-
- // Curly braces must be escaped to avoid brace expansion on systems using
- // bash as default shell..
- EXPECT_EQ("\\{a,b\\}\\{c,d\\}", EscapeString("{a,b}{c,d}", opts, nullptr));
-}
-
-TEST(Escape, NinjaPreformatted) {
- EscapeOptions opts;
- opts.mode = ESCAPE_NINJA_PREFORMATTED_COMMAND;
-
- // Only $ is escaped.
- EXPECT_EQ("a: \"$$\\b<;", EscapeString("a: \"$\\b<;", opts, nullptr));
-}
diff --git a/chromium/tools/gn/example/.gn b/chromium/tools/gn/example/.gn
deleted file mode 100644
index e5b6d4a3db7..00000000000
--- a/chromium/tools/gn/example/.gn
+++ /dev/null
@@ -1,2 +0,0 @@
-# The location of the build configuration file.
-buildconfig = "//build/BUILDCONFIG.gn"
diff --git a/chromium/tools/gn/example/BUILD.gn b/chromium/tools/gn/example/BUILD.gn
deleted file mode 100644
index a18390e6489..00000000000
--- a/chromium/tools/gn/example/BUILD.gn
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-executable("hello") {
- sources = [
- "hello.cc",
- ]
-
- deps = [
- ":hello_shared",
- ":hello_static",
- ]
-}
-
-shared_library("hello_shared") {
- sources = [
- "hello_shared.cc",
- "hello_shared.h",
- ]
-
- defines = [ "HELLO_SHARED_IMPLEMENTATION" ]
-}
-
-static_library("hello_static") {
- sources = [
- "hello_static.cc",
- "hello_static.h",
- ]
-}
diff --git a/chromium/tools/gn/example/README.txt b/chromium/tools/gn/example/README.txt
deleted file mode 100644
index d0ddeed8b47..00000000000
--- a/chromium/tools/gn/example/README.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is an example directory structure that compiles some simple targets using
-gcc. It is intended to show how to set up a simple GN build.
-
-Don't miss the ".gn" file in this directory!
diff --git a/chromium/tools/gn/example/build/BUILD.gn b/chromium/tools/gn/example/build/BUILD.gn
deleted file mode 100644
index 8eae46a1aad..00000000000
--- a/chromium/tools/gn/example/build/BUILD.gn
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-config("compiler_defaults") {
- if (current_os == "linux") {
- cflags = [
- "-fPIC",
- "-pthread",
- ]
- }
-}
-
-config("executable_ldconfig") {
- ldflags = [
- "-Wl,-rpath=\$ORIGIN/",
- "-Wl,-rpath-link=",
- ]
-}
diff --git a/chromium/tools/gn/example/build/BUILDCONFIG.gn b/chromium/tools/gn/example/build/BUILDCONFIG.gn
deleted file mode 100644
index e419fd96a8a..00000000000
--- a/chromium/tools/gn/example/build/BUILDCONFIG.gn
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-if (target_os == "") {
- target_os = host_os
-}
-if (target_cpu == "") {
- target_cpu = host_cpu
-}
-if (current_cpu == "") {
- current_cpu = target_cpu
-}
-if (current_os == "") {
- current_os = target_os
-}
-
-# All binary targets will get this list of configs by default.
-_shared_binary_target_configs = [ "//build:compiler_defaults" ]
-
-# Apply that default list to the binary target types.
-set_defaults("executable") {
- configs = _shared_binary_target_configs
-
- # Executables get this additional configuration.
- configs += [ "//build:executable_ldconfig" ]
-}
-set_defaults("static_library") {
- configs = _shared_binary_target_configs
-}
-set_defaults("shared_library") {
- configs = _shared_binary_target_configs
-}
-set_defaults("source_set") {
- configs = _shared_binary_target_configs
-}
-
-set_default_toolchain("//build/toolchain:gcc")
diff --git a/chromium/tools/gn/example/build/toolchain/BUILD.gn b/chromium/tools/gn/example/build/toolchain/BUILD.gn
deleted file mode 100644
index d9457d7eae4..00000000000
--- a/chromium/tools/gn/example/build/toolchain/BUILD.gn
+++ /dev/null
@@ -1,86 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-toolchain("gcc") {
- tool("cc") {
- depfile = "{{output}}.d"
- command = "gcc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
- depsformat = "gcc"
- description = "CC {{output}}"
- outputs = [
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
- ]
- }
-
- tool("cxx") {
- depfile = "{{output}}.d"
- command = "g++ -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
- depsformat = "gcc"
- description = "CXX {{output}}"
- outputs = [
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
- ]
- }
-
- tool("alink") {
- rspfile = "{{output}}.rsp"
- command = "rm -f {{output}} && ar rcs {{output}} @$rspfile"
- description = "AR {{target_output_name}}{{output_extension}}"
- rspfile_content = "{{inputs}}"
- outputs = [
- "{{target_out_dir}}/{{target_output_name}}{{output_extension}}",
- ]
- default_output_extension = ".a"
- output_prefix = "lib"
- }
-
- tool("solink") {
- soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so".
- sofile = "{{output_dir}}/$soname"
- rspfile = soname + ".rsp"
-
- command = "g++ -shared {{ldflags}} -o $sofile -Wl,-soname=$soname @$rspfile"
- rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}"
-
- description = "SOLINK $soname"
-
- # Use this for {{output_extension}} expansions unless a target manually
- # overrides it (in which case {{output_extension}} will be what the target
- # specifies).
- default_output_extension = ".so"
-
- # Use this for {{output_dir}} expansions unless a target manually overrides
- # it (in which case {{output_dir}} will be what the target specifies).
- default_output_dir = "{{root_out_dir}}"
-
- outputs = [
- sofile,
- ]
- link_output = sofile
- depend_output = sofile
- output_prefix = "lib"
- }
-
- tool("link") {
- outfile = "{{target_output_name}}{{output_extension}}"
- rspfile = "$outfile.rsp"
- command = "g++ {{ldflags}} -o $outfile -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group {{libs}}"
- description = "LINK $outfile"
- default_output_dir = "{{root_out_dir}}"
- rspfile_content = "{{inputs}}"
- outputs = [
- outfile,
- ]
- }
-
- tool("stamp") {
- command = "touch {{output}}"
- description = "STAMP {{output}}"
- }
-
- tool("copy") {
- command = "cp -af {{source}} {{output}}"
- description = "COPY {{source}} {{output}}"
- }
-}
diff --git a/chromium/tools/gn/example/hello.cc b/chromium/tools/gn/example/hello.cc
deleted file mode 100644
index c4aa4482949..00000000000
--- a/chromium/tools/gn/example/hello.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdio.h>
-
-#include "hello_shared.h"
-#include "hello_static.h"
-
-int main(int argc, char* argv[]) {
- printf("%s, %s\n", GetStaticText(), GetSharedText());
- return 0;
-}
diff --git a/chromium/tools/gn/example/hello_shared.cc b/chromium/tools/gn/example/hello_shared.cc
deleted file mode 100644
index 58be84c27b4..00000000000
--- a/chromium/tools/gn/example/hello_shared.cc
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "hello_shared.h"
-
-const char* GetSharedText() {
- return "world";
-}
diff --git a/chromium/tools/gn/example/hello_shared.h b/chromium/tools/gn/example/hello_shared.h
deleted file mode 100644
index 7af804b3be4..00000000000
--- a/chromium/tools/gn/example/hello_shared.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_EXAMPLE_HELLO_SHARED_H_
-#define TOOLS_GN_EXAMPLE_HELLO_SHARED_H_
-
-#if defined(WIN32)
-
-#if defined(HELLO_SHARED_IMPLEMENTATION)
-#define HELLO_EXPORT __declspec(dllexport)
-#define HELLO_EXPORT_PRIVATE __declspec(dllexport)
-#else
-#define HELLO_EXPORT __declspec(dllimport)
-#define HELLO_EXPORT_PRIVATE __declspec(dllimport)
-#endif // defined(HELLO_SHARED_IMPLEMENTATION)
-
-#else
-
-#if defined(HELLO_SHARED_IMPLEMENTATION)
-#define HELLO_EXPORT __attribute__((visibility("default")))
-#define HELLO_EXPORT_PRIVATE __attribute__((visibility("default")))
-#else
-#define HELLO_EXPORT
-#define HELLO_EXPORT_PRIVATE
-#endif // defined(HELLO_SHARED_IMPLEMENTATION)
-
-#endif
-
-HELLO_EXPORT const char* GetSharedText();
-
-#endif // TOOLS_GN_EXAMPLE_HELLO_SHARED_H_
diff --git a/chromium/tools/gn/example/hello_static.cc b/chromium/tools/gn/example/hello_static.cc
deleted file mode 100644
index cdf4e67b05c..00000000000
--- a/chromium/tools/gn/example/hello_static.cc
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "hello_static.h"
-
-const char* GetStaticText() {
- return "Hello";
-}
diff --git a/chromium/tools/gn/example/hello_static.h b/chromium/tools/gn/example/hello_static.h
deleted file mode 100644
index f15a6336d2a..00000000000
--- a/chromium/tools/gn/example/hello_static.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_EXAMPLE_HELLO_STATIC_H_
-#define TOOLS_GN_EXAMPLE_HELLO_STATIC_H_
-
-const char* GetStaticText();
-
-#endif // TOOLS_GN_EXAMPLE_HELLO_STATIC_H_
diff --git a/chromium/tools/gn/exec_process.cc b/chromium/tools/gn/exec_process.cc
deleted file mode 100644
index 5453446ae2f..00000000000
--- a/chromium/tools/gn/exec_process.cc
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/exec_process.h"
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/process/kill.h"
-#include "base/process/launch.h"
-#include "base/process/process.h"
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-
-#include "base/win/scoped_handle.h"
-#include "base/win/scoped_process_information.h"
-#else
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "base/posix/eintr_wrapper.h"
-#include "base/posix/file_descriptor_shuffle.h"
-#endif
-
-namespace internal {
-
-#if defined(OS_WIN)
-bool ExecProcess(const base::CommandLine& cmdline,
- const base::FilePath& startup_dir,
- std::string* std_out,
- std::string* std_err,
- int* exit_code) {
- SECURITY_ATTRIBUTES sa_attr;
- // Set the bInheritHandle flag so pipe handles are inherited.
- sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
- sa_attr.bInheritHandle = TRUE;
- sa_attr.lpSecurityDescriptor = nullptr;
-
- // Create the pipe for the child process's STDOUT.
- HANDLE out_read = nullptr;
- HANDLE out_write = nullptr;
- if (!CreatePipe(&out_read, &out_write, &sa_attr, 0)) {
- NOTREACHED() << "Failed to create pipe";
- return false;
- }
- base::win::ScopedHandle scoped_out_read(out_read);
- base::win::ScopedHandle scoped_out_write(out_write);
-
- // Create the pipe for the child process's STDERR.
- HANDLE err_read = nullptr;
- HANDLE err_write = nullptr;
- if (!CreatePipe(&err_read, &err_write, &sa_attr, 0)) {
- NOTREACHED() << "Failed to create pipe";
- return false;
- }
- base::win::ScopedHandle scoped_err_read(err_read);
- base::win::ScopedHandle scoped_err_write(err_write);
-
- // Ensure the read handle to the pipe for STDOUT/STDERR is not inherited.
- if (!SetHandleInformation(out_read, HANDLE_FLAG_INHERIT, 0)) {
- NOTREACHED() << "Failed to disabled pipe inheritance";
- return false;
- }
- if (!SetHandleInformation(err_read, HANDLE_FLAG_INHERIT, 0)) {
- NOTREACHED() << "Failed to disabled pipe inheritance";
- return false;
- }
-
- base::FilePath::StringType cmdline_str(cmdline.GetCommandLineString());
-
- STARTUPINFO start_info = {};
-
- start_info.cb = sizeof(STARTUPINFO);
- start_info.hStdOutput = out_write;
- // Keep the normal stdin.
- start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- // FIXME(brettw) set stderr here when we actually read it below.
- //start_info.hStdError = err_write;
- start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
- start_info.dwFlags |= STARTF_USESTDHANDLES;
-
- // Create the child process.
- PROCESS_INFORMATION temp_process_info = {};
- if (!CreateProcess(nullptr,
- &cmdline_str[0],
- nullptr, nullptr,
- TRUE, // Handles are inherited.
- NORMAL_PRIORITY_CLASS, nullptr,
- startup_dir.value().c_str(),
- &start_info, &temp_process_info)) {
- return false;
- }
- base::win::ScopedProcessInformation proc_info(temp_process_info);
-
- // Close our writing end of pipes now. Otherwise later read would not be able
- // to detect end of child's output.
- scoped_out_write.Close();
- scoped_err_write.Close();
-
- // Read output from the child process's pipe for STDOUT
- const int kBufferSize = 1024;
- char buffer[kBufferSize];
-
- // FIXME(brettw) read from stderr here! This is complicated because we want
- // to read both of them at the same time, probably need overlapped I/O.
- // Also uncomment start_info code above.
- for (;;) {
- DWORD bytes_read = 0;
- BOOL success =
- ReadFile(out_read, buffer, kBufferSize, &bytes_read, nullptr);
- if (!success || bytes_read == 0)
- break;
- std_out->append(buffer, bytes_read);
- }
-
- // Let's wait for the process to finish.
- WaitForSingleObject(proc_info.process_handle(), INFINITE);
-
- DWORD dw_exit_code;
- GetExitCodeProcess(proc_info.process_handle(), &dw_exit_code);
- *exit_code = static_cast<int>(dw_exit_code);
-
- return true;
-}
-#else
-// Reads from the provided file descriptor and appends to output. Returns false
-// if the fd is closed or there is an unexpected error (not
-// EINTR/EAGAIN/EWOULDBLOCK).
-bool ReadFromPipe(int fd, std::string* output) {
- char buffer[256];
- int bytes_read = HANDLE_EINTR(read(fd, buffer, sizeof(buffer)));
- if (bytes_read == -1) {
- return errno == EAGAIN || errno == EWOULDBLOCK;
- } else if (bytes_read <= 0) {
- return false;
- }
- output->append(buffer, bytes_read);
- return true;
-}
-
-bool ExecProcess(const base::CommandLine& cmdline,
- const base::FilePath& startup_dir,
- std::string* std_out,
- std::string* std_err,
- int* exit_code) {
- *exit_code = EXIT_FAILURE;
-
- std::vector<std::string> argv = cmdline.argv();
-
- int out_fd[2], err_fd[2];
- pid_t pid;
- base::InjectiveMultimap fd_shuffle1, fd_shuffle2;
- std::unique_ptr<char* []> argv_cstr(new char*[argv.size() + 1]);
-
- fd_shuffle1.reserve(3);
- fd_shuffle2.reserve(3);
-
- if (pipe(out_fd) < 0)
- return false;
- base::ScopedFD out_read(out_fd[0]), out_write(out_fd[1]);
-
- if (pipe(err_fd) < 0)
- return false;
- base::ScopedFD err_read(err_fd[0]), err_write(err_fd[1]);
-
- if (out_read.get() >= FD_SETSIZE || err_read.get() >= FD_SETSIZE)
- return false;
-
- switch (pid = fork()) {
- case -1: // error
- return false;
- case 0: // child
- {
- // DANGER: no calls to malloc are allowed from now on:
- // http://crbug.com/36678
- //
- // STL iterators are also not allowed (including those implied
- // by range-based for loops), since debug iterators use locks.
-
- // Obscure fork() rule: in the child, if you don't end up doing exec*(),
- // you call _exit() instead of exit(). This is because _exit() does not
- // call any previously-registered (in the parent) exit handlers, which
- // might do things like block waiting for threads that don't even exist
- // in the child.
- int dev_null = open("/dev/null", O_WRONLY);
- if (dev_null < 0)
- _exit(127);
-
- fd_shuffle1.push_back(
- base::InjectionArc(out_write.get(), STDOUT_FILENO, true));
- fd_shuffle1.push_back(
- base::InjectionArc(err_write.get(), STDERR_FILENO, true));
- fd_shuffle1.push_back(
- base::InjectionArc(dev_null, STDIN_FILENO, true));
- // Adding another element here? Remeber to increase the argument to
- // reserve(), above.
-
- // DANGER: Do NOT convert to range-based for loop!
- for (size_t i = 0; i < fd_shuffle1.size(); ++i)
- fd_shuffle2.push_back(fd_shuffle1[i]);
-
- if (!ShuffleFileDescriptors(&fd_shuffle1))
- _exit(127);
-
- base::SetCurrentDirectory(startup_dir);
-
- // TODO(brettw) the base version GetAppOutput does a
- // CloseSuperfluousFds call here. Do we need this?
-
- // DANGER: Do NOT convert to range-based for loop!
- for (size_t i = 0; i < argv.size(); i++)
- argv_cstr[i] = const_cast<char*>(argv[i].c_str());
- argv_cstr[argv.size()] = nullptr;
- execvp(argv_cstr[0], argv_cstr.get());
- _exit(127);
- }
- default: // parent
- {
- // Close our writing end of pipe now. Otherwise later read would not
- // be able to detect end of child's output (in theory we could still
- // write to the pipe).
- out_write.reset();
- err_write.reset();
-
- bool out_open = true, err_open = true;
- while (out_open || err_open) {
- fd_set read_fds;
- FD_ZERO(&read_fds);
- FD_SET(out_read.get(), &read_fds);
- FD_SET(err_read.get(), &read_fds);
- int res =
- HANDLE_EINTR(select(std::max(out_read.get(), err_read.get()) + 1,
- &read_fds, nullptr, nullptr, nullptr));
- if (res <= 0)
- break;
- if (FD_ISSET(out_read.get(), &read_fds))
- out_open = ReadFromPipe(out_read.get(), std_out);
- if (FD_ISSET(err_read.get(), &read_fds))
- err_open = ReadFromPipe(err_read.get(), std_err);
- }
-
- base::Process process(pid);
- return process.WaitForExit(exit_code);
- }
- }
-
- return false;
-}
-#endif
-
-} // namespace internal
-
diff --git a/chromium/tools/gn/exec_process.h b/chromium/tools/gn/exec_process.h
deleted file mode 100644
index 4d010d519f9..00000000000
--- a/chromium/tools/gn/exec_process.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_EXEC_PROCESS_H_
-#define TOOLS_GN_EXEC_PROCESS_H_
-
-#include <string>
-
-namespace base {
-class CommandLine;
-class FilePath;
-}
-
-namespace internal {
-
-bool ExecProcess(const base::CommandLine& cmdline,
- const base::FilePath& startup_dir,
- std::string* std_out,
- std::string* std_err,
- int* exit_code);
-
-} // namespace internal
-
-#endif // TOOLS_GN_EXEC_PROCESS_H_
diff --git a/chromium/tools/gn/exec_process_unittest.cc b/chromium/tools/gn/exec_process_unittest.cc
deleted file mode 100644
index 51ce7b753ba..00000000000
--- a/chromium/tools/gn/exec_process_unittest.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/exec_process.h"
-
-#include "base/command_line.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/strings/string_util.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_WIN)
-#include "base/strings/utf_string_conversions.h"
-#endif
-
-namespace internal {
-
-// TODO(cjhopman): Enable these tests when windows ExecProcess handles stderr.
-// 'python' is not runnable on Windows. Adding ["cmd", "/c"] fails because
-// CommandLine does unusual reordering of args.
-#if !defined(OS_WIN)
-namespace {
-bool ExecPython(const std::string& command,
- std::string* std_out,
- std::string* std_err,
- int* exit_code) {
- base::ScopedTempDir temp_dir;
- CHECK(temp_dir.CreateUniqueTempDir());
- base::CommandLine::StringVector args;
-#if defined(OS_WIN)
- args.push_back(L"python");
- args.push_back(L"-c");
- args.push_back(base::UTF8ToUTF16(command));
-#else
- args.push_back("python");
- args.push_back("-c");
- args.push_back(command);
-#endif
- return ExecProcess(base::CommandLine(args), temp_dir.GetPath(), std_out,
- std_err, exit_code);
-}
-} // namespace
-
-TEST(ExecProcessTest, TestExitCode) {
- std::string std_out, std_err;
- int exit_code;
-
- ASSERT_TRUE(
- ExecPython("import sys; sys.exit(0)", &std_out, &std_err, &exit_code));
- EXPECT_EQ(0, exit_code);
-
- ASSERT_TRUE(
- ExecPython("import sys; sys.exit(1)", &std_out, &std_err, &exit_code));
- EXPECT_EQ(1, exit_code);
-
- ASSERT_TRUE(
- ExecPython("import sys; sys.exit(253)", &std_out, &std_err, &exit_code));
- EXPECT_EQ(253, exit_code);
-
- ASSERT_TRUE(
- ExecPython("throw Exception()", &std_out, &std_err, &exit_code));
- EXPECT_EQ(1, exit_code);
-}
-
-// Test that large output is handled correctly. There are various ways that this
-// could potentially fail. For example, non-blocking Linux pipes have a 65536
-// byte buffer and, if stdout is non-blocking, python will throw an IOError when
-// a write exceeds the buffer size.
-TEST(ExecProcessTest, TestLargeOutput) {
- base::ScopedTempDir temp_dir;
- std::string std_out, std_err;
- int exit_code;
-
- ASSERT_TRUE(ExecPython(
- "import sys; print 'o' * 1000000", &std_out, &std_err, &exit_code));
- EXPECT_EQ(0, exit_code);
- EXPECT_EQ(1000001u, std_out.size());
-}
-
-TEST(ExecProcessTest, TestStdoutAndStderrOutput) {
- base::ScopedTempDir temp_dir;
- std::string std_out, std_err;
- int exit_code;
-
- ASSERT_TRUE(ExecPython(
- "import sys; print 'o' * 10000; print >>sys.stderr, 'e' * 10000",
- &std_out,
- &std_err,
- &exit_code));
- EXPECT_EQ(0, exit_code);
- EXPECT_EQ(10001u, std_out.size());
- EXPECT_EQ(10001u, std_err.size());
-
- std_out.clear();
- std_err.clear();
- ASSERT_TRUE(ExecPython(
- "import sys; print >>sys.stderr, 'e' * 10000; print 'o' * 10000",
- &std_out,
- &std_err,
- &exit_code));
- EXPECT_EQ(0, exit_code);
- EXPECT_EQ(10001u, std_out.size());
- EXPECT_EQ(10001u, std_err.size());
-}
-
-TEST(ExecProcessTest, TestOneOutputClosed) {
- std::string std_out, std_err;
- int exit_code;
-
- ASSERT_TRUE(ExecPython("import sys; sys.stderr.close(); print 'o' * 10000",
- &std_out,
- &std_err,
- &exit_code));
- EXPECT_EQ(0, exit_code);
- EXPECT_EQ(10001u, std_out.size());
- EXPECT_EQ(std_err.size(), 0u);
-
- std_out.clear();
- std_err.clear();
- ASSERT_TRUE(ExecPython(
- "import sys; sys.stdout.close(); print >>sys.stderr, 'e' * 10000",
- &std_out,
- &std_err,
- &exit_code));
- EXPECT_EQ(0, exit_code);
- EXPECT_EQ(0u, std_out.size());
- EXPECT_EQ(10001u, std_err.size());
-}
-#endif
-} // namespace internal
diff --git a/chromium/tools/gn/filesystem_utils.cc b/chromium/tools/gn/filesystem_utils.cc
deleted file mode 100644
index f9f6794f95b..00000000000
--- a/chromium/tools/gn/filesystem_utils.cc
+++ /dev/null
@@ -1,1063 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/filesystem_utils.h"
-
-#include <algorithm>
-
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "tools/gn/location.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/source_dir.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-namespace {
-
-enum DotDisposition {
- // The given dot is just part of a filename and is not special.
- NOT_A_DIRECTORY,
-
- // The given dot is the current directory.
- DIRECTORY_CUR,
-
- // The given dot is the first of a double dot that should take us up one.
- DIRECTORY_UP
-};
-
-// When we find a dot, this function is called with the character following
-// that dot to see what it is. The return value indicates what type this dot is
-// (see above). This code handles the case where the dot is at the end of the
-// input.
-//
-// |*consumed_len| will contain the number of characters in the input that
-// express what we found.
-DotDisposition ClassifyAfterDot(const std::string& path,
- size_t after_dot,
- size_t* consumed_len) {
- if (after_dot == path.size()) {
- // Single dot at the end.
- *consumed_len = 1;
- return DIRECTORY_CUR;
- }
- if (IsSlash(path[after_dot])) {
- // Single dot followed by a slash.
- *consumed_len = 2; // Consume the slash
- return DIRECTORY_CUR;
- }
-
- if (path[after_dot] == '.') {
- // Two dots.
- if (after_dot + 1 == path.size()) {
- // Double dot at the end.
- *consumed_len = 2;
- return DIRECTORY_UP;
- }
- if (IsSlash(path[after_dot + 1])) {
- // Double dot folowed by a slash.
- *consumed_len = 3;
- return DIRECTORY_UP;
- }
- }
-
- // The dots are followed by something else, not a directory.
- *consumed_len = 1;
- return NOT_A_DIRECTORY;
-}
-
-#if defined(OS_WIN)
-inline char NormalizeWindowsPathChar(char c) {
- if (c == '/')
- return '\\';
- return base::ToLowerASCII(c);
-}
-
-// Attempts to do a case and slash-insensitive comparison of two 8-bit Windows
-// paths.
-bool AreAbsoluteWindowsPathsEqual(const base::StringPiece& a,
- const base::StringPiece& b) {
- if (a.size() != b.size())
- return false;
-
- // For now, just do a case-insensitive ASCII comparison. We could convert to
- // UTF-16 and use ICU if necessary.
- for (size_t i = 0; i < a.size(); i++) {
- if (NormalizeWindowsPathChar(a[i]) != NormalizeWindowsPathChar(b[i]))
- return false;
- }
- return true;
-}
-
-bool DoesBeginWindowsDriveLetter(const base::StringPiece& path) {
- if (path.size() < 3)
- return false;
-
- // Check colon first, this will generally fail fastest.
- if (path[1] != ':')
- return false;
-
- // Check drive letter.
- if (!base::IsAsciiAlpha(path[0]))
- return false;
-
- if (!IsSlash(path[2]))
- return false;
- return true;
-}
-#endif
-
-// A wrapper around FilePath.GetComponents that works the way we need. This is
-// not super efficient since it does some O(n) transformations on the path. If
-// this is called a lot, we might want to optimize.
-std::vector<base::FilePath::StringType> GetPathComponents(
- const base::FilePath& path) {
- std::vector<base::FilePath::StringType> result;
- path.GetComponents(&result);
-
- if (result.empty())
- return result;
-
- // GetComponents will preserve the "/" at the beginning, which confuses us.
- // We don't expect to have relative paths in this function.
- // Don't use IsSeparator since we always want to allow backslashes.
- if (result[0] == FILE_PATH_LITERAL("/") ||
- result[0] == FILE_PATH_LITERAL("\\"))
- result.erase(result.begin());
-
-#if defined(OS_WIN)
- // On Windows, GetComponents will give us [ "C:", "/", "foo" ], and we
- // don't want the slash in there. This doesn't support input like "C:foo"
- // which means foo relative to the current directory of the C drive but
- // that's basically legacy DOS behavior we don't need to support.
- if (result.size() >= 2 && result[1].size() == 1 &&
- IsSlash(static_cast<char>(result[1][0])))
- result.erase(result.begin() + 1);
-#endif
-
- return result;
-}
-
-// Provides the equivalent of == for filesystem strings, trying to do
-// approximately the right thing with case.
-bool FilesystemStringsEqual(const base::FilePath::StringType& a,
- const base::FilePath::StringType& b) {
-#if defined(OS_WIN)
- // Assume case-insensitive filesystems on Windows. We use the CompareString
- // function to do a case-insensitive comparison based on the current locale
- // (we don't want GN to depend on ICU which is large and requires data
- // files). This isn't perfect, but getting this perfectly right is very
- // difficult and requires I/O, and this comparison should cover 99.9999% of
- // all cases.
- //
- // Note: The documentation for CompareString says it runs fastest on
- // null-terminated strings with -1 passed for the length, so we do that here.
- // There should not be embedded nulls in filesystem strings.
- return ::CompareString(LOCALE_USER_DEFAULT, LINGUISTIC_IGNORECASE,
- a.c_str(), -1, b.c_str(), -1) == CSTR_EQUAL;
-#else
- // Assume case-sensitive filesystems on non-Windows.
- return a == b;
-#endif
-}
-
-// Helper function for computing subdirectories in the build directory
-// corresponding to absolute paths. This will try to resolve the absolute
-// path as a source-relative path first, and otherwise it creates a
-// special subdirectory for absolute paths to keep them from colliding with
-// other generated sources and outputs.
-void AppendFixedAbsolutePathSuffix(const BuildSettings* build_settings,
- const SourceDir& source_dir,
- OutputFile* result) {
- const std::string& build_dir = build_settings->build_dir().value();
-
- if (base::StartsWith(source_dir.value(), build_dir,
- base::CompareCase::SENSITIVE)) {
- size_t build_dir_size = build_dir.size();
- result->value().append(&source_dir.value()[build_dir_size],
- source_dir.value().size() - build_dir_size);
- } else {
- result->value().append("ABS_PATH");
-#if defined(OS_WIN)
- // Windows absolute path contains ':' after drive letter. Remove it to
- // avoid inserting ':' in the middle of path (eg. "ABS_PATH/C:/").
- std::string src_dir_value = source_dir.value();
- const auto colon_pos = src_dir_value.find(':');
- if (colon_pos != std::string::npos)
- src_dir_value.erase(src_dir_value.begin() + colon_pos);
-#else
- const std::string& src_dir_value = source_dir.value();
-#endif
- result->value().append(src_dir_value);
- }
-}
-
-} // namespace
-
-std::string FilePathToUTF8(const base::FilePath::StringType& str) {
-#if defined(OS_WIN)
- return base::WideToUTF8(str);
-#else
- return str;
-#endif
-}
-
-base::FilePath UTF8ToFilePath(const base::StringPiece& sp) {
-#if defined(OS_WIN)
- return base::FilePath(base::UTF8ToWide(sp));
-#else
- return base::FilePath(sp.as_string());
-#endif
-}
-
-size_t FindExtensionOffset(const std::string& path) {
- for (int i = static_cast<int>(path.size()); i >= 0; i--) {
- if (IsSlash(path[i]))
- break;
- if (path[i] == '.')
- return i + 1;
- }
- return std::string::npos;
-}
-
-base::StringPiece FindExtension(const std::string* path) {
- size_t extension_offset = FindExtensionOffset(*path);
- if (extension_offset == std::string::npos)
- return base::StringPiece();
- return base::StringPiece(&path->data()[extension_offset],
- path->size() - extension_offset);
-}
-
-size_t FindFilenameOffset(const std::string& path) {
- for (int i = static_cast<int>(path.size()) - 1; i >= 0; i--) {
- if (IsSlash(path[i]))
- return i + 1;
- }
- return 0; // No filename found means everything was the filename.
-}
-
-base::StringPiece FindFilename(const std::string* path) {
- size_t filename_offset = FindFilenameOffset(*path);
- if (filename_offset == 0)
- return base::StringPiece(*path); // Everything is the file name.
- return base::StringPiece(&(*path).data()[filename_offset],
- path->size() - filename_offset);
-}
-
-base::StringPiece FindFilenameNoExtension(const std::string* path) {
- if (path->empty())
- return base::StringPiece();
- size_t filename_offset = FindFilenameOffset(*path);
- size_t extension_offset = FindExtensionOffset(*path);
-
- size_t name_len;
- if (extension_offset == std::string::npos)
- name_len = path->size() - filename_offset;
- else
- name_len = extension_offset - filename_offset - 1;
-
- return base::StringPiece(&(*path).data()[filename_offset], name_len);
-}
-
-void RemoveFilename(std::string* path) {
- path->resize(FindFilenameOffset(*path));
-}
-
-bool EndsWithSlash(const std::string& s) {
- return !s.empty() && IsSlash(s[s.size() - 1]);
-}
-
-base::StringPiece FindDir(const std::string* path) {
- size_t filename_offset = FindFilenameOffset(*path);
- if (filename_offset == 0u)
- return base::StringPiece();
- return base::StringPiece(path->data(), filename_offset);
-}
-
-base::StringPiece FindLastDirComponent(const SourceDir& dir) {
- const std::string& dir_string = dir.value();
-
- if (dir_string.empty())
- return base::StringPiece();
- int cur = static_cast<int>(dir_string.size()) - 1;
- DCHECK(dir_string[cur] == '/');
- int end = cur;
- cur--; // Skip before the last slash.
-
- for (; cur >= 0; cur--) {
- if (dir_string[cur] == '/')
- return base::StringPiece(&dir_string[cur + 1], end - cur - 1);
- }
- return base::StringPiece(&dir_string[0], end);
-}
-
-bool IsStringInOutputDir(const SourceDir& output_dir, const std::string& str) {
- // This check will be wrong for all proper prefixes "e.g. "/output" will
- // match "/out" but we don't really care since this is just a sanity check.
- const std::string& dir_str = output_dir.value();
- return str.compare(0, dir_str.length(), dir_str) == 0;
-}
-
-bool EnsureStringIsInOutputDir(const SourceDir& output_dir,
- const std::string& str,
- const ParseNode* origin,
- Err* err) {
- if (IsStringInOutputDir(output_dir, str))
- return true; // Output directory is hardcoded.
-
- *err = Err(origin, "File is not inside output directory.",
- "The given file should be in the output directory. Normally you would "
- "specify\n\"$target_out_dir/foo\" or "
- "\"$target_gen_dir/foo\". I interpreted this as\n\""
- + str + "\".");
- return false;
-}
-
-bool IsPathAbsolute(const base::StringPiece& path) {
- if (path.empty())
- return false;
-
- if (!IsSlash(path[0])) {
-#if defined(OS_WIN)
- // Check for Windows system paths like "C:\foo".
- if (path.size() > 2 && path[1] == ':' && IsSlash(path[2]))
- return true;
-#endif
- return false; // Doesn't begin with a slash, is relative.
- }
-
- // Double forward slash at the beginning means source-relative (we don't
- // allow backslashes for denoting this).
- if (path.size() > 1 && path[1] == '/')
- return false;
-
- return true;
-}
-
-bool IsPathSourceAbsolute(const base::StringPiece& path) {
- return (path.size() >= 2 && path[0] == '/' && path[1] == '/');
-}
-
-bool MakeAbsolutePathRelativeIfPossible(const base::StringPiece& source_root,
- const base::StringPiece& path,
- std::string* dest) {
- DCHECK(IsPathAbsolute(source_root));
- DCHECK(IsPathAbsolute(path));
-
- dest->clear();
-
- if (source_root.size() > path.size())
- return false; // The source root is longer: the path can never be inside.
-
-#if defined(OS_WIN)
- // Source root should be canonical on Windows. Note that the initial slash
- // must be forward slash, but that the other ones can be either forward or
- // backward.
- DCHECK(source_root.size() > 2 && source_root[0] != '/' &&
- source_root[1] == ':' && IsSlash(source_root[2]));
-
- size_t after_common_index = std::string::npos;
- if (DoesBeginWindowsDriveLetter(path)) {
- // Handle "C:\foo"
- if (AreAbsoluteWindowsPathsEqual(source_root,
- path.substr(0, source_root.size())))
- after_common_index = source_root.size();
- else
- return false;
- } else if (path[0] == '/' && source_root.size() <= path.size() - 1 &&
- DoesBeginWindowsDriveLetter(path.substr(1))) {
- // Handle "/C:/foo"
- if (AreAbsoluteWindowsPathsEqual(source_root,
- path.substr(1, source_root.size())))
- after_common_index = source_root.size() + 1;
- else
- return false;
- } else {
- return false;
- }
-
- // If we get here, there's a match and after_common_index identifies the
- // part after it.
-
- // The base may or may not have a trailing slash, so skip all slashes from
- // the path after our prefix match.
- size_t first_after_slash = after_common_index;
- while (first_after_slash < path.size() && IsSlash(path[first_after_slash]))
- first_after_slash++;
-
- dest->assign("//"); // Result is source root relative.
- dest->append(&path.data()[first_after_slash],
- path.size() - first_after_slash);
- return true;
-
-#else
-
- // On non-Windows this is easy. Since we know both are absolute, just do a
- // prefix check.
- if (path.substr(0, source_root.size()) == source_root) {
- // The base may or may not have a trailing slash, so skip all slashes from
- // the path after our prefix match.
- size_t first_after_slash = source_root.size();
- while (first_after_slash < path.size() && IsSlash(path[first_after_slash]))
- first_after_slash++;
-
- dest->assign("//"); // Result is source root relative.
- dest->append(&path.data()[first_after_slash],
- path.size() - first_after_slash);
- return true;
- }
- return false;
-#endif
-}
-
-base::FilePath MakeAbsoluteFilePathRelativeIfPossible(
- const base::FilePath& base,
- const base::FilePath& target) {
- DCHECK(base.IsAbsolute());
- DCHECK(target.IsAbsolute());
- std::vector<base::FilePath::StringType> base_components;
- std::vector<base::FilePath::StringType> target_components;
- base.GetComponents(&base_components);
- target.GetComponents(&target_components);
-#if defined(OS_WIN)
- // On Windows, it's impossible to have a relative path from C:\foo to D:\bar,
- // so return the target as an aboslute path instead.
- if (base_components[0] != target_components[0])
- return target;
-#endif
- size_t i;
- for (i = 0; i < base_components.size() && i < target_components.size(); i++) {
- if (base_components[i] != target_components[i])
- break;
- }
- std::vector<base::FilePath::StringType> relative_components;
- for (size_t j = i; j < base_components.size(); j++)
- relative_components.push_back(base::FilePath::kParentDirectory);
- for (size_t j = i; j < target_components.size(); j++)
- relative_components.push_back(target_components[j]);
- if (relative_components.size() <= 1) {
- // In case the file pointed-to is an executable, prepend the current
- // directory to the path -- if the path was "gn", use "./gn" instead. If
- // the file path is used in a command, this prevents issues where "gn" might
- // not be in the PATH (or it is in the path, and the wrong gn is used).
- relative_components.insert(relative_components.begin(),
- base::FilePath::kCurrentDirectory);
- }
- // base::FilePath::Append(component) replaces the file path with |component|
- // if the path is base::Filepath::kCurrentDirectory. We want to preserve the
- // leading "./", so we build the path ourselves and use that to construct the
- // base::FilePath.
- base::FilePath::StringType separator(&base::FilePath::kSeparators[0], 1);
- return base::FilePath(base::JoinString(relative_components, separator));
-}
-
-void NormalizePath(std::string* path, const base::StringPiece& source_root) {
- char* pathbuf = path->empty() ? nullptr : &(*path)[0];
-
- // top_index is the first character we can modify in the path. Anything
- // before this indicates where the path is relative to.
- size_t top_index = 0;
- bool is_relative = true;
- if (!path->empty() && pathbuf[0] == '/') {
- is_relative = false;
-
- if (path->size() > 1 && pathbuf[1] == '/') {
- // Two leading slashes, this is a path into the source dir.
- top_index = 2;
- } else {
- // One leading slash, this is a system-absolute path.
- top_index = 1;
- }
- }
-
- size_t dest_i = top_index;
- for (size_t src_i = top_index; src_i < path->size(); /* nothing */) {
- if (pathbuf[src_i] == '.') {
- if (src_i == 0 || IsSlash(pathbuf[src_i - 1])) {
- // Slash followed by a dot, see if it's something special.
- size_t consumed_len;
- switch (ClassifyAfterDot(*path, src_i + 1, &consumed_len)) {
- case NOT_A_DIRECTORY:
- // Copy the dot to the output, it means nothing special.
- pathbuf[dest_i++] = pathbuf[src_i++];
- break;
- case DIRECTORY_CUR:
- // Current directory, just skip the input.
- src_i += consumed_len;
- break;
- case DIRECTORY_UP:
- // Back up over previous directory component. If we're already
- // at the top, preserve the "..".
- if (dest_i > top_index) {
- // The previous char was a slash, remove it.
- dest_i--;
- }
-
- if (dest_i == top_index) {
- if (is_relative) {
- // We're already at the beginning of a relative input, copy the
- // ".." and continue. We need the trailing slash if there was
- // one before (otherwise we're at the end of the input).
- pathbuf[dest_i++] = '.';
- pathbuf[dest_i++] = '.';
- if (consumed_len == 3)
- pathbuf[dest_i++] = '/';
-
- // This also makes a new "root" that we can't delete by going
- // up more levels. Otherwise "../.." would collapse to
- // nothing.
- top_index = dest_i;
- } else if (top_index == 2 && !source_root.empty()) {
- // |path| was passed in as a source-absolute path. Prepend
- // |source_root| to make |path| absolute. |source_root| must not
- // end with a slash unless we are at root.
- DCHECK(source_root.size() == 1u ||
- !IsSlash(source_root[source_root.size() - 1u]));
- size_t source_root_len = source_root.size();
-
-#if defined(OS_WIN)
- // On Windows, if the source_root does not start with a slash,
- // append one here for consistency.
- if (!IsSlash(source_root[0])) {
- path->insert(0, "/" + source_root.as_string());
- source_root_len++;
- } else {
- path->insert(0, source_root.data(), source_root_len);
- }
-
- // Normalize slashes in source root portion.
- for (size_t i = 0; i < source_root_len; ++i) {
- if ((*path)[i] == '\\')
- (*path)[i] = '/';
- }
-#else
- path->insert(0, source_root.data(), source_root_len);
-#endif
-
- // |path| is now absolute, so |top_index| is 1. |dest_i| and
- // |src_i| should be incremented to keep the same relative
- // position. Comsume the leading "//" by decrementing |dest_i|.
- top_index = 1;
- pathbuf = &(*path)[0];
- dest_i += source_root_len - 2;
- src_i += source_root_len;
-
- // Just find the previous slash or the beginning of input.
- while (dest_i > 0 && !IsSlash(pathbuf[dest_i - 1]))
- dest_i--;
- }
- // Otherwise we're at the beginning of a system-absolute path, or
- // a source-absolute path for which we don't know the absolute
- // path. Don't allow ".." to go up another level, and just eat it.
- } else {
- // Just find the previous slash or the beginning of input.
- while (dest_i > 0 && !IsSlash(pathbuf[dest_i - 1]))
- dest_i--;
- }
- src_i += consumed_len;
- }
- } else {
- // Dot not preceeded by a slash, copy it literally.
- pathbuf[dest_i++] = pathbuf[src_i++];
- }
- } else if (IsSlash(pathbuf[src_i])) {
- if (src_i > 0 && IsSlash(pathbuf[src_i - 1])) {
- // Two slashes in a row, skip over it.
- src_i++;
- } else {
- // Just one slash, copy it, normalizing to foward slash.
- pathbuf[dest_i] = '/';
- dest_i++;
- src_i++;
- }
- } else {
- // Input nothing special, just copy it.
- pathbuf[dest_i++] = pathbuf[src_i++];
- }
- }
- path->resize(dest_i);
-}
-
-void ConvertPathToSystem(std::string* path) {
-#if defined(OS_WIN)
- for (size_t i = 0; i < path->size(); i++) {
- if ((*path)[i] == '/')
- (*path)[i] = '\\';
- }
-#endif
-}
-
-std::string MakeRelativePath(const std::string& input,
- const std::string& dest) {
-#if defined(OS_WIN)
- // Make sure that absolute |input| path starts with a slash if |dest| path
- // does. Otherwise skipping common prefixes won't work properly. Ensure the
- // same for |dest| path too.
- if (IsPathAbsolute(input) && !IsSlash(input[0]) && IsSlash(dest[0])) {
- std::string corrected_input(1, dest[0]);
- corrected_input.append(input);
- return MakeRelativePath(corrected_input, dest);
- }
- if (IsPathAbsolute(dest) && !IsSlash(dest[0]) && IsSlash(input[0])) {
- std::string corrected_dest(1, input[0]);
- corrected_dest.append(dest);
- return MakeRelativePath(input, corrected_dest);
- }
-
- // Make sure that both absolute paths use the same drive letter case.
- if (IsPathAbsolute(input) && IsPathAbsolute(dest) && input.size() > 1 &&
- dest.size() > 1) {
- int letter_pos = base::IsAsciiAlpha(input[0]) ? 0 : 1;
- if (input[letter_pos] != dest[letter_pos] &&
- base::ToUpperASCII(input[letter_pos]) ==
- base::ToUpperASCII(dest[letter_pos])) {
- std::string corrected_input = input;
- corrected_input[letter_pos] = dest[letter_pos];
- return MakeRelativePath(corrected_input, dest);
- }
- }
-#endif
-
- std::string ret;
-
- // Skip the common prefixes of the source and dest as long as they end in
- // a [back]slash.
- size_t common_prefix_len = 0;
- size_t max_common_length = std::min(input.size(), dest.size());
- for (size_t i = common_prefix_len; i < max_common_length; i++) {
- if (IsSlash(input[i]) && IsSlash(dest[i]))
- common_prefix_len = i + 1;
- else if (input[i] != dest[i])
- break;
- }
-
- // Invert the dest dir starting from the end of the common prefix.
- for (size_t i = common_prefix_len; i < dest.size(); i++) {
- if (IsSlash(dest[i]))
- ret.append("../");
- }
-
- // Append any remaining unique input.
- ret.append(&input[common_prefix_len], input.size() - common_prefix_len);
-
- // If the result is still empty, the paths are the same.
- if (ret.empty())
- ret.push_back('.');
-
- return ret;
-}
-
-std::string RebasePath(const std::string& input,
- const SourceDir& dest_dir,
- const base::StringPiece& source_root) {
- std::string ret;
- DCHECK(source_root.empty() || !source_root.ends_with("/"));
-
- bool input_is_source_path = (input.size() >= 2 &&
- input[0] == '/' && input[1] == '/');
-
- if (!source_root.empty() &&
- (!input_is_source_path || !dest_dir.is_source_absolute())) {
- std::string input_full;
- std::string dest_full;
- if (input_is_source_path) {
- source_root.AppendToString(&input_full);
- input_full.push_back('/');
- input_full.append(input, 2, std::string::npos);
- } else {
- input_full.append(input);
- }
- if (dest_dir.is_source_absolute()) {
- source_root.AppendToString(&dest_full);
- dest_full.push_back('/');
- dest_full.append(dest_dir.value(), 2, std::string::npos);
- } else {
-#if defined(OS_WIN)
- // On Windows, SourceDir system-absolute paths start
- // with /, e.g. "/C:/foo/bar".
- const std::string& value = dest_dir.value();
- if (value.size() > 2 && value[2] == ':')
- dest_full.append(dest_dir.value().substr(1));
- else
- dest_full.append(dest_dir.value());
-#else
- dest_full.append(dest_dir.value());
-#endif
- }
- bool remove_slash = false;
- if (!EndsWithSlash(input_full)) {
- input_full.push_back('/');
- remove_slash = true;
- }
- ret = MakeRelativePath(input_full, dest_full);
- if (remove_slash && ret.size() > 1)
- ret.resize(ret.size() - 1);
- return ret;
- }
-
- ret = MakeRelativePath(input, dest_dir.value());
- return ret;
-}
-
-base::FilePath ResolvePath(const std::string& value,
- bool as_file,
- const base::FilePath& source_root) {
- if (value.empty())
- return base::FilePath();
-
- std::string converted;
- if (!IsPathSourceAbsolute(value)) {
- if (value.size() > 2 && value[2] == ':') {
- // Windows path, strip the leading slash.
- converted.assign(&value[1], value.size() - 1);
- } else {
- converted.assign(value);
- }
- return base::FilePath(UTF8ToFilePath(converted));
- }
-
- // String the double-leading slash for source-relative paths.
- converted.assign(&value[2], value.size() - 2);
-
- if (as_file && source_root.empty())
- return UTF8ToFilePath(converted).NormalizePathSeparatorsTo('/');
-
- return source_root.Append(UTF8ToFilePath(converted))
- .NormalizePathSeparatorsTo('/');
-}
-
-template <typename StringType>
-std::string ResolveRelative(const StringType& input,
- const std::string& value,
- bool as_file,
- const base::StringPiece& source_root) {
- std::string result;
-
- if (input.size() >= 2 && input[0] == '/' && input[1] == '/') {
- // Source-relative.
- result.assign(input.data(), input.size());
- if (!as_file) {
- if (!EndsWithSlash(result))
- result.push_back('/');
- }
- NormalizePath(&result, source_root);
- return result;
- } else if (IsPathAbsolute(input)) {
- if (source_root.empty() ||
- !MakeAbsolutePathRelativeIfPossible(source_root, input, &result)) {
-#if defined(OS_WIN)
- if (input[0] != '/') // See the file case for why we do this check.
- result = "/";
-#endif
- result.append(input.data(), input.size());
- }
- NormalizePath(&result);
- if (!as_file) {
- if (!EndsWithSlash(result))
- result.push_back('/');
- }
- return result;
- }
-
- if (!source_root.empty()) {
- std::string absolute =
- FilePathToUTF8(ResolvePath(value, as_file, UTF8ToFilePath(source_root))
- .AppendASCII(input)
- .value());
- NormalizePath(&absolute);
- if (!MakeAbsolutePathRelativeIfPossible(source_root, absolute, &result)) {
-#if defined(OS_WIN)
- if (absolute[0] != '/') // See the file case for why we do this check.
- result = "/";
-#endif
- result.append(absolute.data(), absolute.size());
- }
- if (!as_file && !EndsWithSlash(result))
- result.push_back('/');
- return result;
- }
-
- // With no source_root, there's nothing we can do about
- // e.g. input=../../../path/to/file and value=//source and we'll
- // errornously return //file.
- result.reserve(value.size() + input.size());
- result.assign(value);
- result.append(input.data(), input.size());
-
- NormalizePath(&result);
- if (!as_file && !EndsWithSlash(result))
- result.push_back('/');
-
- return result;
-}
-
-// Explicit template instantiation
-template std::string ResolveRelative(const base::StringPiece& input,
- const std::string& value,
- bool as_file,
- const base::StringPiece& source_root);
-
-template std::string ResolveRelative(const std::string& input,
- const std::string& value,
- bool as_file,
- const base::StringPiece& source_root);
-
-std::string DirectoryWithNoLastSlash(const SourceDir& dir) {
- std::string ret;
-
- if (dir.value().empty()) {
- // Just keep input the same.
- } else if (dir.value() == "/") {
- ret.assign("/.");
- } else if (dir.value() == "//") {
- ret.assign("//.");
- } else {
- ret.assign(dir.value());
- ret.resize(ret.size() - 1);
- }
- return ret;
-}
-
-SourceDir SourceDirForPath(const base::FilePath& source_root,
- const base::FilePath& path) {
- std::vector<base::FilePath::StringType> source_comp =
- GetPathComponents(source_root);
- std::vector<base::FilePath::StringType> path_comp =
- GetPathComponents(path);
-
- // See if path is inside the source root by looking for each of source root's
- // components at the beginning of path.
- bool is_inside_source;
- if (path_comp.size() < source_comp.size() || source_root.empty()) {
- // Too small to fit.
- is_inside_source = false;
- } else {
- is_inside_source = true;
- for (size_t i = 0; i < source_comp.size(); i++) {
- if (!FilesystemStringsEqual(source_comp[i], path_comp[i])) {
- is_inside_source = false;
- break;
- }
- }
- }
-
- std::string result_str;
- size_t initial_path_comp_to_use;
- if (is_inside_source) {
- // Construct a source-relative path beginning in // and skip all of the
- // shared directories.
- result_str = "//";
- initial_path_comp_to_use = source_comp.size();
- } else {
- // Not inside source code, construct a system-absolute path.
- result_str = "/";
- initial_path_comp_to_use = 0;
- }
-
- for (size_t i = initial_path_comp_to_use; i < path_comp.size(); i++) {
- result_str.append(FilePathToUTF8(path_comp[i]));
- result_str.push_back('/');
- }
- return SourceDir(result_str);
-}
-
-SourceDir SourceDirForCurrentDirectory(const base::FilePath& source_root) {
- base::FilePath cd;
- base::GetCurrentDirectory(&cd);
- return SourceDirForPath(source_root, cd);
-}
-
-std::string GetOutputSubdirName(const Label& toolchain_label, bool is_default) {
- // The default toolchain has no subdir.
- if (is_default)
- return std::string();
-
- // For now just assume the toolchain name is always a valid dir name. We may
- // want to clean up the in the future.
- return toolchain_label.name() + "/";
-}
-
-bool ContentsEqual(const base::FilePath& file_path, const std::string& data) {
- // Compare file and stream sizes first. Quick and will save us some time if
- // they are different sizes.
- int64_t file_size;
- if (!base::GetFileSize(file_path, &file_size) ||
- static_cast<size_t>(file_size) != data.size()) {
- return false;
- }
-
- std::string file_data;
- file_data.resize(file_size);
- if (!base::ReadFileToString(file_path, &file_data))
- return false;
-
- return file_data == data;
-}
-
-bool WriteFileIfChanged(const base::FilePath& file_path,
- const std::string& data,
- Err* err) {
- if (ContentsEqual(file_path, data))
- return true;
-
- return WriteFile(file_path, data, err);
-}
-
-bool WriteFile(const base::FilePath& file_path, const std::string& data,
- Err* err) {
- // Create the directory if necessary.
- if (!base::CreateDirectory(file_path.DirName())) {
- if (err) {
- *err =
- Err(Location(), "Unable to create directory.",
- "I was using \"" + FilePathToUTF8(file_path.DirName()) + "\".");
- }
- return false;
- }
-
- int size = static_cast<int>(data.size());
- bool write_success = false;
-
-#if defined(OS_WIN)
- // On Windows, provide a custom implementation of base::WriteFile. Sometimes
- // the base version fails, especially on the bots. The guess is that Windows
- // Defender or other antivirus programs still have the file open (after
- // checking for the read) when the write happens immediately after. This
- // version opens with FILE_SHARE_READ (normally not what you want when
- // replacing the entire contents of the file) which lets us continue even if
- // another program has the file open for reading. See http://crbug.com/468437
- base::win::ScopedHandle file(::CreateFile(file_path.value().c_str(),
- GENERIC_WRITE, FILE_SHARE_READ,
- NULL, CREATE_ALWAYS, 0, NULL));
- if (file.IsValid()) {
- DWORD written;
- BOOL result = ::WriteFile(file.Get(), data.c_str(), size, &written, NULL);
- if (result) {
- if (static_cast<int>(written) == size) {
- write_success = true;
- } else {
- // Didn't write all the bytes.
- LOG(ERROR) << "wrote" << written << " bytes to "
- << base::UTF16ToUTF8(file_path.value()) << " expected "
- << size;
- }
- } else {
- // WriteFile failed.
- PLOG(ERROR) << "writing file " << base::UTF16ToUTF8(file_path.value())
- << " failed";
- }
- } else {
- PLOG(ERROR) << "CreateFile failed for path "
- << base::UTF16ToUTF8(file_path.value());
- }
-#else
- write_success = base::WriteFile(file_path, data.c_str(), size) == size;
-#endif
-
- if (!write_success && err) {
- *err = Err(Location(), "Unable to write file.",
- "I was writing \"" + FilePathToUTF8(file_path) + "\".");
- }
-
- return write_success;
-}
-
-BuildDirContext::BuildDirContext(const Target* target)
- : BuildDirContext(target->settings()) {
-}
-
-BuildDirContext::BuildDirContext(const Settings* settings)
- : BuildDirContext(settings->build_settings(),
- settings->toolchain_label(),
- settings->is_default()) {
-}
-
-BuildDirContext::BuildDirContext(const Scope* execution_scope)
- : BuildDirContext(execution_scope->settings()) {
-}
-
-BuildDirContext::BuildDirContext(const Scope* execution_scope,
- const Label& toolchain_label)
- : BuildDirContext(execution_scope->settings()->build_settings(),
- toolchain_label,
- execution_scope->settings()->default_toolchain_label() ==
- toolchain_label) {
-}
-
-BuildDirContext::BuildDirContext(const BuildSettings* in_build_settings,
- const Label& in_toolchain_label,
- bool in_is_default_toolchain)
- : build_settings(in_build_settings),
- toolchain_label(in_toolchain_label),
- is_default_toolchain(in_is_default_toolchain) {
-}
-
-SourceDir GetBuildDirAsSourceDir(const BuildDirContext& context,
- BuildDirType type) {
- return GetBuildDirAsOutputFile(context, type).AsSourceDir(
- context.build_settings);
-}
-
-OutputFile GetBuildDirAsOutputFile(const BuildDirContext& context,
- BuildDirType type) {
- OutputFile result(GetOutputSubdirName(context.toolchain_label,
- context.is_default_toolchain));
- DCHECK(result.value().empty() || result.value().back() == '/');
-
- if (type == BuildDirType::GEN)
- result.value().append("gen/");
- else if (type == BuildDirType::OBJ)
- result.value().append("obj/");
- return result;
-}
-
-SourceDir GetSubBuildDirAsSourceDir(const BuildDirContext& context,
- const SourceDir& source_dir,
- BuildDirType type) {
- return GetSubBuildDirAsOutputFile(context, source_dir, type)
- .AsSourceDir(context.build_settings);
-}
-
-OutputFile GetSubBuildDirAsOutputFile(const BuildDirContext& context,
- const SourceDir& source_dir,
- BuildDirType type) {
- DCHECK(type != BuildDirType::TOOLCHAIN_ROOT);
- OutputFile result = GetBuildDirAsOutputFile(context, type);
-
- if (source_dir.is_source_absolute()) {
- // The source dir is source-absolute, so we trim off the two leading
- // slashes to append to the toolchain object directory.
- result.value().append(&source_dir.value()[2],
- source_dir.value().size() - 2);
- } else {
- // System-absolute.
- AppendFixedAbsolutePathSuffix(context.build_settings, source_dir, &result);
- }
- return result;
-}
-
-SourceDir GetBuildDirForTargetAsSourceDir(const Target* target,
- BuildDirType type) {
- return GetSubBuildDirAsSourceDir(
- BuildDirContext(target), target->label().dir(), type);
-}
-
-OutputFile GetBuildDirForTargetAsOutputFile(const Target* target,
- BuildDirType type) {
- return GetSubBuildDirAsOutputFile(
- BuildDirContext(target), target->label().dir(), type);
-}
-
-SourceDir GetScopeCurrentBuildDirAsSourceDir(const Scope* scope,
- BuildDirType type) {
- if (type == BuildDirType::TOOLCHAIN_ROOT)
- return GetBuildDirAsSourceDir(BuildDirContext(scope), type);
- return GetSubBuildDirAsSourceDir(
- BuildDirContext(scope), scope->GetSourceDir(), type);
-}
diff --git a/chromium/tools/gn/filesystem_utils.h b/chromium/tools/gn/filesystem_utils.h
deleted file mode 100644
index 1313279b4c0..00000000000
--- a/chromium/tools/gn/filesystem_utils.h
+++ /dev/null
@@ -1,304 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_FILESYSTEM_UTILS_H_
-#define TOOLS_GN_FILESYSTEM_UTILS_H_
-
-#include <stddef.h>
-
-#include <string>
-
-#include "base/files/file_path.h"
-#include "base/strings/string_piece.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/target.h"
-
-class Err;
-
-std::string FilePathToUTF8(const base::FilePath::StringType& str);
-inline std::string FilePathToUTF8(const base::FilePath& path) {
- return FilePathToUTF8(path.value());
-}
-base::FilePath UTF8ToFilePath(const base::StringPiece& sp);
-
-// Extensions -----------------------------------------------------------------
-
-// Returns the index of the extension (character after the last dot not after a
-// slash). Returns std::string::npos if not found. Returns path.size() if the
-// file ends with a dot.
-size_t FindExtensionOffset(const std::string& path);
-
-// Returns a string piece pointing into the input string identifying the
-// extension. Note that the input pointer must outlive the output.
-base::StringPiece FindExtension(const std::string* path);
-
-// Filename parts -------------------------------------------------------------
-
-// Returns the offset of the character following the last slash, or
-// 0 if no slash was found. Returns path.size() if the path ends with a slash.
-// Note that the input pointer must outlive the output.
-size_t FindFilenameOffset(const std::string& path);
-
-// Returns a string piece pointing into the input string identifying the
-// file name (following the last slash, including the extension). Note that the
-// input pointer must outlive the output.
-base::StringPiece FindFilename(const std::string* path);
-
-// Like FindFilename but does not include the extension.
-base::StringPiece FindFilenameNoExtension(const std::string* path);
-
-// Removes everything after the last slash. The last slash, if any, will be
-// preserved.
-void RemoveFilename(std::string* path);
-
-// Returns if the given character is a slash. This allows both slashes and
-// backslashes for consistency between Posix and Windows (as opposed to
-// FilePath::IsSeparator which is based on the current platform).
-inline bool IsSlash(const char ch) {
- return ch == '/' || ch == '\\';
-}
-
-// Returns true if the given path ends with a slash.
-bool EndsWithSlash(const std::string& s);
-
-// Path parts -----------------------------------------------------------------
-
-// Returns a string piece pointing into the input string identifying the
-// directory name of the given path, including the last slash. Note that the
-// input pointer must outlive the output.
-base::StringPiece FindDir(const std::string* path);
-
-// Returns the substring identifying the last component of the dir, or the
-// empty substring if none. For example "//foo/bar/" -> "bar".
-base::StringPiece FindLastDirComponent(const SourceDir& dir);
-
-// Returns true if the given string is in the given output dir. This is pretty
-// stupid and doesn't handle "." and "..", etc., it is designed for a sanity
-// check to keep people from writing output files to the source directory
-// accidentally.
-bool IsStringInOutputDir(const SourceDir& output_dir, const std::string& str);
-
-// Verifies that the given string references a file inside of the given
-// directory. This just uses IsStringInOutputDir above.
-//
-// The origin will be blamed in the error.
-//
-// If the file isn't in the dir, returns false and sets the error. Otherwise
-// returns true and leaves the error untouched.
-bool EnsureStringIsInOutputDir(const SourceDir& output_dir,
- const std::string& str,
- const ParseNode* origin,
- Err* err);
-
-// ----------------------------------------------------------------------------
-
-// Returns true if the input string is absolute. Double-slashes at the
-// beginning are treated as source-relative paths. On Windows, this handles
-// paths of both the native format: "C:/foo" and ours "/C:/foo"
-bool IsPathAbsolute(const base::StringPiece& path);
-
-// Returns true if the input string is source-absolute. Source-absolute
-// paths begin with two forward slashes and resolve as if they are
-// relative to the source root.
-bool IsPathSourceAbsolute(const base::StringPiece& path);
-
-// Given an absolute path, checks to see if is it is inside the source root.
-// If it is, fills a source-absolute path into the given output and returns
-// true. If it isn't, clears the dest and returns false.
-//
-// The source_root should be a base::FilePath converted to UTF-8. On Windows,
-// it should begin with a "C:/" rather than being our SourceFile's style
-// ("/C:/"). The source root can end with a slash or not.
-//
-// Note that this does not attempt to normalize slashes in the output.
-bool MakeAbsolutePathRelativeIfPossible(const base::StringPiece& source_root,
- const base::StringPiece& path,
- std::string* dest);
-
-// Given two absolute paths |base| and |target|, returns a relative path to
-// |target| as if the current directory was |base|. The relative path returned
-// is minimal. For example, if "../../a/b/" and "../b" are both valid, then the
-// latter will be returned. On Windows, it's impossible to have a relative path
-// from C:\foo to D:\bar, so the absolute path |target| is returned instead for
-// this case.
-base::FilePath MakeAbsoluteFilePathRelativeIfPossible(
- const base::FilePath& base,
- const base::FilePath& target);
-
-// Collapses "." and sequential "/"s and evaluates "..". |path| may be
-// system-absolute, source-absolute, or relative. If |path| is source-absolute
-// and |source_root| is non-empty, |path| may be system absolute after this
-// function returns, if |path| references the filesystem outside of
-// |source_root| (ex. path = "//.."). In this case on Windows, |path| will have
-// a leading slash. Otherwise, |path| will retain its relativity. |source_root|
-// must not end with a slash.
-void NormalizePath(std::string* path,
- const base::StringPiece& source_root = base::StringPiece());
-
-// Converts slashes to backslashes for Windows. Keeps the string unchanged
-// for other systems.
-void ConvertPathToSystem(std::string* path);
-
-// Takes a path, |input|, and makes it relative to the given directory
-// |dest_dir|. Both inputs may be source-relative (e.g. begins with
-// with "//") or may be absolute.
-//
-// If supplied, the |source_root| parameter is the absolute path to
-// the source root and not end in a slash. Unless you know that the
-// inputs are always source relative, this should be supplied.
-std::string RebasePath(
- const std::string& input,
- const SourceDir& dest_dir,
- const base::StringPiece& source_root = base::StringPiece());
-
-// Resolves a file or dir name (parameter input) relative to
-// value directory. Will return an empty SourceDir/File on error
-// and set the give *err pointer (required). Empty input is always an error.
-// Returned value can be used to set value in either SourceFile or SourceDir
-// (based on as_file parameter).
-//
-// Parameter as_file defines whether result path will look like a file path
-// or it should be treated as a directory (contains "/" and the end
-// of the string).
-//
-// If source_root is supplied, these functions will additionally handle the
-// case where the input is a system-absolute but still inside the source
-// tree. This is the case for some external tools.
-template <typename StringType>
-std::string ResolveRelative(const StringType& input,
- const std::string& value,
- bool as_file,
- const base::StringPiece& source_root);
-
-// Resolves source file or directory relative to some given source root. Returns
-// an empty file path on error.
-base::FilePath ResolvePath(const std::string& value,
- bool as_file,
- const base::FilePath& source_root);
-
-// Returns the given directory with no terminating slash at the end, such that
-// appending a slash and more stuff will produce a valid path.
-//
-// If the directory refers to either the source or system root, we'll append
-// a "." so this remains valid.
-std::string DirectoryWithNoLastSlash(const SourceDir& dir);
-
-// Returns the "best" SourceDir representing the given path. If it's inside the
-// given source_root, a source-relative directory will be returned (e.g.
-// "//foo/bar.cc". If it's outside of the source root or the source root is
-// empty, a system-absolute directory will be returned.
-SourceDir SourceDirForPath(const base::FilePath& source_root,
- const base::FilePath& path);
-
-// Like SourceDirForPath but returns the SourceDir representing the current
-// directory.
-SourceDir SourceDirForCurrentDirectory(const base::FilePath& source_root);
-
-// Given the label of a toolchain and whether that toolchain is the default
-// toolchain, returns the name of the subdirectory for that toolchain's
-// output. This will be the empty string to indicate that the toolchain outputs
-// go in the root build directory. Otherwise, the result will end in a slash.
-std::string GetOutputSubdirName(const Label& toolchain_label, bool is_default);
-
-// Returns true if the contents of the file and stream given are equal, false
-// otherwise.
-bool ContentsEqual(const base::FilePath& file_path, const std::string& data);
-
-// Writes given stream contents to the given file if it differs from existing
-// file contents. Returns true if new contents was successfully written or
-// existing file contents doesn't need updating, false on write error. |err| is
-// set on write error if not nullptr.
-bool WriteFileIfChanged(const base::FilePath& file_path,
- const std::string& data,
- Err* err);
-
-// Writes given stream contents to the given file. Returns true if data was
-// successfully written, false otherwise. |err| is set on error if not nullptr.
-bool WriteFile(const base::FilePath& file_path, const std::string& data,
- Err* err);
-
-// -----------------------------------------------------------------------------
-
-enum class BuildDirType {
- // Returns the root toolchain dir rather than the generated or output
- // subdirectories. This is valid only for the toolchain directory getters.
- // Asking for this for a target or source dir makes no sense.
- TOOLCHAIN_ROOT,
-
- // Generated file directory.
- GEN,
-
- // Output file directory.
- OBJ,
-};
-
-// In different contexts, different information is known about the toolchain in
-// question. If you have a Target or settings object, everything can be
-// extracted from there. But when querying label information on something in
-// another toolchain, for example, the only thing known (it may not even exist)
-// is the toolchain label string and whether it matches the default toolchain.
-//
-// This object extracts the relevant information from a variety of input
-// types for the convenience of the caller.
-class BuildDirContext {
- public:
- // Extracts toolchain information associated with the given target.
- explicit BuildDirContext(const Target* target);
-
- // Extracts toolchain information associated with the given settings object.
- explicit BuildDirContext(const Settings* settings);
-
- // Extrats toolchain information from the current toolchain of the scope.
- explicit BuildDirContext(const Scope* execution_scope);
-
- // Extracts the default toolchain information from the given execution
- // scope. The toolchain you want to query must be passed in. This doesn't
- // use the settings object from the Scope so one can query other toolchains.
- // If you want to use the scope's current toolchain, use the version above.
- BuildDirContext(const Scope* execution_scope, const Label& toolchain_label);
-
- // Specify all information manually.
- BuildDirContext(const BuildSettings* build_settings,
- const Label& toolchain_label,
- bool is_default_toolchain);
-
- const BuildSettings* build_settings;
- const Label& toolchain_label;
- bool is_default_toolchain;
-};
-
-// Returns the root, object, or generated file directory for the toolchain.
-//
-// The toolchain object file root is never exposed in GN (there is no
-// root_obj_dir variable) so BuildDirType::OBJ would normally never be passed
-// to this function except when it's called by one of the variants below that
-// append paths to it.
-SourceDir GetBuildDirAsSourceDir(const BuildDirContext& context,
- BuildDirType type);
-OutputFile GetBuildDirAsOutputFile(const BuildDirContext& context,
- BuildDirType type);
-
-// Returns the output or generated file directory corresponding to the given
-// source directory.
-SourceDir GetSubBuildDirAsSourceDir(const BuildDirContext& context,
- const SourceDir& source_dir,
- BuildDirType type);
-OutputFile GetSubBuildDirAsOutputFile(const BuildDirContext& context,
- const SourceDir& source_dir,
- BuildDirType type);
-
-// Returns the output or generated file directory corresponding to the given
-// target.
-SourceDir GetBuildDirForTargetAsSourceDir(const Target* target,
- BuildDirType type);
-OutputFile GetBuildDirForTargetAsOutputFile(const Target* target,
- BuildDirType type);
-
-// Returns the scope's current directory.
-SourceDir GetScopeCurrentBuildDirAsSourceDir(const Scope* scope,
- BuildDirType type);
-// Lack of OutputDir version is due only to it not currently being needed,
-// please add one if you need it.
-
-#endif // TOOLS_GN_FILESYSTEM_UTILS_H_
diff --git a/chromium/tools/gn/filesystem_utils_unittest.cc b/chromium/tools/gn/filesystem_utils_unittest.cc
deleted file mode 100644
index dc2e512b8db..00000000000
--- a/chromium/tools/gn/filesystem_utils_unittest.cc
+++ /dev/null
@@ -1,850 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/platform_thread.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/target.h"
-
-TEST(FilesystemUtils, FileExtensionOffset) {
- EXPECT_EQ(std::string::npos, FindExtensionOffset(""));
- EXPECT_EQ(std::string::npos, FindExtensionOffset("foo/bar/baz"));
- EXPECT_EQ(4u, FindExtensionOffset("foo."));
- EXPECT_EQ(4u, FindExtensionOffset("f.o.bar"));
- EXPECT_EQ(std::string::npos, FindExtensionOffset("foo.bar/"));
- EXPECT_EQ(std::string::npos, FindExtensionOffset("foo.bar/baz"));
-}
-
-TEST(FilesystemUtils, FindExtension) {
- std::string input;
- EXPECT_EQ("", FindExtension(&input).as_string());
- input = "foo/bar/baz";
- EXPECT_EQ("", FindExtension(&input).as_string());
- input = "foo.";
- EXPECT_EQ("", FindExtension(&input).as_string());
- input = "f.o.bar";
- EXPECT_EQ("bar", FindExtension(&input).as_string());
- input = "foo.bar/";
- EXPECT_EQ("", FindExtension(&input).as_string());
- input = "foo.bar/baz";
- EXPECT_EQ("", FindExtension(&input).as_string());
-}
-
-TEST(FilesystemUtils, FindFilenameOffset) {
- EXPECT_EQ(0u, FindFilenameOffset(""));
- EXPECT_EQ(0u, FindFilenameOffset("foo"));
- EXPECT_EQ(4u, FindFilenameOffset("foo/"));
- EXPECT_EQ(4u, FindFilenameOffset("foo/bar"));
-}
-
-TEST(FilesystemUtils, RemoveFilename) {
- std::string s;
-
- RemoveFilename(&s);
- EXPECT_STREQ("", s.c_str());
-
- s = "foo";
- RemoveFilename(&s);
- EXPECT_STREQ("", s.c_str());
-
- s = "/";
- RemoveFilename(&s);
- EXPECT_STREQ("/", s.c_str());
-
- s = "foo/bar";
- RemoveFilename(&s);
- EXPECT_STREQ("foo/", s.c_str());
-
- s = "foo/bar/baz.cc";
- RemoveFilename(&s);
- EXPECT_STREQ("foo/bar/", s.c_str());
-}
-
-TEST(FilesystemUtils, FindDir) {
- std::string input;
- EXPECT_EQ("", FindDir(&input));
- input = "/";
- EXPECT_EQ("/", FindDir(&input));
- input = "foo/";
- EXPECT_EQ("foo/", FindDir(&input));
- input = "foo/bar/baz";
- EXPECT_EQ("foo/bar/", FindDir(&input));
-}
-
-TEST(FilesystemUtils, FindLastDirComponent) {
- SourceDir empty;
- EXPECT_EQ("", FindLastDirComponent(empty));
-
- SourceDir root("/");
- EXPECT_EQ("", FindLastDirComponent(root));
-
- SourceDir srcroot("//");
- EXPECT_EQ("", FindLastDirComponent(srcroot));
-
- SourceDir regular1("//foo/");
- EXPECT_EQ("foo", FindLastDirComponent(regular1));
-
- SourceDir regular2("//foo/bar/");
- EXPECT_EQ("bar", FindLastDirComponent(regular2));
-}
-
-TEST(FilesystemUtils, EnsureStringIsInOutputDir) {
- SourceDir output_dir("//out/Debug/");
-
- // Some outside.
- Err err;
- EXPECT_FALSE(EnsureStringIsInOutputDir(output_dir, "//foo", nullptr, &err));
- EXPECT_TRUE(err.has_error());
- err = Err();
- EXPECT_FALSE(
- EnsureStringIsInOutputDir(output_dir, "//out/Debugit", nullptr, &err));
- EXPECT_TRUE(err.has_error());
-
- // Some inside.
- err = Err();
- EXPECT_TRUE(
- EnsureStringIsInOutputDir(output_dir, "//out/Debug/", nullptr, &err));
- EXPECT_FALSE(err.has_error());
- EXPECT_TRUE(
- EnsureStringIsInOutputDir(output_dir, "//out/Debug/foo", nullptr, &err));
- EXPECT_FALSE(err.has_error());
-
- // Pattern but no template expansions are allowed.
- EXPECT_FALSE(EnsureStringIsInOutputDir(output_dir, "{{source_gen_dir}}",
- nullptr, &err));
- EXPECT_TRUE(err.has_error());
-}
-
-TEST(FilesystemUtils, IsPathAbsolute) {
- EXPECT_TRUE(IsPathAbsolute("/foo/bar"));
- EXPECT_TRUE(IsPathAbsolute("/"));
- EXPECT_FALSE(IsPathAbsolute(""));
- EXPECT_FALSE(IsPathAbsolute("//"));
- EXPECT_FALSE(IsPathAbsolute("//foo/bar"));
-
-#if defined(OS_WIN)
- EXPECT_TRUE(IsPathAbsolute("C:/foo"));
- EXPECT_TRUE(IsPathAbsolute("C:/"));
- EXPECT_TRUE(IsPathAbsolute("C:\\foo"));
- EXPECT_TRUE(IsPathAbsolute("C:\\"));
- EXPECT_TRUE(IsPathAbsolute("/C:/foo"));
- EXPECT_TRUE(IsPathAbsolute("/C:\\foo"));
-#endif
-}
-
-TEST(FilesystemUtils, MakeAbsolutePathRelativeIfPossible) {
- std::string dest;
-
-#if defined(OS_WIN)
- EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("C:\\base", "C:\\base\\foo",
- &dest));
- EXPECT_EQ("//foo", dest);
- EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("C:\\base", "/C:/base/foo",
- &dest));
- EXPECT_EQ("//foo", dest);
- EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("c:\\base", "C:\\base\\foo\\",
- &dest));
- EXPECT_EQ("//foo\\", dest);
-
- EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("C:\\base", "C:\\ba", &dest));
- EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("C:\\base",
- "C:\\/notbase/foo",
- &dest));
-#else
-
- EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base", "/base/foo/", &dest));
- EXPECT_EQ("//foo/", dest);
- EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base", "/base/foo", &dest));
- EXPECT_EQ("//foo", dest);
- EXPECT_TRUE(MakeAbsolutePathRelativeIfPossible("/base/", "/base/foo/",
- &dest));
- EXPECT_EQ("//foo/", dest);
-
- EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("/base", "/ba", &dest));
- EXPECT_FALSE(MakeAbsolutePathRelativeIfPossible("/base", "/notbase/foo",
- &dest));
-#endif
-}
-
-TEST(FilesystemUtils, MakeAbsoluteFilePathRelativeIfPossible) {
-#if defined(OS_WIN)
- EXPECT_EQ(
- base::FilePath(L"out\\Debug"),
- MakeAbsoluteFilePathRelativeIfPossible(
- base::FilePath(L"C:\\src"), base::FilePath(L"C:\\src\\out\\Debug")));
- EXPECT_EQ(base::FilePath(L".\\gn"),
- MakeAbsoluteFilePathRelativeIfPossible(
- base::FilePath(L"C:\\src\\out\\Debug"),
- base::FilePath(L"C:\\src\\out\\Debug\\gn")));
- EXPECT_EQ(
- base::FilePath(L"..\\.."),
- MakeAbsoluteFilePathRelativeIfPossible(
- base::FilePath(L"C:\\src\\out\\Debug"), base::FilePath(L"C:\\src")));
- EXPECT_EQ(base::FilePath(L"."),
- MakeAbsoluteFilePathRelativeIfPossible(base::FilePath(L"C:\\src"),
- base::FilePath(L"C:\\src")));
- EXPECT_EQ(base::FilePath(L"..\\..\\..\\u\\v\\w"),
- MakeAbsoluteFilePathRelativeIfPossible(
- base::FilePath(L"C:\\a\\b\\c\\x\\y\\z"),
- base::FilePath(L"C:\\a\\b\\c\\u\\v\\w")));
- EXPECT_EQ(base::FilePath(L"D:\\bar"),
- MakeAbsoluteFilePathRelativeIfPossible(base::FilePath(L"C:\\foo"),
- base::FilePath(L"D:\\bar")));
-#else
- EXPECT_EQ(base::FilePath("out/Debug"),
- MakeAbsoluteFilePathRelativeIfPossible(
- base::FilePath("/src"), base::FilePath("/src/out/Debug")));
- EXPECT_EQ(base::FilePath("./gn"), MakeAbsoluteFilePathRelativeIfPossible(
- base::FilePath("/src/out/Debug"),
- base::FilePath("/src/out/Debug/gn")));
- EXPECT_EQ(base::FilePath("../.."),
- MakeAbsoluteFilePathRelativeIfPossible(
- base::FilePath("/src/out/Debug"), base::FilePath("/src")));
- EXPECT_EQ(base::FilePath("."),
- MakeAbsoluteFilePathRelativeIfPossible(base::FilePath("/src"),
- base::FilePath("/src")));
- EXPECT_EQ(
- base::FilePath("../../../u/v/w"),
- MakeAbsoluteFilePathRelativeIfPossible(base::FilePath("/a/b/c/x/y/z"),
- base::FilePath("/a/b/c/u/v/w")));
-#endif
-}
-
-TEST(FilesystemUtils, NormalizePath) {
- std::string input;
-
- NormalizePath(&input);
- EXPECT_EQ("", input);
-
- input = "foo/bar.txt";
- NormalizePath(&input);
- EXPECT_EQ("foo/bar.txt", input);
-
- input = ".";
- NormalizePath(&input);
- EXPECT_EQ("", input);
-
- input = "..";
- NormalizePath(&input);
- EXPECT_EQ("..", input);
-
- input = "foo//bar";
- NormalizePath(&input);
- EXPECT_EQ("foo/bar", input);
-
- input = "//foo";
- NormalizePath(&input);
- EXPECT_EQ("//foo", input);
-
- input = "foo/..//bar";
- NormalizePath(&input);
- EXPECT_EQ("bar", input);
-
- input = "foo/../../bar";
- NormalizePath(&input);
- EXPECT_EQ("../bar", input);
-
- input = "/../foo"; // Don't go above the root dir.
- NormalizePath(&input);
- EXPECT_EQ("/foo", input);
-
- input = "//../foo"; // Don't go above the root dir.
- NormalizePath(&input);
- EXPECT_EQ("//foo", input);
-
- input = "../foo";
- NormalizePath(&input);
- EXPECT_EQ("../foo", input);
-
- input = "..";
- NormalizePath(&input);
- EXPECT_EQ("..", input);
-
- input = "./././.";
- NormalizePath(&input);
- EXPECT_EQ("", input);
-
- input = "../../..";
- NormalizePath(&input);
- EXPECT_EQ("../../..", input);
-
- input = "../";
- NormalizePath(&input);
- EXPECT_EQ("../", input);
-
- // Backslash normalization.
- input = "foo\\..\\..\\bar";
- NormalizePath(&input);
- EXPECT_EQ("../bar", input);
-
- // Trailing slashes should get preserved.
- input = "//foo/bar/";
- NormalizePath(&input);
- EXPECT_EQ("//foo/bar/", input);
-
-#if defined(OS_WIN)
- // Go above and outside of the source root.
- input = "//../foo";
- NormalizePath(&input, "/C:/source/root");
- EXPECT_EQ("/C:/source/foo", input);
-
- input = "//../foo";
- NormalizePath(&input, "C:\\source\\root");
- EXPECT_EQ("/C:/source/foo", input);
-
- input = "//../";
- NormalizePath(&input, "/C:/source/root");
- EXPECT_EQ("/C:/source/", input);
-
- input = "//../foo.txt";
- NormalizePath(&input, "/C:/source/root");
- EXPECT_EQ("/C:/source/foo.txt", input);
-
- input = "//../foo/bar/";
- NormalizePath(&input, "/C:/source/root");
- EXPECT_EQ("/C:/source/foo/bar/", input);
-
- // Go above and back into the source root. This should return a system-
- // absolute path. We could arguably return this as a source-absolute path,
- // but that would require additional handling to account for a rare edge
- // case.
- input = "//../root/foo";
- NormalizePath(&input, "/C:/source/root");
- EXPECT_EQ("/C:/source/root/foo", input);
-
- input = "//../root/foo/bar/";
- NormalizePath(&input, "/C:/source/root");
- EXPECT_EQ("/C:/source/root/foo/bar/", input);
-
- // Stay inside the source root
- input = "//foo/bar";
- NormalizePath(&input, "/C:/source/root");
- EXPECT_EQ("//foo/bar", input);
-
- input = "//foo/bar/";
- NormalizePath(&input, "/C:/source/root");
- EXPECT_EQ("//foo/bar/", input);
-
- // The path should not go above the system root. Note that on Windows, this
- // will consume the drive (C:).
- input = "//../../../../../foo/bar";
- NormalizePath(&input, "/C:/source/root");
- EXPECT_EQ("/foo/bar", input);
-
- // Test when the source root is the letter drive.
- input = "//../foo";
- NormalizePath(&input, "/C:");
- EXPECT_EQ("/foo", input);
-
- input = "//../foo";
- NormalizePath(&input, "C:");
- EXPECT_EQ("/foo", input);
-
- input = "//../foo";
- NormalizePath(&input, "/");
- EXPECT_EQ("/foo", input);
-
- input = "//../";
- NormalizePath(&input, "\\C:");
- EXPECT_EQ("/", input);
-
- input = "//../foo.txt";
- NormalizePath(&input, "/C:");
- EXPECT_EQ("/foo.txt", input);
-#else
- // Go above and outside of the source root.
- input = "//../foo";
- NormalizePath(&input, "/source/root");
- EXPECT_EQ("/source/foo", input);
-
- input = "//../";
- NormalizePath(&input, "/source/root");
- EXPECT_EQ("/source/", input);
-
- input = "//../foo.txt";
- NormalizePath(&input, "/source/root");
- EXPECT_EQ("/source/foo.txt", input);
-
- input = "//../foo/bar/";
- NormalizePath(&input, "/source/root");
- EXPECT_EQ("/source/foo/bar/", input);
-
- // Go above and back into the source root. This should return a system-
- // absolute path. We could arguably return this as a source-absolute path,
- // but that would require additional handling to account for a rare edge
- // case.
- input = "//../root/foo";
- NormalizePath(&input, "/source/root");
- EXPECT_EQ("/source/root/foo", input);
-
- input = "//../root/foo/bar/";
- NormalizePath(&input, "/source/root");
- EXPECT_EQ("/source/root/foo/bar/", input);
-
- // Stay inside the source root
- input = "//foo/bar";
- NormalizePath(&input, "/source/root");
- EXPECT_EQ("//foo/bar", input);
-
- input = "//foo/bar/";
- NormalizePath(&input, "/source/root");
- EXPECT_EQ("//foo/bar/", input);
-
- // The path should not go above the system root.
- input = "//../../../../../foo/bar";
- NormalizePath(&input, "/source/root");
- EXPECT_EQ("/foo/bar", input);
-
- // Test when the source root is the system root.
- input = "//../foo/bar/";
- NormalizePath(&input, "/");
- EXPECT_EQ("/foo/bar/", input);
-
- input = "//../";
- NormalizePath(&input, "/");
- EXPECT_EQ("/", input);
-
- input = "//../foo.txt";
- NormalizePath(&input, "/");
- EXPECT_EQ("/foo.txt", input);
-
-#endif
-}
-
-TEST(FilesystemUtils, RebasePath) {
- base::StringPiece source_root("/source/root");
-
- // Degenerate case.
- EXPECT_EQ(".", RebasePath("//", SourceDir("//"), source_root));
- EXPECT_EQ(".", RebasePath("//foo/bar/", SourceDir("//foo/bar/"),
- source_root));
-
- // Going up the tree.
- EXPECT_EQ("../foo", RebasePath("//foo", SourceDir("//bar/"), source_root));
- EXPECT_EQ("../foo/", RebasePath("//foo/", SourceDir("//bar/"), source_root));
- EXPECT_EQ("../../foo", RebasePath("//foo", SourceDir("//bar/moo"),
- source_root));
- EXPECT_EQ("../../foo/", RebasePath("//foo/", SourceDir("//bar/moo"),
- source_root));
-
- // Going down the tree.
- EXPECT_EQ("foo/bar", RebasePath("//foo/bar", SourceDir("//"), source_root));
- EXPECT_EQ("foo/bar/", RebasePath("//foo/bar/", SourceDir("//"),
- source_root));
-
- // Going up and down the tree.
- EXPECT_EQ("../../foo/bar", RebasePath("//foo/bar", SourceDir("//a/b/"),
- source_root));
- EXPECT_EQ("../../foo/bar/", RebasePath("//foo/bar/", SourceDir("//a/b/"),
- source_root));
-
- // Sharing prefix.
- EXPECT_EQ("foo", RebasePath("//a/foo", SourceDir("//a/"), source_root));
- EXPECT_EQ("foo/", RebasePath("//a/foo/", SourceDir("//a/"), source_root));
- EXPECT_EQ("foo", RebasePath("//a/b/foo", SourceDir("//a/b/"), source_root));
- EXPECT_EQ("foo/", RebasePath("//a/b/foo/", SourceDir("//a/b/"),
- source_root));
- EXPECT_EQ("foo/bar", RebasePath("//a/b/foo/bar", SourceDir("//a/b/"),
- source_root));
- EXPECT_EQ("foo/bar/", RebasePath("//a/b/foo/bar/", SourceDir("//a/b/"),
- source_root));
-
- // One could argue about this case. Since the input doesn't have a slash it
- // would normally not be treated like a directory and we'd go up, which is
- // simpler. However, since it matches the output directory's name, we could
- // potentially infer that it's the same and return "." for this.
- EXPECT_EQ("../bar", RebasePath("//foo/bar", SourceDir("//foo/bar/"),
- source_root));
-
- // Check when only |input| is system-absolute
- EXPECT_EQ("foo", RebasePath("/source/root/foo", SourceDir("//"),
- base::StringPiece("/source/root")));
- EXPECT_EQ("foo/", RebasePath("/source/root/foo/", SourceDir("//"),
- base::StringPiece("/source/root")));
- EXPECT_EQ("../../builddir/Out/Debug",
- RebasePath("/builddir/Out/Debug", SourceDir("//"),
- base::StringPiece("/source/root")));
- EXPECT_EQ("../../../builddir/Out/Debug",
- RebasePath("/builddir/Out/Debug", SourceDir("//"),
- base::StringPiece("/source/root/foo")));
- EXPECT_EQ("../../../builddir/Out/Debug/",
- RebasePath("/builddir/Out/Debug/", SourceDir("//"),
- base::StringPiece("/source/root/foo")));
- EXPECT_EQ("../../path/to/foo",
- RebasePath("/path/to/foo", SourceDir("//"),
- base::StringPiece("/source/root")));
- EXPECT_EQ("../../../path/to/foo",
- RebasePath("/path/to/foo", SourceDir("//a"),
- base::StringPiece("/source/root")));
- EXPECT_EQ("../../../../path/to/foo",
- RebasePath("/path/to/foo", SourceDir("//a/b"),
- base::StringPiece("/source/root")));
-
- // Check when only |dest_dir| is system-absolute.
- EXPECT_EQ(".",
- RebasePath("//", SourceDir("/source/root"),
- base::StringPiece("/source/root")));
- EXPECT_EQ("foo",
- RebasePath("//foo", SourceDir("/source/root"),
- base::StringPiece("/source/root")));
- EXPECT_EQ("../foo",
- RebasePath("//foo", SourceDir("/source/root/bar"),
- base::StringPiece("/source/root")));
- EXPECT_EQ("../../../source/root/foo",
- RebasePath("//foo", SourceDir("/other/source/root"),
- base::StringPiece("/source/root")));
- EXPECT_EQ("../../../../source/root/foo",
- RebasePath("//foo", SourceDir("/other/source/root/bar"),
- base::StringPiece("/source/root")));
-
- // Check when |input| and |dest_dir| are both system-absolute. Also,
- // in this case |source_root| is never used so set it to a dummy
- // value.
- EXPECT_EQ("foo",
- RebasePath("/source/root/foo", SourceDir("/source/root"),
- base::StringPiece("/x/y/z")));
- EXPECT_EQ("foo/",
- RebasePath("/source/root/foo/", SourceDir("/source/root"),
- base::StringPiece("/x/y/z")));
- EXPECT_EQ("../../builddir/Out/Debug",
- RebasePath("/builddir/Out/Debug",SourceDir("/source/root"),
- base::StringPiece("/x/y/z")));
- EXPECT_EQ("../../../builddir/Out/Debug",
- RebasePath("/builddir/Out/Debug", SourceDir("/source/root/foo"),
- base::StringPiece("/source/root/foo")));
- EXPECT_EQ("../../../builddir/Out/Debug/",
- RebasePath("/builddir/Out/Debug/", SourceDir("/source/root/foo"),
- base::StringPiece("/source/root/foo")));
- EXPECT_EQ("../../path/to/foo",
- RebasePath("/path/to/foo", SourceDir("/source/root"),
- base::StringPiece("/x/y/z")));
- EXPECT_EQ("../../../path/to/foo",
- RebasePath("/path/to/foo", SourceDir("/source/root/a"),
- base::StringPiece("/x/y/z")));
- EXPECT_EQ("../../../../path/to/foo",
- RebasePath("/path/to/foo", SourceDir("/source/root/a/b"),
- base::StringPiece("/x/y/z")));
-
-#if defined(OS_WIN)
- // Test corrections while rebasing Windows-style absolute paths.
- EXPECT_EQ("../../../../path/to/foo",
- RebasePath("C:/path/to/foo", SourceDir("//a/b"),
- base::StringPiece("/C:/source/root")));
- EXPECT_EQ("../../../../path/to/foo",
- RebasePath("/C:/path/to/foo", SourceDir("//a/b"),
- base::StringPiece("C:/source/root")));
- EXPECT_EQ("../../../../path/to/foo",
- RebasePath("/C:/path/to/foo", SourceDir("//a/b"),
- base::StringPiece("/c:/source/root")));
- EXPECT_EQ("../../../../path/to/foo",
- RebasePath("/c:/path/to/foo", SourceDir("//a/b"),
- base::StringPiece("c:/source/root")));
- EXPECT_EQ("../../../../path/to/foo",
- RebasePath("/c:/path/to/foo", SourceDir("//a/b"),
- base::StringPiece("C:/source/root")));
-#endif
-}
-
-TEST(FilesystemUtils, DirectoryWithNoLastSlash) {
- EXPECT_EQ("", DirectoryWithNoLastSlash(SourceDir()));
- EXPECT_EQ("/.", DirectoryWithNoLastSlash(SourceDir("/")));
- EXPECT_EQ("//.", DirectoryWithNoLastSlash(SourceDir("//")));
- EXPECT_EQ("//foo", DirectoryWithNoLastSlash(SourceDir("//foo/")));
- EXPECT_EQ("/bar", DirectoryWithNoLastSlash(SourceDir("/bar/")));
-}
-
-TEST(FilesystemUtils, SourceDirForPath) {
-#if defined(OS_WIN)
- base::FilePath root(L"C:\\source\\foo\\");
- EXPECT_EQ("/C:/foo/bar/", SourceDirForPath(root,
- base::FilePath(L"C:\\foo\\bar")).value());
- EXPECT_EQ("/", SourceDirForPath(root,
- base::FilePath(L"/")).value());
- EXPECT_EQ("//", SourceDirForPath(root,
- base::FilePath(L"C:\\source\\foo")).value());
- EXPECT_EQ("//bar/", SourceDirForPath(root,
- base::FilePath(L"C:\\source\\foo\\bar\\")). value());
- EXPECT_EQ("//bar/baz/", SourceDirForPath(root,
- base::FilePath(L"C:\\source\\foo\\bar\\baz")).value());
-
- // Should be case-and-slash-insensitive.
- EXPECT_EQ("//baR/", SourceDirForPath(root,
- base::FilePath(L"c:/SOURCE\\Foo/baR/")).value());
-
- // Some "weird" Windows paths.
- EXPECT_EQ("/foo/bar/", SourceDirForPath(root,
- base::FilePath(L"/foo/bar/")).value());
- EXPECT_EQ("/C:/foo/bar/", SourceDirForPath(root,
- base::FilePath(L"C:foo/bar/")).value());
-
- // Also allow absolute GN-style Windows paths.
- EXPECT_EQ("/C:/foo/bar/", SourceDirForPath(root,
- base::FilePath(L"/C:/foo/bar")).value());
- EXPECT_EQ("//bar/", SourceDirForPath(root,
- base::FilePath(L"/C:/source/foo/bar")).value());
-
- // Empty source dir.
- base::FilePath empty;
- EXPECT_EQ(
- "/C:/source/foo/",
- SourceDirForPath(empty, base::FilePath(L"C:\\source\\foo")).value());
-#else
- base::FilePath root("/source/foo/");
- EXPECT_EQ("/foo/bar/", SourceDirForPath(root,
- base::FilePath("/foo/bar/")).value());
- EXPECT_EQ("/", SourceDirForPath(root,
- base::FilePath("/")).value());
- EXPECT_EQ("//", SourceDirForPath(root,
- base::FilePath("/source/foo")).value());
- EXPECT_EQ("//bar/", SourceDirForPath(root,
- base::FilePath("/source/foo/bar/")).value());
- EXPECT_EQ("//bar/baz/", SourceDirForPath(root,
- base::FilePath("/source/foo/bar/baz/")).value());
-
- // Should be case-sensitive.
- EXPECT_EQ("/SOURCE/foo/bar/", SourceDirForPath(root,
- base::FilePath("/SOURCE/foo/bar/")).value());
-
- // Empty source dir.
- base::FilePath empty;
- EXPECT_EQ("/source/foo/",
- SourceDirForPath(empty, base::FilePath("/source/foo")).value());
-#endif
-}
-
-TEST(FilesystemUtils, ContentsEqual) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- std::string data = "foo";
-
- base::FilePath file_path = temp_dir.GetPath().AppendASCII("foo.txt");
- base::WriteFile(file_path, data.c_str(), static_cast<int>(data.size()));
-
- EXPECT_TRUE(ContentsEqual(file_path, data));
-
- // Different length and contents.
- data += "bar";
- EXPECT_FALSE(ContentsEqual(file_path, data));
-
- // The same length, different contents.
- EXPECT_FALSE(ContentsEqual(file_path, "bar"));
-}
-
-TEST(FilesystemUtils, WriteFileIfChanged) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- std::string data = "foo";
-
- // Write if file doesn't exist. Create also directory.
- base::FilePath file_path =
- temp_dir.GetPath().AppendASCII("bar").AppendASCII("foo.txt");
- EXPECT_TRUE(WriteFileIfChanged(file_path, data, nullptr));
-
- base::File::Info file_info;
- ASSERT_TRUE(base::GetFileInfo(file_path, &file_info));
- base::Time last_modified = file_info.last_modified;
-
-#if defined(OS_MACOSX)
- // Modification times are in seconds in HFS on Mac.
- base::TimeDelta sleep_time = base::TimeDelta::FromSeconds(1);
-#else
- base::TimeDelta sleep_time = base::TimeDelta::FromMilliseconds(1);
-#endif
- base::PlatformThread::Sleep(sleep_time);
-
- // Don't write if contents is the same.
- EXPECT_TRUE(WriteFileIfChanged(file_path, data, nullptr));
- ASSERT_TRUE(base::GetFileInfo(file_path, &file_info));
- EXPECT_EQ(last_modified, file_info.last_modified);
-
- // Write if contents changed.
- EXPECT_TRUE(WriteFileIfChanged(file_path, "bar", nullptr));
- std::string file_data;
- ASSERT_TRUE(base::ReadFileToString(file_path, &file_data));
- EXPECT_EQ("bar", file_data);
-}
-
-TEST(FilesystemUtils, GetToolchainDirs) {
- BuildSettings build_settings;
- build_settings.SetBuildDir(SourceDir("//out/Debug/"));
-
- // The default toolchain.
- Settings default_settings(&build_settings, "");
- Label default_toolchain_label(SourceDir("//toolchain/"), "default");
- default_settings.set_toolchain_label(default_toolchain_label);
- default_settings.set_default_toolchain_label(default_toolchain_label);
- BuildDirContext default_context(&default_settings);
-
- // Default toolchain out dir as source dirs.
- EXPECT_EQ("//out/Debug/",
- GetBuildDirAsSourceDir(default_context,
- BuildDirType::TOOLCHAIN_ROOT).value());
- EXPECT_EQ("//out/Debug/obj/",
- GetBuildDirAsSourceDir(default_context,
- BuildDirType::OBJ).value());
- EXPECT_EQ("//out/Debug/gen/",
- GetBuildDirAsSourceDir(default_context,
- BuildDirType::GEN).value());
-
- // Default toolchain our dir as output files.
- EXPECT_EQ("",
- GetBuildDirAsOutputFile(default_context,
- BuildDirType::TOOLCHAIN_ROOT).value());
- EXPECT_EQ("obj/",
- GetBuildDirAsOutputFile(default_context,
- BuildDirType::OBJ).value());
- EXPECT_EQ("gen/",
- GetBuildDirAsOutputFile(default_context,
- BuildDirType::GEN).value());
-
- // Check a secondary toolchain.
- Settings other_settings(&build_settings, "two/");
- Label other_toolchain_label(SourceDir("//toolchain/"), "two");
- other_settings.set_toolchain_label(other_toolchain_label);
- other_settings.set_default_toolchain_label(default_toolchain_label);
- BuildDirContext other_context(&other_settings);
-
- // Secondary toolchain out dir as source dirs.
- EXPECT_EQ("//out/Debug/two/",
- GetBuildDirAsSourceDir(other_context,
- BuildDirType::TOOLCHAIN_ROOT).value());
- EXPECT_EQ("//out/Debug/two/obj/",
- GetBuildDirAsSourceDir(other_context,
- BuildDirType::OBJ).value());
- EXPECT_EQ("//out/Debug/two/gen/",
- GetBuildDirAsSourceDir(other_context,
- BuildDirType::GEN).value());
-
- // Secondary toolchain out dir as output files.
- EXPECT_EQ("two/",
- GetBuildDirAsOutputFile(other_context,
- BuildDirType::TOOLCHAIN_ROOT).value());
- EXPECT_EQ("two/obj/",
- GetBuildDirAsOutputFile(other_context,
- BuildDirType::OBJ).value());
- EXPECT_EQ("two/gen/",
- GetBuildDirAsOutputFile(other_context,
- BuildDirType::GEN).value());
-}
-
-TEST(FilesystemUtils, GetSubBuildDir) {
- BuildSettings build_settings;
- build_settings.SetBuildDir(SourceDir("//out/Debug/"));
-
- // Test the default toolchain.
- Label default_toolchain_label(SourceDir("//toolchain/"), "default");
- Settings default_settings(&build_settings, "");
- default_settings.set_toolchain_label(default_toolchain_label);
- default_settings.set_default_toolchain_label(default_toolchain_label);
- BuildDirContext default_context(&default_settings);
-
- // Target in the root.
- EXPECT_EQ("//out/Debug/obj/",
- GetSubBuildDirAsSourceDir(
- default_context, SourceDir("//"), BuildDirType::OBJ).value());
- EXPECT_EQ("gen/",
- GetSubBuildDirAsOutputFile(
- default_context, SourceDir("//"), BuildDirType::GEN).value());
-
- // Target in another directory.
- EXPECT_EQ("//out/Debug/obj/foo/bar/",
- GetSubBuildDirAsSourceDir(
- default_context, SourceDir("//foo/bar/"), BuildDirType::OBJ)
- .value());
- EXPECT_EQ("gen/foo/bar/",
- GetSubBuildDirAsOutputFile(
- default_context, SourceDir("//foo/bar/"), BuildDirType::GEN)
- .value());
-
- // Secondary toolchain.
- Settings other_settings(&build_settings, "two/");
- other_settings.set_toolchain_label(Label(SourceDir("//toolchain/"), "two"));
- other_settings.set_default_toolchain_label(default_toolchain_label);
- BuildDirContext other_context(&other_settings);
-
- // Target in the root.
- EXPECT_EQ("//out/Debug/two/obj/",
- GetSubBuildDirAsSourceDir(
- other_context, SourceDir("//"), BuildDirType::OBJ).value());
- EXPECT_EQ("two/gen/",
- GetSubBuildDirAsOutputFile(
- other_context, SourceDir("//"), BuildDirType::GEN).value());
-
- // Target in another directory.
- EXPECT_EQ("//out/Debug/two/obj/foo/bar/",
- GetSubBuildDirAsSourceDir(
- other_context, SourceDir("//foo/bar/"), BuildDirType::OBJ)
- .value());
- EXPECT_EQ("two/gen/foo/bar/",
- GetSubBuildDirAsOutputFile(
- other_context, SourceDir("//foo/bar/"), BuildDirType::GEN)
- .value());
-
- // Absolute source path
- EXPECT_EQ("//out/Debug/obj/ABS_PATH/abs/",
- GetSubBuildDirAsSourceDir(
- default_context, SourceDir("/abs"), BuildDirType::OBJ).value());
- EXPECT_EQ("gen/ABS_PATH/abs/",
- GetSubBuildDirAsOutputFile(
- default_context, SourceDir("/abs"), BuildDirType::GEN).value());
-#if defined(OS_WIN)
- EXPECT_EQ("//out/Debug/obj/ABS_PATH/C/abs/",
- GetSubBuildDirAsSourceDir(
- default_context, SourceDir("/C:/abs"), BuildDirType::OBJ)
- .value());
- EXPECT_EQ("gen/ABS_PATH/C/abs/",
- GetSubBuildDirAsOutputFile(
- default_context, SourceDir("/C:/abs"), BuildDirType::GEN)
- .value());
-#endif
-}
-
-TEST(FilesystemUtils, GetBuildDirForTarget) {
- BuildSettings build_settings;
- build_settings.SetBuildDir(SourceDir("//out/Debug/"));
- Settings settings(&build_settings, "");
-
- Target a(&settings, Label(SourceDir("//foo/bar/"), "baz"));
- EXPECT_EQ("//out/Debug/obj/foo/bar/",
- GetBuildDirForTargetAsSourceDir(&a, BuildDirType::OBJ).value());
- EXPECT_EQ("obj/foo/bar/",
- GetBuildDirForTargetAsOutputFile(&a, BuildDirType::OBJ).value());
- EXPECT_EQ("//out/Debug/gen/foo/bar/",
- GetBuildDirForTargetAsSourceDir(&a, BuildDirType::GEN).value());
- EXPECT_EQ("gen/foo/bar/",
- GetBuildDirForTargetAsOutputFile(&a, BuildDirType::GEN).value());
-}
-
-// Tests handling of output dirs when build dir is the same as the root.
-TEST(FilesystemUtils, GetDirForEmptyBuildDir) {
- BuildSettings build_settings;
- build_settings.SetBuildDir(SourceDir("//"));
- Settings settings(&build_settings, "");
-
- BuildDirContext context(&settings);
-
- EXPECT_EQ("//",
- GetBuildDirAsSourceDir(context, BuildDirType::TOOLCHAIN_ROOT)
- .value());
- EXPECT_EQ("//gen/",
- GetBuildDirAsSourceDir(context, BuildDirType::GEN).value());
- EXPECT_EQ("//obj/",
- GetBuildDirAsSourceDir(context, BuildDirType::OBJ).value());
-
- EXPECT_EQ("",
- GetBuildDirAsOutputFile(context, BuildDirType::TOOLCHAIN_ROOT)
- .value());
- EXPECT_EQ("gen/",
- GetBuildDirAsOutputFile(context, BuildDirType::GEN).value());
- EXPECT_EQ("obj/",
- GetBuildDirAsOutputFile(context, BuildDirType::OBJ).value());
-}
diff --git a/chromium/tools/gn/format_test_data/001.gn b/chromium/tools/gn/format_test_data/001.gn
deleted file mode 100644
index c35c27951fd..00000000000
--- a/chromium/tools/gn/format_test_data/001.gn
+++ /dev/null
@@ -1,2 +0,0 @@
-# Test.
-executable("test"){}
diff --git a/chromium/tools/gn/format_test_data/001.golden b/chromium/tools/gn/format_test_data/001.golden
deleted file mode 100644
index 31c9069d2b2..00000000000
--- a/chromium/tools/gn/format_test_data/001.golden
+++ /dev/null
@@ -1,3 +0,0 @@
-# Test.
-executable("test") {
-}
diff --git a/chromium/tools/gn/format_test_data/002.gn b/chromium/tools/gn/format_test_data/002.gn
deleted file mode 100644
index 34043b5ed30..00000000000
--- a/chromium/tools/gn/format_test_data/002.gn
+++ /dev/null
@@ -1,6 +0,0 @@
-executable("test") {
- sources = [
- "stuff.cc",
- "things.cc"
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/002.golden b/chromium/tools/gn/format_test_data/002.golden
deleted file mode 100644
index cd8f38810c4..00000000000
--- a/chromium/tools/gn/format_test_data/002.golden
+++ /dev/null
@@ -1,6 +0,0 @@
-executable("test") {
- sources = [
- "stuff.cc",
- "things.cc",
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/003.gn b/chromium/tools/gn/format_test_data/003.gn
deleted file mode 100644
index 429165a285c..00000000000
--- a/chromium/tools/gn/format_test_data/003.gn
+++ /dev/null
@@ -1,10 +0,0 @@
-executable("test") {
- sources = [
- "stuff.cc",
- "things.cc"
- ]
-
- deps = [
- "//base",
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/003.golden b/chromium/tools/gn/format_test_data/003.golden
deleted file mode 100644
index 2fdcb9e38ba..00000000000
--- a/chromium/tools/gn/format_test_data/003.golden
+++ /dev/null
@@ -1,10 +0,0 @@
-executable("test") {
- sources = [
- "stuff.cc",
- "things.cc",
- ]
-
- deps = [
- "//base",
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/004.gn b/chromium/tools/gn/format_test_data/004.gn
deleted file mode 100644
index f36d039cf4c..00000000000
--- a/chromium/tools/gn/format_test_data/004.gn
+++ /dev/null
@@ -1,10 +0,0 @@
-# This is a block comment that goes at the top of the file and is attached to
-# the top level target.
-executable("test") {
- sources = [
- "stuff.cc",# Comment attached to list item.
- "things.cc"
- ]
- # Comment attached to statement.
- deps = [ "//base", ]
-}
diff --git a/chromium/tools/gn/format_test_data/004.golden b/chromium/tools/gn/format_test_data/004.golden
deleted file mode 100644
index 68373d10144..00000000000
--- a/chromium/tools/gn/format_test_data/004.golden
+++ /dev/null
@@ -1,13 +0,0 @@
-# This is a block comment that goes at the top of the file and is attached to
-# the top level target.
-executable("test") {
- sources = [
- "stuff.cc", # Comment attached to list item.
- "things.cc",
- ]
-
- # Comment attached to statement.
- deps = [
- "//base",
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/005.gn b/chromium/tools/gn/format_test_data/005.gn
deleted file mode 100644
index 07b4ef372c0..00000000000
--- a/chromium/tools/gn/format_test_data/005.gn
+++ /dev/null
@@ -1,5 +0,0 @@
-# This is a separated block comment that mustn't be attached the to target
-# below, and should be separated by a single blank line.
-
-executable("test") {
-}
diff --git a/chromium/tools/gn/format_test_data/005.golden b/chromium/tools/gn/format_test_data/005.golden
deleted file mode 100644
index 07b4ef372c0..00000000000
--- a/chromium/tools/gn/format_test_data/005.golden
+++ /dev/null
@@ -1,5 +0,0 @@
-# This is a separated block comment that mustn't be attached the to target
-# below, and should be separated by a single blank line.
-
-executable("test") {
-}
diff --git a/chromium/tools/gn/format_test_data/006.gn b/chromium/tools/gn/format_test_data/006.gn
deleted file mode 100644
index 737fceaae0e..00000000000
--- a/chromium/tools/gn/format_test_data/006.gn
+++ /dev/null
@@ -1,9 +0,0 @@
-# This is a separated block comment that mustn't be attached the to target
-# below, and should be separated by a single blank line.
-
-
-
-
-
-executable("test") {
-}
diff --git a/chromium/tools/gn/format_test_data/006.golden b/chromium/tools/gn/format_test_data/006.golden
deleted file mode 100644
index 07b4ef372c0..00000000000
--- a/chromium/tools/gn/format_test_data/006.golden
+++ /dev/null
@@ -1,5 +0,0 @@
-# This is a separated block comment that mustn't be attached the to target
-# below, and should be separated by a single blank line.
-
-executable("test") {
-}
diff --git a/chromium/tools/gn/format_test_data/007.gn b/chromium/tools/gn/format_test_data/007.gn
deleted file mode 100644
index 3cd002d8606..00000000000
--- a/chromium/tools/gn/format_test_data/007.gn
+++ /dev/null
@@ -1,9 +0,0 @@
-executable("test") {
- sources = ["a.cc"]
-
- # This is an unusual comment that's a header for the stuff that comes after
- # it. We want to make sure that it's not connected to the next element in
- # the file.
-
- cflags = ["-Wee"]
-}
diff --git a/chromium/tools/gn/format_test_data/007.golden b/chromium/tools/gn/format_test_data/007.golden
deleted file mode 100644
index 610fa3fead5..00000000000
--- a/chromium/tools/gn/format_test_data/007.golden
+++ /dev/null
@@ -1,11 +0,0 @@
-executable("test") {
- sources = [
- "a.cc",
- ]
-
- # This is an unusual comment that's a header for the stuff that comes after
- # it. We want to make sure that it's not connected to the next element in
- # the file.
-
- cflags = [ "-Wee" ]
-}
diff --git a/chromium/tools/gn/format_test_data/008.gn b/chromium/tools/gn/format_test_data/008.gn
deleted file mode 100644
index 16b4a8e32fb..00000000000
--- a/chromium/tools/gn/format_test_data/008.gn
+++ /dev/null
@@ -1 +0,0 @@
-if (is_win) { sources = ["win.cc"] }
diff --git a/chromium/tools/gn/format_test_data/008.golden b/chromium/tools/gn/format_test_data/008.golden
deleted file mode 100644
index aec281ab952..00000000000
--- a/chromium/tools/gn/format_test_data/008.golden
+++ /dev/null
@@ -1,5 +0,0 @@
-if (is_win) {
- sources = [
- "win.cc",
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/009.gn b/chromium/tools/gn/format_test_data/009.gn
deleted file mode 100644
index e47b62175ae..00000000000
--- a/chromium/tools/gn/format_test_data/009.gn
+++ /dev/null
@@ -1,2 +0,0 @@
-if (is_win) { sources = ["win.cc"] }
-else { sources = ["linux.cc"] }
diff --git a/chromium/tools/gn/format_test_data/009.golden b/chromium/tools/gn/format_test_data/009.golden
deleted file mode 100644
index af27d797005..00000000000
--- a/chromium/tools/gn/format_test_data/009.golden
+++ /dev/null
@@ -1,9 +0,0 @@
-if (is_win) {
- sources = [
- "win.cc",
- ]
-} else {
- sources = [
- "linux.cc",
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/010.gn b/chromium/tools/gn/format_test_data/010.gn
deleted file mode 100644
index 70004a75158..00000000000
--- a/chromium/tools/gn/format_test_data/010.gn
+++ /dev/null
@@ -1,2 +0,0 @@
-if (is_win) { sources = ["win.cc"] }
-else if (is_linux) { sources = ["linux.cc"] }
diff --git a/chromium/tools/gn/format_test_data/010.golden b/chromium/tools/gn/format_test_data/010.golden
deleted file mode 100644
index 64fabb9ebc5..00000000000
--- a/chromium/tools/gn/format_test_data/010.golden
+++ /dev/null
@@ -1,9 +0,0 @@
-if (is_win) {
- sources = [
- "win.cc",
- ]
-} else if (is_linux) {
- sources = [
- "linux.cc",
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/011.gn b/chromium/tools/gn/format_test_data/011.gn
deleted file mode 100644
index c2c5bf755ea..00000000000
--- a/chromium/tools/gn/format_test_data/011.gn
+++ /dev/null
@@ -1,4 +0,0 @@
-if (is_win) { sources = ["win.cc"] }
-else if (is_linux) { sources = ["linux.cc"] }
-else { sources = ["wha.cc"] }
-
diff --git a/chromium/tools/gn/format_test_data/011.golden b/chromium/tools/gn/format_test_data/011.golden
deleted file mode 100644
index 4ce009ea1dc..00000000000
--- a/chromium/tools/gn/format_test_data/011.golden
+++ /dev/null
@@ -1,13 +0,0 @@
-if (is_win) {
- sources = [
- "win.cc",
- ]
-} else if (is_linux) {
- sources = [
- "linux.cc",
- ]
-} else {
- sources = [
- "wha.cc",
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/012.gn b/chromium/tools/gn/format_test_data/012.gn
deleted file mode 100644
index 1da385c00e8..00000000000
--- a/chromium/tools/gn/format_test_data/012.gn
+++ /dev/null
@@ -1,16 +0,0 @@
-# (A sample top level block comment)
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-if (is_win) {
- # This is some special stuff for Windows
- sources = ["win.cc"] } else if (is_linux) {
-
- # This is a block comment inside the linux block, but not attached.
-
- sources = ["linux.cc"]
-} else {
- # A comment with trailing spaces
-sources = ["wha.cc"] }
-
diff --git a/chromium/tools/gn/format_test_data/012.golden b/chromium/tools/gn/format_test_data/012.golden
deleted file mode 100644
index a0049b2d55d..00000000000
--- a/chromium/tools/gn/format_test_data/012.golden
+++ /dev/null
@@ -1,22 +0,0 @@
-# (A sample top level block comment)
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-if (is_win) {
- # This is some special stuff for Windows
- sources = [
- "win.cc",
- ]
-} else if (is_linux) {
- # This is a block comment inside the linux block, but not attached.
-
- sources = [
- "linux.cc",
- ]
-} else {
- # A comment with trailing spaces
- sources = [
- "wha.cc",
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/013.gn b/chromium/tools/gn/format_test_data/013.gn
deleted file mode 100644
index 06183a82d48..00000000000
--- a/chromium/tools/gn/format_test_data/013.gn
+++ /dev/null
@@ -1,7 +0,0 @@
-defines = [
- # Separate comment inside expression.
-
- # Connected comment.
- "WEE",
- "BLORPY",
-]
diff --git a/chromium/tools/gn/format_test_data/013.golden b/chromium/tools/gn/format_test_data/013.golden
deleted file mode 100644
index d84b7d20f8e..00000000000
--- a/chromium/tools/gn/format_test_data/013.golden
+++ /dev/null
@@ -1,7 +0,0 @@
-defines = [
- # Separate comment inside expression.
-
- # Connected comment.
- "WEE",
- "BLORPY",
-]
diff --git a/chromium/tools/gn/format_test_data/014.gn b/chromium/tools/gn/format_test_data/014.gn
deleted file mode 100644
index 2d0170d862a..00000000000
--- a/chromium/tools/gn/format_test_data/014.gn
+++ /dev/null
@@ -1,6 +0,0 @@
-defines = [
-
- # Connected comment.
- "WEE",
- "BLORPY",
-]
diff --git a/chromium/tools/gn/format_test_data/014.golden b/chromium/tools/gn/format_test_data/014.golden
deleted file mode 100644
index c0ba5bb3981..00000000000
--- a/chromium/tools/gn/format_test_data/014.golden
+++ /dev/null
@@ -1,5 +0,0 @@
-defines = [
- # Connected comment.
- "WEE",
- "BLORPY",
-]
diff --git a/chromium/tools/gn/format_test_data/015.gn b/chromium/tools/gn/format_test_data/015.gn
deleted file mode 100644
index f065095f656..00000000000
--- a/chromium/tools/gn/format_test_data/015.gn
+++ /dev/null
@@ -1,4 +0,0 @@
-if (is_win) {
- sources = ["a.cc"]
- # Some comment at end.
-}
diff --git a/chromium/tools/gn/format_test_data/015.golden b/chromium/tools/gn/format_test_data/015.golden
deleted file mode 100644
index 553f01ce105..00000000000
--- a/chromium/tools/gn/format_test_data/015.golden
+++ /dev/null
@@ -1,6 +0,0 @@
-if (is_win) {
- sources = [
- "a.cc",
- ]
- # Some comment at end.
-}
diff --git a/chromium/tools/gn/format_test_data/016.gn b/chromium/tools/gn/format_test_data/016.gn
deleted file mode 100644
index 00a79922828..00000000000
--- a/chromium/tools/gn/format_test_data/016.gn
+++ /dev/null
@@ -1 +0,0 @@
-something = !is_win && is_linux || is_mac && !(is_freebsd || is_ios)
diff --git a/chromium/tools/gn/format_test_data/016.golden b/chromium/tools/gn/format_test_data/016.golden
deleted file mode 100644
index 3f4f15bc507..00000000000
--- a/chromium/tools/gn/format_test_data/016.golden
+++ /dev/null
@@ -1 +0,0 @@
-something = (!is_win && is_linux) || (is_mac && !(is_freebsd || is_ios))
diff --git a/chromium/tools/gn/format_test_data/017.gn b/chromium/tools/gn/format_test_data/017.gn
deleted file mode 100644
index 225ae2fe30c..00000000000
--- a/chromium/tools/gn/format_test_data/017.gn
+++ /dev/null
@@ -1,15 +0,0 @@
-executable("win" # Suffix comment on arg.
- # And a strangely positioned line comment for some reason
- ) {
- defines = [ # Defines comment, suffix at end position.
- ]
-
- deps = [
- # Deps comment, should be forced multiline.
- ]
- sources = [
- "a.cc"
- # End of single sources comment, should be forced multiline.
- ]
- # End of block comment.
-}
diff --git a/chromium/tools/gn/format_test_data/017.golden b/chromium/tools/gn/format_test_data/017.golden
deleted file mode 100644
index d9d7ad9a472..00000000000
--- a/chromium/tools/gn/format_test_data/017.golden
+++ /dev/null
@@ -1,16 +0,0 @@
-executable("win" # Suffix comment on arg.
-
- # And a strangely positioned line comment for some reason
- ) {
- defines = [] # Defines comment, suffix at end position.
-
- deps = [
- # Deps comment, should be forced multiline.
- ]
- sources = [
- "a.cc",
- # End of single sources comment, should be forced multiline.
- ]
-
- # End of block comment.
-}
diff --git a/chromium/tools/gn/format_test_data/018.gn b/chromium/tools/gn/format_test_data/018.gn
deleted file mode 100644
index e63ef9def15..00000000000
--- a/chromium/tools/gn/format_test_data/018.gn
+++ /dev/null
@@ -1,3 +0,0 @@
-# Don't crash when no block on a function call.
-
-import("wee.gni")
diff --git a/chromium/tools/gn/format_test_data/018.golden b/chromium/tools/gn/format_test_data/018.golden
deleted file mode 100644
index e63ef9def15..00000000000
--- a/chromium/tools/gn/format_test_data/018.golden
+++ /dev/null
@@ -1,3 +0,0 @@
-# Don't crash when no block on a function call.
-
-import("wee.gni")
diff --git a/chromium/tools/gn/format_test_data/019.gn b/chromium/tools/gn/format_test_data/019.gn
deleted file mode 100644
index 48772b9ded8..00000000000
--- a/chromium/tools/gn/format_test_data/019.gn
+++ /dev/null
@@ -1,23 +0,0 @@
-# Make sure blank lines are maintained before comments in lists.
-
-deps = [
- "//pdf", # Not compiled on Android in GYP yet, either.
- "//ppapi:ppapi_c",
- "//third_party/libusb",
- "//ui/keyboard", # Blocked on content.
-
- # Seems to not be compiled on Android. Otherwise it will need a config.h.
- "//third_party/libxslt",
-
- # Not relevant to Android.
- "//ash",
- "//tools/gn",
-
- # Multiple line
- # comment
- # here.
- "//ui/aura",
- "//ui/display",
- "//ui/views",
- "//ui/views/controls/webview",
-]
diff --git a/chromium/tools/gn/format_test_data/019.golden b/chromium/tools/gn/format_test_data/019.golden
deleted file mode 100644
index c800ed1fe42..00000000000
--- a/chromium/tools/gn/format_test_data/019.golden
+++ /dev/null
@@ -1,23 +0,0 @@
-# Make sure blank lines are maintained before comments in lists.
-
-deps = [
- "//pdf", # Not compiled on Android in GYP yet, either.
- "//ppapi:ppapi_c",
- "//third_party/libusb",
- "//ui/keyboard", # Blocked on content.
-
- # Seems to not be compiled on Android. Otherwise it will need a config.h.
- "//third_party/libxslt",
-
- # Not relevant to Android.
- "//ash",
- "//tools/gn",
-
- # Multiple line
- # comment
- # here.
- "//ui/aura",
- "//ui/display",
- "//ui/views",
- "//ui/views/controls/webview",
-]
diff --git a/chromium/tools/gn/format_test_data/020.gn b/chromium/tools/gn/format_test_data/020.gn
deleted file mode 100644
index 96de16448bc..00000000000
--- a/chromium/tools/gn/format_test_data/020.gn
+++ /dev/null
@@ -1,5 +0,0 @@
-cflags = [
- "/wd4267", # size_t -> int.
- "/wd4324", # Structure was padded due to __declspec(align()), which is
- # uninteresting.
-]
diff --git a/chromium/tools/gn/format_test_data/020.golden b/chromium/tools/gn/format_test_data/020.golden
deleted file mode 100644
index 96de16448bc..00000000000
--- a/chromium/tools/gn/format_test_data/020.golden
+++ /dev/null
@@ -1,5 +0,0 @@
-cflags = [
- "/wd4267", # size_t -> int.
- "/wd4324", # Structure was padded due to __declspec(align()), which is
- # uninteresting.
-]
diff --git a/chromium/tools/gn/format_test_data/021.gn b/chromium/tools/gn/format_test_data/021.gn
deleted file mode 100644
index 355735db135..00000000000
--- a/chromium/tools/gn/format_test_data/021.gn
+++ /dev/null
@@ -1,33 +0,0 @@
-f(aaaaaaaaaaaaaaaaaaa)
-
-f(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaa)
-
-# Exactly 80 wide.
-f(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaa, aaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaa, aaaaa)
-
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)
-
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)
-
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa, aaaaaaaaa)
-
-aaaaaaaaaa(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaa + aaaaaaaaaa.aaaaaaaaaaaaaaa)
-
-# 80 ---------------------------------------------------------------------------
-f(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaa)
-
-aaaaaaa(aaaaaaaaaaaaa, aaaaaaaaaaaaa, aaaaaaaaaaaaa(aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaa))
-
-# 80 ---------------------------------------------------------------------------
-f(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)
-
-aaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaa, aaaaaaaaaaaa)
-
-# 80 ---------------------------------------------------------------------------
-aaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaa, aaaaaaaaaaaa)
-
-aaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaa)
-
-aaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaa)
-
-somefunction(someotherFunction(ddddddddddddddddddddddddddddddddddd, ddddddddddddddddddddddddddddd), test)
diff --git a/chromium/tools/gn/format_test_data/021.golden b/chromium/tools/gn/format_test_data/021.golden
deleted file mode 100644
index f17c5fd83c6..00000000000
--- a/chromium/tools/gn/format_test_data/021.golden
+++ /dev/null
@@ -1,61 +0,0 @@
-f(aaaaaaaaaaaaaaaaaaa)
-
-f(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaa)
-
-# Exactly 80 wide.
-f(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaa, aaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaa, aaaaa)
-
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)
-
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)
-
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa,
- aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa,
- aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa,
- aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa,
- aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa,
- aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa,
- aaaaaaaaa)
-
-aaaaaaaaaa(
- aaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaa + aaaaaaaaaa.aaaaaaaaaaaaaaa)
-
-# 80 ---------------------------------------------------------------------------
-f(aaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaa)
-
-aaaaaaa(aaaaaaaaaaaaa,
- aaaaaaaaaaaaa,
- aaaaaaaaaaaaa(aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaa))
-
-# 80 ---------------------------------------------------------------------------
-f(aaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaaaaaaaaaaaa +
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)
-
-aaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaa,
- aaaaaaaaaaaa)
-
-# 80 ---------------------------------------------------------------------------
-aaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaa,
- aaaaaaaaaaaa)
-
-aaaaaaaaaaaa(
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaa)
-
-aaaaaaaaaaaa(
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaa)
-
-somefunction(someotherFunction(ddddddddddddddddddddddddddddddddddd,
- ddddddddddddddddddddddddddddd),
- test)
diff --git a/chromium/tools/gn/format_test_data/022.gn b/chromium/tools/gn/format_test_data/022.gn
deleted file mode 100644
index a67ed24d6bb..00000000000
--- a/chromium/tools/gn/format_test_data/022.gn
+++ /dev/null
@@ -1,6 +0,0 @@
-executable(something[0]) {
- if (weeeeee.stuff) {
- x = a.b
- y = a[8]
- }
-}
diff --git a/chromium/tools/gn/format_test_data/022.golden b/chromium/tools/gn/format_test_data/022.golden
deleted file mode 100644
index a67ed24d6bb..00000000000
--- a/chromium/tools/gn/format_test_data/022.golden
+++ /dev/null
@@ -1,6 +0,0 @@
-executable(something[0]) {
- if (weeeeee.stuff) {
- x = a.b
- y = a[8]
- }
-}
diff --git a/chromium/tools/gn/format_test_data/023.gn b/chromium/tools/gn/format_test_data/023.gn
deleted file mode 100644
index 8a1b51926b7..00000000000
--- a/chromium/tools/gn/format_test_data/023.gn
+++ /dev/null
@@ -1,38 +0,0 @@
-f(aaaaaaaaaaaaaaaaaaa) {}
-
-f(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaa) {}
-
-# 80 ---------------------------------------------------------------------------
-f(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaa, aaaaaaaaaaaaaaaa, aaaaaaaaaaaaa, aaaaaa) {}
-
-# 80 ---------------------------------------------------------------------------
-f(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaa, aaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaa, aaaaa) {}
-
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}
-
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}
-
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}
-
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa, aaaaaaaaa) {}
-
-aaaaaaaaaa(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaa + aaaaaaaaaa.aaaaaaaaaaaaaaa) {}
-
-# 80 ---------------------------------------------------------------------------
-f(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaa) {}
-
-aaaaaaa(aaaaaaaaaaaaa, aaaaaaaaaaaaa, aaaaaaaaaaaaa(aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaa)) {}
-
-# 80 ---------------------------------------------------------------------------
-f(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}
-
-aaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaa, aaaaaaaaaaaa) {}
-
-# 80 ---------------------------------------------------------------------------
-aaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaa, aaaaaaaaaaaa) {}
-
-aaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaa) {}
-
-aaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaa) {}
-
-somefunction(someotherFunction(ddddddddddddddddddddddddddddddddddd, ddddddddddddddddddddddddddddd), test) {}
diff --git a/chromium/tools/gn/format_test_data/023.golden b/chromium/tools/gn/format_test_data/023.golden
deleted file mode 100644
index bab6e45eda3..00000000000
--- a/chromium/tools/gn/format_test_data/023.golden
+++ /dev/null
@@ -1,88 +0,0 @@
-f(aaaaaaaaaaaaaaaaaaa) {
-}
-
-f(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaa) {
-}
-
-# 80 ---------------------------------------------------------------------------
-f(aaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaa, aaaaaaaaaaaaaaaa, aaaaaaaaaaaaa, aaaaaa) {
-}
-
-# 80 ---------------------------------------------------------------------------
-f(aaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaaa,
- aaaaaaaaaaaaaaaa,
- aaaaaaaaaaaaaaaa,
- aaaaa) {
-}
-
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {
-}
-
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {
-}
-
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {
-}
-
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa,
- aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa,
- aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa,
- aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa,
- aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa,
- aaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaa,
- aaaaaaaaa) {
-}
-
-aaaaaaaaaa(
- aaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaa + aaaaaaaaaa.aaaaaaaaaaaaaaa) {
-}
-
-# 80 ---------------------------------------------------------------------------
-f(aaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaa) {
-}
-
-aaaaaaa(aaaaaaaaaaaaa,
- aaaaaaaaaaaaa,
- aaaaaaaaaaaaa(aaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaa)) {
-}
-
-# 80 ---------------------------------------------------------------------------
-f(aaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaaaaaaaaaaaa +
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {
-}
-
-aaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaa,
- aaaaaaaaaaaa) {
-}
-
-# 80 ---------------------------------------------------------------------------
-aaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaa,
- aaaaaaaaaaaa) {
-}
-
-aaaaaaaaaaaa(
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaa) {
-}
-
-aaaaaaaaaaaa(
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
- aaaaaaaaaaaa) {
-}
-
-somefunction(someotherFunction(ddddddddddddddddddddddddddddddddddd,
- ddddddddddddddddddddddddddddd),
- test) {
-}
diff --git a/chromium/tools/gn/format_test_data/024.gn b/chromium/tools/gn/format_test_data/024.gn
deleted file mode 100644
index 5034cdc84e7..00000000000
--- a/chromium/tools/gn/format_test_data/024.gn
+++ /dev/null
@@ -1 +0,0 @@
-somefunc(){}
diff --git a/chromium/tools/gn/format_test_data/024.golden b/chromium/tools/gn/format_test_data/024.golden
deleted file mode 100644
index f2c755dcb8b..00000000000
--- a/chromium/tools/gn/format_test_data/024.golden
+++ /dev/null
@@ -1,2 +0,0 @@
-somefunc() {
-}
diff --git a/chromium/tools/gn/format_test_data/025.gn b/chromium/tools/gn/format_test_data/025.gn
deleted file mode 100644
index 959ec8a3c52..00000000000
--- a/chromium/tools/gn/format_test_data/025.gn
+++ /dev/null
@@ -1,5 +0,0 @@
-# Various parenthesis maintenance/trimming.
-if ((a.b && c[d] + ((x < 4 || ((z + b)))))) {
- y = z - (y - (x - !(b-d)))
- a += ["a", "b", "c"] - (["x"] - ["y"])
-}
diff --git a/chromium/tools/gn/format_test_data/025.golden b/chromium/tools/gn/format_test_data/025.golden
deleted file mode 100644
index e6d08692a4f..00000000000
--- a/chromium/tools/gn/format_test_data/025.golden
+++ /dev/null
@@ -1,9 +0,0 @@
-# Various parenthesis maintenance/trimming.
-if (a.b && c[d] + (x < 4 || z + b)) {
- y = z - (y - (x - !(b - d)))
- a += [
- "a",
- "b",
- "c",
- ] - ([ "x" ] - [ "y" ])
-}
diff --git a/chromium/tools/gn/format_test_data/026.gn b/chromium/tools/gn/format_test_data/026.gn
deleted file mode 100644
index 8cf2028a72a..00000000000
--- a/chromium/tools/gn/format_test_data/026.gn
+++ /dev/null
@@ -1,6 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-args = [
- rebase_path("$target_gen_dir/experimental-libraries.cc", root_build_dir),
- "EXPERIMENTAL",
- v8_compress_startup_data
-] + rebase_path(sources, root_build_dir)
diff --git a/chromium/tools/gn/format_test_data/026.golden b/chromium/tools/gn/format_test_data/026.golden
deleted file mode 100644
index a1d1d3f936d..00000000000
--- a/chromium/tools/gn/format_test_data/026.golden
+++ /dev/null
@@ -1,7 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-args =
- [
- rebase_path("$target_gen_dir/experimental-libraries.cc", root_build_dir),
- "EXPERIMENTAL",
- v8_compress_startup_data,
- ] + rebase_path(sources, root_build_dir)
diff --git a/chromium/tools/gn/format_test_data/027.gn b/chromium/tools/gn/format_test_data/027.gn
deleted file mode 100644
index cc5fe5fa942..00000000000
--- a/chromium/tools/gn/format_test_data/027.gn
+++ /dev/null
@@ -1,3 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = [
-"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaa"]
diff --git a/chromium/tools/gn/format_test_data/027.golden b/chromium/tools/gn/format_test_data/027.golden
deleted file mode 100644
index 05f0eb57931..00000000000
--- a/chromium/tools/gn/format_test_data/027.golden
+++ /dev/null
@@ -1,5 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = [
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
- "aaaaaaaaaaaaaaaaaaaaaaaaa",
-]
diff --git a/chromium/tools/gn/format_test_data/028.gn b/chromium/tools/gn/format_test_data/028.gn
deleted file mode 100644
index d84e1f8c957..00000000000
--- a/chromium/tools/gn/format_test_data/028.gn
+++ /dev/null
@@ -1,9 +0,0 @@
-# Don't separate these.
-import("wee.gni")
-import("waa.gni")
-
-import("woo.gni")
-
-
-
-import("blah.gni")
diff --git a/chromium/tools/gn/format_test_data/028.golden b/chromium/tools/gn/format_test_data/028.golden
deleted file mode 100644
index a1d54c550a2..00000000000
--- a/chromium/tools/gn/format_test_data/028.golden
+++ /dev/null
@@ -1,7 +0,0 @@
-# Don't separate these.
-import("wee.gni")
-import("waa.gni")
-
-import("woo.gni")
-
-import("blah.gni")
diff --git a/chromium/tools/gn/format_test_data/029.gn b/chromium/tools/gn/format_test_data/029.gn
deleted file mode 100644
index ac67830164e..00000000000
--- a/chromium/tools/gn/format_test_data/029.gn
+++ /dev/null
@@ -1,9 +0,0 @@
-# Don't separate small simple statements.
-is_android = false
-is_chromeos = false
-is_ios = false
-is_linux -= false
-is_mac = true
-is_nacl = false
-is_posix += true
-is_win = false
diff --git a/chromium/tools/gn/format_test_data/029.golden b/chromium/tools/gn/format_test_data/029.golden
deleted file mode 100644
index ac67830164e..00000000000
--- a/chromium/tools/gn/format_test_data/029.golden
+++ /dev/null
@@ -1,9 +0,0 @@
-# Don't separate small simple statements.
-is_android = false
-is_chromeos = false
-is_ios = false
-is_linux -= false
-is_mac = true
-is_nacl = false
-is_posix += true
-is_win = false
diff --git a/chromium/tools/gn/format_test_data/030.gn b/chromium/tools/gn/format_test_data/030.gn
deleted file mode 100644
index adac9a82416..00000000000
--- a/chromium/tools/gn/format_test_data/030.gn
+++ /dev/null
@@ -1,12 +0,0 @@
-# Don't separate simple statements in a scope.
-
-import("//testing/test.gni")
-
-test("something") {
- if (is_linux) {
- sources -= [ "file_version_info_unittest.cc" ]
- sources += [ "nix/xdg_util_unittest.cc" ]
- defines = [ "USE_SYMBOLIZE" ]
- configs += [ "//build/config/linux:glib" ]
- }
-}
diff --git a/chromium/tools/gn/format_test_data/030.golden b/chromium/tools/gn/format_test_data/030.golden
deleted file mode 100644
index adac9a82416..00000000000
--- a/chromium/tools/gn/format_test_data/030.golden
+++ /dev/null
@@ -1,12 +0,0 @@
-# Don't separate simple statements in a scope.
-
-import("//testing/test.gni")
-
-test("something") {
- if (is_linux) {
- sources -= [ "file_version_info_unittest.cc" ]
- sources += [ "nix/xdg_util_unittest.cc" ]
- defines = [ "USE_SYMBOLIZE" ]
- configs += [ "//build/config/linux:glib" ]
- }
-}
diff --git a/chromium/tools/gn/format_test_data/031.gn b/chromium/tools/gn/format_test_data/031.gn
deleted file mode 100644
index d83d4234a70..00000000000
--- a/chromium/tools/gn/format_test_data/031.gn
+++ /dev/null
@@ -1,8 +0,0 @@
-deps += [
- ":packed_extra_resources",
- ":packed_resources",
-
- # This shouldn't crash.
-
- # This shouldn't crash 2.
- ]
diff --git a/chromium/tools/gn/format_test_data/031.golden b/chromium/tools/gn/format_test_data/031.golden
deleted file mode 100644
index 6653951f16a..00000000000
--- a/chromium/tools/gn/format_test_data/031.golden
+++ /dev/null
@@ -1,8 +0,0 @@
-deps += [
- ":packed_extra_resources",
- ":packed_resources",
-
- # This shouldn't crash.
-
- # This shouldn't crash 2.
-]
diff --git a/chromium/tools/gn/format_test_data/032.gn b/chromium/tools/gn/format_test_data/032.gn
deleted file mode 100644
index d7ea7e5f8f4..00000000000
--- a/chromium/tools/gn/format_test_data/032.gn
+++ /dev/null
@@ -1,6 +0,0 @@
-# Make sure continued conditions are aligned.
-if (something) {
- if (false) {
- } else if (is_linux && !is_android && current_cpu == "x64" && !disable_iterator_debugging) {
- }
-}
diff --git a/chromium/tools/gn/format_test_data/032.golden b/chromium/tools/gn/format_test_data/032.golden
deleted file mode 100644
index aeca8963933..00000000000
--- a/chromium/tools/gn/format_test_data/032.golden
+++ /dev/null
@@ -1,7 +0,0 @@
-# Make sure continued conditions are aligned.
-if (something) {
- if (false) {
- } else if (is_linux && !is_android && current_cpu == "x64" &&
- !disable_iterator_debugging) {
- }
-}
diff --git a/chromium/tools/gn/format_test_data/033.gn b/chromium/tools/gn/format_test_data/033.gn
deleted file mode 100644
index 6767acd6b93..00000000000
--- a/chromium/tools/gn/format_test_data/033.gn
+++ /dev/null
@@ -1,8 +0,0 @@
-# Don't attach trailing comments too far back.
-if (!is_android) {
- source_set("tcmalloc") {
- if (is_win) {
- ldflags = [ "/ignore:4006:4221" ]
- } # is_win
- } # source_set
-} # !is_android
diff --git a/chromium/tools/gn/format_test_data/033.golden b/chromium/tools/gn/format_test_data/033.golden
deleted file mode 100644
index 6767acd6b93..00000000000
--- a/chromium/tools/gn/format_test_data/033.golden
+++ /dev/null
@@ -1,8 +0,0 @@
-# Don't attach trailing comments too far back.
-if (!is_android) {
- source_set("tcmalloc") {
- if (is_win) {
- ldflags = [ "/ignore:4006:4221" ]
- } # is_win
- } # source_set
-} # !is_android
diff --git a/chromium/tools/gn/format_test_data/034.gn b/chromium/tools/gn/format_test_data/034.gn
deleted file mode 100644
index 33f5eadceb5..00000000000
--- a/chromium/tools/gn/format_test_data/034.gn
+++ /dev/null
@@ -1,13 +0,0 @@
-# Special case for 'args': If args[N] starts with '-' and args[N+1] is a call to
-# rebase_path, keep them as a pair, rather than breaking into individual items.
-action("wee") {
- if (something) {
- args = [
- "--depfile", rebase_path(depfile, root_build_dir),
- "--android-sdk", rebase_path(android_sdk, root_build_dir),
- "--android-sdk-tools",
- rebase_path(android_sdk_build_tools, root_build_dir),
- "--android-manifest", rebase_path(android_manifest, root_build_dir),
- ]
- }
-}
diff --git a/chromium/tools/gn/format_test_data/035.gn b/chromium/tools/gn/format_test_data/035.gn
deleted file mode 100644
index 70bc1a9eca0..00000000000
--- a/chromium/tools/gn/format_test_data/035.gn
+++ /dev/null
@@ -1 +0,0 @@
-import("//build/config/sysroot.gni") # Imports android/config.gni.
diff --git a/chromium/tools/gn/format_test_data/035.golden b/chromium/tools/gn/format_test_data/035.golden
deleted file mode 100644
index 70bc1a9eca0..00000000000
--- a/chromium/tools/gn/format_test_data/035.golden
+++ /dev/null
@@ -1 +0,0 @@
-import("//build/config/sysroot.gni") # Imports android/config.gni.
diff --git a/chromium/tools/gn/format_test_data/036.gn b/chromium/tools/gn/format_test_data/036.gn
deleted file mode 100644
index 5a5eca8455c..00000000000
--- a/chromium/tools/gn/format_test_data/036.gn
+++ /dev/null
@@ -1,9 +0,0 @@
-import("a")
-import("b")
-
-assert(x)
-assert(y)
-assert(z)
-
-source_set("stuff") {
-}
diff --git a/chromium/tools/gn/format_test_data/036.golden b/chromium/tools/gn/format_test_data/036.golden
deleted file mode 100644
index 5a5eca8455c..00000000000
--- a/chromium/tools/gn/format_test_data/036.golden
+++ /dev/null
@@ -1,9 +0,0 @@
-import("a")
-import("b")
-
-assert(x)
-assert(y)
-assert(z)
-
-source_set("stuff") {
-}
diff --git a/chromium/tools/gn/format_test_data/037.gn b/chromium/tools/gn/format_test_data/037.gn
deleted file mode 100644
index ebbf0f8fa9a..00000000000
--- a/chromium/tools/gn/format_test_data/037.gn
+++ /dev/null
@@ -1,5 +0,0 @@
-if (true) {
- if (true) {
- args = rebase_path(sources, root_build_dir) + rebase_path(outputs, root_build_dir)
- }
-}
diff --git a/chromium/tools/gn/format_test_data/037.golden b/chromium/tools/gn/format_test_data/037.golden
deleted file mode 100644
index 71e95a4b581..00000000000
--- a/chromium/tools/gn/format_test_data/037.golden
+++ /dev/null
@@ -1,6 +0,0 @@
-if (true) {
- if (true) {
- args = rebase_path(sources, root_build_dir) +
- rebase_path(outputs, root_build_dir)
- }
-}
diff --git a/chromium/tools/gn/format_test_data/038.gn b/chromium/tools/gn/format_test_data/038.gn
deleted file mode 100644
index ea06d93da70..00000000000
--- a/chromium/tools/gn/format_test_data/038.gn
+++ /dev/null
@@ -1,4 +0,0 @@
-if (stuff) {
- # Blank line at EOF.
-}
-
diff --git a/chromium/tools/gn/format_test_data/038.golden b/chromium/tools/gn/format_test_data/038.golden
deleted file mode 100644
index f8c9a1b92b0..00000000000
--- a/chromium/tools/gn/format_test_data/038.golden
+++ /dev/null
@@ -1,3 +0,0 @@
-if (stuff) {
- # Blank line at EOF.
-}
diff --git a/chromium/tools/gn/format_test_data/039.gn b/chromium/tools/gn/format_test_data/039.gn
deleted file mode 100644
index 662b8cdb108..00000000000
--- a/chromium/tools/gn/format_test_data/039.gn
+++ /dev/null
@@ -1,6 +0,0 @@
-if (true) {
- assert(arm_float_abi == "" ||
- arm_float_abi == "hard" ||
- arm_float_abi == "soft" ||
- arm_float_abi == "softfp")
-}
diff --git a/chromium/tools/gn/format_test_data/039.golden b/chromium/tools/gn/format_test_data/039.golden
deleted file mode 100644
index b92b1ae838b..00000000000
--- a/chromium/tools/gn/format_test_data/039.golden
+++ /dev/null
@@ -1,4 +0,0 @@
-if (true) {
- assert(arm_float_abi == "" || arm_float_abi == "hard" ||
- arm_float_abi == "soft" || arm_float_abi == "softfp")
-}
diff --git a/chromium/tools/gn/format_test_data/040.gn b/chromium/tools/gn/format_test_data/040.gn
deleted file mode 100644
index 1f4754e2794..00000000000
--- a/chromium/tools/gn/format_test_data/040.gn
+++ /dev/null
@@ -1,9 +0,0 @@
-# Dewrapping shouldn't cause 80 col to be exceed.
-# 80 ---------------------------------------------------------------------------
-if (true) {
- if (is_win) {
- cflags = [
- "/wd4267", # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- ]
- }
-}
diff --git a/chromium/tools/gn/format_test_data/041.gn b/chromium/tools/gn/format_test_data/041.gn
deleted file mode 100644
index fa39b4923ff..00000000000
--- a/chromium/tools/gn/format_test_data/041.gn
+++ /dev/null
@@ -1,12 +0,0 @@
-if (true) {
- a = [ "wee" ]
-
- b = [
- "x",
- "y",
- "z",
- ]
- c = [ "x" ]
-
- d = [ "x" ]
-}
diff --git a/chromium/tools/gn/format_test_data/041.golden b/chromium/tools/gn/format_test_data/041.golden
deleted file mode 100644
index fa39b4923ff..00000000000
--- a/chromium/tools/gn/format_test_data/041.golden
+++ /dev/null
@@ -1,12 +0,0 @@
-if (true) {
- a = [ "wee" ]
-
- b = [
- "x",
- "y",
- "z",
- ]
- c = [ "x" ]
-
- d = [ "x" ]
-}
diff --git a/chromium/tools/gn/format_test_data/042.gn b/chromium/tools/gn/format_test_data/042.gn
deleted file mode 100644
index b827f29e070..00000000000
--- a/chromium/tools/gn/format_test_data/042.gn
+++ /dev/null
@@ -1,44 +0,0 @@
-# Test zero, one, and multiple element for specifically named LHSs.
-if (true) {
- cflags = []
- cflags_c = []
- cflags_cc = []
- data = []
- datadeps = []
- defines = []
- deps = []
- include_dirs = []
- inputs = []
- ldflags = []
- outputs = []
- public_deps = []
- sources = []
-} else if (true) {
- cflags = [ "x" ]
- cflags_c = [ "x" ]
- cflags_cc = [ "x" ]
- data = [ "x" ]
- datadeps = [ "x" ]
- defines = [ "x" ]
- deps = [ "x" ]
- include_dirs = [ "x" ]
- inputs = [ "x" ]
- ldflags = [ "x" ]
- outputs = [ "x" ]
- public_deps = [ "x" ]
- sources = [ "x" ]
-} else {
- cflags = [ "x", "y", "z"]
- cflags_c = [ "x", "y", "z"]
- cflags_cc = [ "x", "y", "z"]
- data = [ "x", "y", "z"]
- datadeps = [ "x", "y", "z"]
- defines = [ "x", "y", "z"]
- deps = [ "x", "y", "z"]
- include_dirs = [ "x", "y", "z"]
- inputs = [ "x", "y", "z"]
- ldflags = [ "x", "y", "z"]
- outputs = [ "x", "y", "z"]
- public_deps = [ "x", "y", "z"]
- sources = [ "x", "y", "z"]
-}
diff --git a/chromium/tools/gn/format_test_data/042.golden b/chromium/tools/gn/format_test_data/042.golden
deleted file mode 100644
index 1968d0acd94..00000000000
--- a/chromium/tools/gn/format_test_data/042.golden
+++ /dev/null
@@ -1,110 +0,0 @@
-# Test zero, one, and multiple element for specifically named LHSs.
-if (true) {
- cflags = []
- cflags_c = []
- cflags_cc = []
- data = []
- datadeps = []
- defines = []
- deps = []
- include_dirs = []
- inputs = []
- ldflags = []
- outputs = []
- public_deps = []
- sources = []
-} else if (true) {
- cflags = [ "x" ]
- cflags_c = [ "x" ]
- cflags_cc = [ "x" ]
- data = [
- "x",
- ]
- datadeps = [
- "x",
- ]
- defines = [ "x" ]
- deps = [
- "x",
- ]
- include_dirs = [ "x" ]
- inputs = [
- "x",
- ]
- ldflags = [ "x" ]
- outputs = [
- "x",
- ]
- public_deps = [
- "x",
- ]
- sources = [
- "x",
- ]
-} else {
- cflags = [
- "x",
- "y",
- "z",
- ]
- cflags_c = [
- "x",
- "y",
- "z",
- ]
- cflags_cc = [
- "x",
- "y",
- "z",
- ]
- data = [
- "x",
- "y",
- "z",
- ]
- datadeps = [
- "x",
- "y",
- "z",
- ]
- defines = [
- "x",
- "y",
- "z",
- ]
- deps = [
- "x",
- "y",
- "z",
- ]
- include_dirs = [
- "x",
- "y",
- "z",
- ]
- inputs = [
- "x",
- "y",
- "z",
- ]
- ldflags = [
- "x",
- "y",
- "z",
- ]
- outputs = [
- "x",
- "y",
- "z",
- ]
- public_deps = [
- "x",
- "y",
- "z",
- ]
- sources = [
- "x",
- "y",
- "z",
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/043.gn b/chromium/tools/gn/format_test_data/043.gn
deleted file mode 100644
index b95c6a52593..00000000000
--- a/chromium/tools/gn/format_test_data/043.gn
+++ /dev/null
@@ -1,6 +0,0 @@
-# Don't break and indent when it's hopeless.
-# 80 ---------------------------------------------------------------------------
-android_java_prebuilt("android_support_v13_java") {
- jar_path = "$android_sdk_root/extras/android/support/v7/appcompat/libs/android-support-v7-appcompat.jar"
- jar_path = "$android_sdk_root/extras/android/support/v13/android-support-v13.jar"
-}
diff --git a/chromium/tools/gn/format_test_data/043.golden b/chromium/tools/gn/format_test_data/043.golden
deleted file mode 100644
index 336ec2fff1e..00000000000
--- a/chromium/tools/gn/format_test_data/043.golden
+++ /dev/null
@@ -1,7 +0,0 @@
-# Don't break and indent when it's hopeless.
-# 80 ---------------------------------------------------------------------------
-android_java_prebuilt("android_support_v13_java") {
- jar_path = "$android_sdk_root/extras/android/support/v7/appcompat/libs/android-support-v7-appcompat.jar"
- jar_path =
- "$android_sdk_root/extras/android/support/v13/android-support-v13.jar"
-}
diff --git a/chromium/tools/gn/format_test_data/044.gn b/chromium/tools/gn/format_test_data/044.gn
deleted file mode 100644
index fe09617912d..00000000000
--- a/chromium/tools/gn/format_test_data/044.gn
+++ /dev/null
@@ -1,10 +0,0 @@
-config("compiler") {
- if (is_win) {
- if (is_component_build) {
- cflags += [
- "/EHsc", # Assume C functions can't throw exceptions and don't catch
- # structured exceptions (only C++ ones).
- ]
- }
- }
-}
diff --git a/chromium/tools/gn/format_test_data/044.golden b/chromium/tools/gn/format_test_data/044.golden
deleted file mode 100644
index 030c5dd5dc7..00000000000
--- a/chromium/tools/gn/format_test_data/044.golden
+++ /dev/null
@@ -1,11 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-config("compiler") {
- if (is_win) {
- if (is_component_build) {
- cflags += [
- "/EHsc", # Assume C functions can't throw exceptions and don't catch
- # structured exceptions (only C++ ones).
- ]
- }
- }
-}
diff --git a/chromium/tools/gn/format_test_data/045.gn b/chromium/tools/gn/format_test_data/045.gn
deleted file mode 100644
index 28a7280d3ba..00000000000
--- a/chromium/tools/gn/format_test_data/045.gn
+++ /dev/null
@@ -1,10 +0,0 @@
-static_library("browser") {
- if (!is_ios) {
- sources += rebase_path(gypi_values.chrome_browser_predictor_sources,
- ".", "//chrome")
- sources += rebase_path(gypi_values.chrome_browser_predictor_sourcesaaaaaaaa,
- ".", "//chrome")
- sources += rebase_path(gypi_values.chrome_browser_predictor_sourcesaaaaaaaaa,
- ".", "//chrome")
- }
-}
diff --git a/chromium/tools/gn/format_test_data/045.golden b/chromium/tools/gn/format_test_data/045.golden
deleted file mode 100644
index 21c560a80f4..00000000000
--- a/chromium/tools/gn/format_test_data/045.golden
+++ /dev/null
@@ -1,14 +0,0 @@
-static_library("browser") {
- if (!is_ios) {
- sources += rebase_path(gypi_values.chrome_browser_predictor_sources,
- ".",
- "//chrome")
- sources += rebase_path(gypi_values.chrome_browser_predictor_sourcesaaaaaaaa,
- ".",
- "//chrome")
- sources +=
- rebase_path(gypi_values.chrome_browser_predictor_sourcesaaaaaaaaa,
- ".",
- "//chrome")
- }
-}
diff --git a/chromium/tools/gn/format_test_data/046.gn b/chromium/tools/gn/format_test_data/046.gn
deleted file mode 100644
index 28df74be66c..00000000000
--- a/chromium/tools/gn/format_test_data/046.gn
+++ /dev/null
@@ -1,22 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-if (true) {
- # The JavaScript files required by main.html.
- remoting_webapp_main_html_js_files =
- # Include the core files first as it is required by the other files.
- # Otherwise, Jscompile will complain.
- remoting_webapp_js_core_files +
- remoting_webapp_js_auth_client2host_files +
- remoting_webapp_js_auth_google_files +
- remoting_webapp_js_client_files +
- remoting_webapp_js_gnubby_auth_files +
- remoting_webapp_js_cast_extension_files +
- remoting_webapp_js_host_files +
- remoting_webapp_js_logging_files +
- remoting_webapp_js_ui_files +
- remoting_webapp_js_ui_host_control_files +
- remoting_webapp_js_ui_host_display_files +
- remoting_webapp_js_wcs_container_files
- # Uncomment this line to include browser test files in the web app
- # to expedite debugging or local development.
- #+ remoting_webapp_js_browser_test_files
-}
diff --git a/chromium/tools/gn/format_test_data/046.golden b/chromium/tools/gn/format_test_data/046.golden
deleted file mode 100644
index 7d2a679c18d..00000000000
--- a/chromium/tools/gn/format_test_data/046.golden
+++ /dev/null
@@ -1,19 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-if (true) {
- # The JavaScript files required by main.html.
- remoting_webapp_main_html_js_files =
- # Include the core files first as it is required by the other files.
- # Otherwise, Jscompile will complain.
- remoting_webapp_js_core_files +
- remoting_webapp_js_auth_client2host_files +
- remoting_webapp_js_auth_google_files + remoting_webapp_js_client_files +
- remoting_webapp_js_gnubby_auth_files +
- remoting_webapp_js_cast_extension_files + remoting_webapp_js_host_files +
- remoting_webapp_js_logging_files + remoting_webapp_js_ui_files +
- remoting_webapp_js_ui_host_control_files +
- remoting_webapp_js_ui_host_display_files +
- remoting_webapp_js_wcs_container_files
- # Uncomment this line to include browser test files in the web app
- # to expedite debugging or local development.
- #+ remoting_webapp_js_browser_test_files
-}
diff --git a/chromium/tools/gn/format_test_data/047.gn b/chromium/tools/gn/format_test_data/047.gn
deleted file mode 100644
index f1fdbeca8b5..00000000000
--- a/chromium/tools/gn/format_test_data/047.gn
+++ /dev/null
@@ -1,7 +0,0 @@
-if (true) {
- args += [ "--template" ] +
- rebase_path(remoting_webapp_template_files, template_rel_dir)
- args += [ "--dir-for-templates",
- rebase_path(template_rel_dir, root_build_dir) ]
- args += ["--js"] + rebase_path(remoting_webapp_main_html_js_files, template_rel_dir_and_some_more)
-}
diff --git a/chromium/tools/gn/format_test_data/047.golden b/chromium/tools/gn/format_test_data/047.golden
deleted file mode 100644
index 5217e762580..00000000000
--- a/chromium/tools/gn/format_test_data/047.golden
+++ /dev/null
@@ -1,10 +0,0 @@
-if (true) {
- args += [ "--template" ] +
- rebase_path(remoting_webapp_template_files, template_rel_dir)
- args += [
- "--dir-for-templates",
- rebase_path(template_rel_dir, root_build_dir),
- ]
- args += [ "--js" ] + rebase_path(remoting_webapp_main_html_js_files,
- template_rel_dir_and_some_more)
-}
diff --git a/chromium/tools/gn/format_test_data/048.gn b/chromium/tools/gn/format_test_data/048.gn
deleted file mode 100644
index 7d39efb68c4..00000000000
--- a/chromium/tools/gn/format_test_data/048.gn
+++ /dev/null
@@ -1,19 +0,0 @@
-# No blank inserted after libs (caused by trailing comment on 'else').
-component("google_toolbox_for_mac") {
- if (!is_ios) {
- sources += [
- "src/AddressBook/GTMABAddressBook.h",
- "src/AddressBook/GTMABAddressBook.m",
- ]
-
- libs = [
- "AddressBook.framework",
- "AppKit.framework",
- ]
- } else { # is_ios
- sources += [
- "src/iPhone/GTMFadeTruncatingLabel.h",
- "src/iPhone/GTMFadeTruncatingLabel.m",
- ]
- }
-}
diff --git a/chromium/tools/gn/format_test_data/048.golden b/chromium/tools/gn/format_test_data/048.golden
deleted file mode 100644
index 7d39efb68c4..00000000000
--- a/chromium/tools/gn/format_test_data/048.golden
+++ /dev/null
@@ -1,19 +0,0 @@
-# No blank inserted after libs (caused by trailing comment on 'else').
-component("google_toolbox_for_mac") {
- if (!is_ios) {
- sources += [
- "src/AddressBook/GTMABAddressBook.h",
- "src/AddressBook/GTMABAddressBook.m",
- ]
-
- libs = [
- "AddressBook.framework",
- "AppKit.framework",
- ]
- } else { # is_ios
- sources += [
- "src/iPhone/GTMFadeTruncatingLabel.h",
- "src/iPhone/GTMFadeTruncatingLabel.m",
- ]
- }
-}
diff --git a/chromium/tools/gn/format_test_data/049.gn b/chromium/tools/gn/format_test_data/049.gn
deleted file mode 100644
index fe793d2898a..00000000000
--- a/chromium/tools/gn/format_test_data/049.gn
+++ /dev/null
@@ -1,14 +0,0 @@
-func(aaaaaaaaaaaaaaaaaaaaa,
- bbbbbbbbbbbbbbbbbbbbbbbbbb,
- # Comment about function arg.
- ccccccccccccccccccccccccccccc,
- dddddddddddddddddddd)
-
-func(aaaaaaaaaaaaaaaaaaaaa,
- bbbbbbbbbbbbbbbbbbbbbbbbbb,
-
- # Block comment
- # Comment about function arg.
-
- ccccccccccccccccccccccccccccc,
- dddddddddddddddddddd)
diff --git a/chromium/tools/gn/format_test_data/050.gn b/chromium/tools/gn/format_test_data/050.gn
deleted file mode 100644
index 92a6d6d7d4b..00000000000
--- a/chromium/tools/gn/format_test_data/050.gn
+++ /dev/null
@@ -1,10 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-zippy = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb - cccccccccccccccccccccccc)
-
-zippy = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccccccccccc
-
-zippy = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccccccccccc + ddddddddddddddddddddd + eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + ffffffffffffff(aaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccc, ddddddddddddddddddd)
-
-zippy = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccccccccccc + ddddddddddddddddddddd + eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + ffffffffffffff(aaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbb + ccccccccccccccccccc + ddddddddddddddddddd)
-
-zippy = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + cccccccccccccccccccccccc + ddddddddddddddddddddd + eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + ffffffffffffff(aaaaaaaaaaaaa - (bbbbbbbbbbbbbbbbbbbbbbbb + ccccccccccccccccccc + ddddddddddddddddddd))
diff --git a/chromium/tools/gn/format_test_data/050.golden b/chromium/tools/gn/format_test_data/050.golden
deleted file mode 100644
index 2645600c738..00000000000
--- a/chromium/tools/gn/format_test_data/050.golden
+++ /dev/null
@@ -1,27 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-zippy = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -
- (bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb - cccccccccccccccccccccccc)
-
-zippy = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +
- cccccccccccccccccccccccc
-
-zippy = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +
- cccccccccccccccccccccccc + ddddddddddddddddddddd +
- eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee +
- ffffffffffffff(aaaaaaaaaaaaa,
- bbbbbbbbbbbbbbbbbbbbbbbb,
- ccccccccccccccccccc,
- ddddddddddddddddddd)
-
-zippy = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +
- cccccccccccccccccccccccc + ddddddddddddddddddddd +
- eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee +
- ffffffffffffff(aaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbb +
- ccccccccccccccccccc + ddddddddddddddddddd)
-
-zippy =
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +
- cccccccccccccccccccccccc + ddddddddddddddddddddd +
- eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee +
- ffffffffffffff(aaaaaaaaaaaaa - (bbbbbbbbbbbbbbbbbbbbbbbb +
- ccccccccccccccccccc + ddddddddddddddddddd))
diff --git a/chromium/tools/gn/format_test_data/051.gn b/chromium/tools/gn/format_test_data/051.gn
deleted file mode 100644
index 8076ec696d4..00000000000
--- a/chromium/tools/gn/format_test_data/051.gn
+++ /dev/null
@@ -1,6 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-if (true) {
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa =
- bbbbbbbbbbbbbbbbbbbb - bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +
- cccccccccccccccccccccccccccccccccccc
-}
diff --git a/chromium/tools/gn/format_test_data/051.golden b/chromium/tools/gn/format_test_data/051.golden
deleted file mode 100644
index 37a12124013..00000000000
--- a/chromium/tools/gn/format_test_data/051.golden
+++ /dev/null
@@ -1,7 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-if (true) {
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa =
- bbbbbbbbbbbbbbbbbbbb -
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +
- cccccccccccccccccccccccccccccccccccc
-}
diff --git a/chromium/tools/gn/format_test_data/052.gn b/chromium/tools/gn/format_test_data/052.gn
deleted file mode 100644
index 1f6a10f5159..00000000000
--- a/chromium/tools/gn/format_test_data/052.gn
+++ /dev/null
@@ -1,11 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-if (true) {
- if (true) {
- sources += rebase_path(
- gypi_values.browser_chromeos_non_athena_sources,
- ".", "//chrome") +
- rebase_path(gypi_values.browser_chromeos_extension_non_athena_sources,
- ".", "//chrome")
- }
-}
-
diff --git a/chromium/tools/gn/format_test_data/052.golden b/chromium/tools/gn/format_test_data/052.golden
deleted file mode 100644
index 880c5639f2c..00000000000
--- a/chromium/tools/gn/format_test_data/052.golden
+++ /dev/null
@@ -1,12 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-if (true) {
- if (true) {
- sources +=
- rebase_path(gypi_values.browser_chromeos_non_athena_sources,
- ".",
- "//chrome") +
- rebase_path(gypi_values.browser_chromeos_extension_non_athena_sources,
- ".",
- "//chrome")
- }
-}
diff --git a/chromium/tools/gn/format_test_data/053.gn b/chromium/tools/gn/format_test_data/053.gn
deleted file mode 100644
index 42a3e0899ba..00000000000
--- a/chromium/tools/gn/format_test_data/053.gn
+++ /dev/null
@@ -1,7 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-if (true) {
- check_internal_result = exec_script(
- "build/check_internal.py",
- [ rebase_path("internal/google_chrome_api_keys.h", root_build_dir) ],
- "value")
-}
diff --git a/chromium/tools/gn/format_test_data/053.golden b/chromium/tools/gn/format_test_data/053.golden
deleted file mode 100644
index 76179cc1953..00000000000
--- a/chromium/tools/gn/format_test_data/053.golden
+++ /dev/null
@@ -1,8 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-if (true) {
- check_internal_result =
- exec_script("build/check_internal.py",
- [ rebase_path("internal/google_chrome_api_keys.h",
- root_build_dir) ],
- "value")
-}
diff --git a/chromium/tools/gn/format_test_data/054.gn b/chromium/tools/gn/format_test_data/054.gn
deleted file mode 100644
index dca2ace3b32..00000000000
--- a/chromium/tools/gn/format_test_data/054.gn
+++ /dev/null
@@ -1,7 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-if (true) {
- args = [
- "{{source}}",
- rebase_path("${target_gen_dir}/{{source_name_part}}-inc.cc", root_build_dir)
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/054.golden b/chromium/tools/gn/format_test_data/054.golden
deleted file mode 100644
index 7dfe5be7f26..00000000000
--- a/chromium/tools/gn/format_test_data/054.golden
+++ /dev/null
@@ -1,8 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-if (true) {
- args = [
- "{{source}}",
- rebase_path("${target_gen_dir}/{{source_name_part}}-inc.cc",
- root_build_dir),
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/055.gn b/chromium/tools/gn/format_test_data/055.gn
deleted file mode 100644
index 7e467247694..00000000000
--- a/chromium/tools/gn/format_test_data/055.gn
+++ /dev/null
@@ -1,10 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-if (true) {
- if (true) {
- use_system_harfbuzz = exec_script(
- pkg_config_script,
- pkg_config_args + [ "--atleast-version=1.31.0", "pangoft2" ],
- "value")
- }
-}
-
diff --git a/chromium/tools/gn/format_test_data/055.golden b/chromium/tools/gn/format_test_data/055.golden
deleted file mode 100644
index b2bfdf28654..00000000000
--- a/chromium/tools/gn/format_test_data/055.golden
+++ /dev/null
@@ -1,11 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-if (true) {
- if (true) {
- use_system_harfbuzz = exec_script(pkg_config_script,
- pkg_config_args + [
- "--atleast-version=1.31.0",
- "pangoft2",
- ],
- "value")
- }
-}
diff --git a/chromium/tools/gn/format_test_data/056.gn b/chromium/tools/gn/format_test_data/056.gn
deleted file mode 100644
index 2082a770d87..00000000000
--- a/chromium/tools/gn/format_test_data/056.gn
+++ /dev/null
@@ -1,45 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-java_files = [
- "test/android/java/src/org/chromium/base/ContentUriTestUtils.java"
-]
-
-defines = [
- "test/android/java/src/org/chromium/base/ContentUriTestUtils.java"
-]
-
-defines = [
- "abc/test/android/java/src/org/chromium/base/ContentUriTestUtils.java"
-]
-
-cflags += [
- # WEE
- "/a",
- "/b",
- "/c",
-]
-
-sources = [ "/a", "/b", "/c" ]
-
-sources = [
- # WEE
- "/a",
- "/b",
- "/c",
-]
-
-sources += [
- # WEE
- "/a",
- "/b",
- "/c",
-]
-
-configs -= [
- # Something!
- "//build/config/win:nominmax",
-]
-
-cflags = [
- "/wd4267", # size_t -> int
- "/wd4324", # structure was padded
-]
diff --git a/chromium/tools/gn/format_test_data/056.golden b/chromium/tools/gn/format_test_data/056.golden
deleted file mode 100644
index df088fc06b5..00000000000
--- a/chromium/tools/gn/format_test_data/056.golden
+++ /dev/null
@@ -1,45 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-java_files =
- [ "test/android/java/src/org/chromium/base/ContentUriTestUtils.java" ]
-
-defines = [ "test/android/java/src/org/chromium/base/ContentUriTestUtils.java" ]
-
-defines =
- [ "abc/test/android/java/src/org/chromium/base/ContentUriTestUtils.java" ]
-
-cflags += [
- # WEE
- "/a",
- "/b",
- "/c",
-]
-
-sources = [
- "/a",
- "/b",
- "/c",
-]
-
-sources = [
- # WEE
- "/a",
- "/b",
- "/c",
-]
-
-sources += [
- # WEE
- "/a",
- "/b",
- "/c",
-]
-
-configs -= [
- # Something!
- "//build/config/win:nominmax",
-]
-
-cflags = [
- "/wd4267", # size_t -> int
- "/wd4324", # structure was padded
-]
diff --git a/chromium/tools/gn/format_test_data/057.gn b/chromium/tools/gn/format_test_data/057.gn
deleted file mode 100644
index 858e3115b11..00000000000
--- a/chromium/tools/gn/format_test_data/057.gn
+++ /dev/null
@@ -1,24 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-# Because there is a difference in precedence level between || and &&
-# a || b || c && d
-# is equivalent to
-# a || b || (c && d)
-# Because parens are not stored in the parse tree, the formatter recreates the
-# minimally required set to maintain meaning. However, this particular case can
-# be confusing for human readers, so we special case these ones and add
-# strictly-unnecessary parens.
-
-supports_android = (is_apk || is_android_resources ||
- (is_java_library && defined(invoker.supports_android) &&
- invoker.supports_android))
-
-enable_one_click_signin = is_win || is_mac || (is_linux && !is_chromeos)
-enable_one_click_signin = (is_linux && !is_chromeos) || is_win || is_mac
-
-x = c || (a&&b)
-x = (a&&b) || c
-x = a&&b || c
-
-x = c && (a||b)
-x = (a||b) && c
-x = a||b && c
diff --git a/chromium/tools/gn/format_test_data/057.golden b/chromium/tools/gn/format_test_data/057.golden
deleted file mode 100644
index d0daa6c8e72..00000000000
--- a/chromium/tools/gn/format_test_data/057.golden
+++ /dev/null
@@ -1,24 +0,0 @@
-# 80 ---------------------------------------------------------------------------
-# Because there is a difference in precedence level between || and &&
-# a || b || c && d
-# is equivalent to
-# a || b || (c && d)
-# Because parens are not stored in the parse tree, the formatter recreates the
-# minimally required set to maintain meaning. However, this particular case can
-# be confusing for human readers, so we special case these ones and add
-# strictly-unnecessary parens.
-
-supports_android = is_apk || is_android_resources ||
- (is_java_library && defined(invoker.supports_android) &&
- invoker.supports_android)
-
-enable_one_click_signin = is_win || is_mac || (is_linux && !is_chromeos)
-enable_one_click_signin = (is_linux && !is_chromeos) || is_win || is_mac
-
-x = c || (a && b)
-x = (a && b) || c
-x = (a && b) || c
-
-x = c && (a || b)
-x = (a || b) && c
-x = a || (b && c)
diff --git a/chromium/tools/gn/format_test_data/058.gn b/chromium/tools/gn/format_test_data/058.gn
deleted file mode 100644
index 568074a634b..00000000000
--- a/chromium/tools/gn/format_test_data/058.gn
+++ /dev/null
@@ -1,2 +0,0 @@
-if (!defined(invoker.ignore_libs) || !invoker.ignore_libs) {
-}
diff --git a/chromium/tools/gn/format_test_data/058.golden b/chromium/tools/gn/format_test_data/058.golden
deleted file mode 100644
index 568074a634b..00000000000
--- a/chromium/tools/gn/format_test_data/058.golden
+++ /dev/null
@@ -1,2 +0,0 @@
-if (!defined(invoker.ignore_libs) || !invoker.ignore_libs) {
-}
diff --git a/chromium/tools/gn/format_test_data/059.gn b/chromium/tools/gn/format_test_data/059.gn
deleted file mode 100644
index ea6fb8e3dc8..00000000000
--- a/chromium/tools/gn/format_test_data/059.gn
+++ /dev/null
@@ -1,10 +0,0 @@
-assert(type == "android_apk" || type == "java_library" ||
- type == "android_resources" || things == stuff && stuff != 432)
-
-assert(type == "android_apk" || type == "java_library" ||
- type == "android_resources",
- type == "android_apk" || type == "java_library" ||
- type == "android_resources")
-
-
-if (type == "android_apk" || type == "java_library" || type == "android_resources" || things == stuff && stuff != 432) {}
diff --git a/chromium/tools/gn/format_test_data/059.golden b/chromium/tools/gn/format_test_data/059.golden
deleted file mode 100644
index 423e88882e1..00000000000
--- a/chromium/tools/gn/format_test_data/059.golden
+++ /dev/null
@@ -1,11 +0,0 @@
-assert(type == "android_apk" || type == "java_library" ||
- type == "android_resources" || (things == stuff && stuff != 432))
-
-assert(type == "android_apk" || type == "java_library" ||
- type == "android_resources",
- type == "android_apk" || type == "java_library" ||
- type == "android_resources")
-
-if (type == "android_apk" || type == "java_library" ||
- type == "android_resources" || (things == stuff && stuff != 432)) {
-}
diff --git a/chromium/tools/gn/format_test_data/060.gn b/chromium/tools/gn/format_test_data/060.gn
deleted file mode 100644
index 2b0da79f7cb..00000000000
--- a/chromium/tools/gn/format_test_data/060.gn
+++ /dev/null
@@ -1,2 +0,0 @@
-some_variable = "this is a very long string that is going to exceed 80 col and will never under any circumstance fit"
-another_variable = [ "this is a very long string that is going to exceed 80 col and will never under any circumstance fit" ]
diff --git a/chromium/tools/gn/format_test_data/060.golden b/chromium/tools/gn/format_test_data/060.golden
deleted file mode 100644
index 2b0da79f7cb..00000000000
--- a/chromium/tools/gn/format_test_data/060.golden
+++ /dev/null
@@ -1,2 +0,0 @@
-some_variable = "this is a very long string that is going to exceed 80 col and will never under any circumstance fit"
-another_variable = [ "this is a very long string that is going to exceed 80 col and will never under any circumstance fit" ]
diff --git a/chromium/tools/gn/format_test_data/061.gn b/chromium/tools/gn/format_test_data/061.gn
deleted file mode 100644
index 5948037fe56..00000000000
--- a/chromium/tools/gn/format_test_data/061.gn
+++ /dev/null
@@ -1,9 +0,0 @@
-action("generate_gl_bindings") {
- args = [
- "--header-paths=" + rebase_path("//third_party/khronos", root_build_dir) +
- ":" + rebase_path("//third_party/mesa/src/include", root_build_dir) + ":" +
- rebase_path("//ui/gl", root_build_dir) + ":" +
- rebase_path("//gpu", root_build_dir),
- rebase_path(gl_binding_output_dir, root_build_dir),
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/061.golden b/chromium/tools/gn/format_test_data/061.golden
deleted file mode 100644
index edbf43dc6ad..00000000000
--- a/chromium/tools/gn/format_test_data/061.golden
+++ /dev/null
@@ -1,9 +0,0 @@
-action("generate_gl_bindings") {
- args = [
- "--header-paths=" + rebase_path("//third_party/khronos", root_build_dir) +
- ":" + rebase_path("//third_party/mesa/src/include", root_build_dir) +
- ":" + rebase_path("//ui/gl", root_build_dir) + ":" +
- rebase_path("//gpu", root_build_dir),
- rebase_path(gl_binding_output_dir, root_build_dir),
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/062.gn b/chromium/tools/gn/format_test_data/062.gn
deleted file mode 100644
index 8c4cc7d8423..00000000000
--- a/chromium/tools/gn/format_test_data/062.gn
+++ /dev/null
@@ -1,122 +0,0 @@
-# Sorting, making sure we don't detach comments.
-
-sources = []
-
-sources = ["x.cc"]
-
-sources = [
- "/a",
- "/b",
- "/c",
- # End of block.
-]
-
-sources += [
- # Start of block, separate.
-
- "c",
- "a",
- "b",
-]
-
-sources += [
- "z",
- "z2",
- # Attached comment.
- "y.h",
- "y.cc",
- "y.mm",
- "y.rc",
- "a"
-]
-
-sources += [
- "z",
- "z2",
-
- # Block comment.
-
- "y.h",
- "y.cc",
- "y.mm",
- "y.rc",
- "a"
-]
-
-sources += [
- "z",
- "z2",
-
- #
- # Multiline block comment.
- #
-
- "y.h",
- "y.cc",
- "y.mm",
- "y.rc",
- "a"
-]
-
-# With identifiers.
-sources += [
- "a",
- "b",
- "c",
- some_other_thing,
- abcd,
-]
-
-# With accessors.
-sources += [
- "a",
- wee[0],
- "b",
- invoker.stuff,
- "c",
-]
-
-# Various separated blocks.
-sources -= [
- # Fix this test to build on Windows.
- "focus_cycler_unittest.cc",
-
- # All tests for multiple displays: not supported on Windows Ash.
- "wm/drag_window_resizer_unittest.cc",
-
- # Accelerometer is only available on Chrome OS.
- "wm/maximize_mode/maximize_mode_controller_unittest.cc",
-
- # Can't resize on Windows Ash. http://crbug.com/165962
- "autoclick/autoclick_unittest.cc",
- "magnifier/magnification_controller_unittest.cc",
- # Attached 1.
- # Attached 2.
- "wm/workspace/workspace_window_resizer_unittest.cc",
- "sticky_keys/sticky_keys_overlay_unittest.cc",
- "system/tray/media_security/multi_profile_media_tray_item_unittest.cc",
- "virtual_keyboard_controller_unittest.cc",
-
- # Separated at end.
- "zzzzzzzzzzzzzz.cc",
-]
-
-sources += [
- "srtp/crypto/include/xfm.h",
-
- # sources
- "srtp/srtp/ekt.c",
- "srtp/srtp/srtp.c",
- "srtp/crypto/rng/prng.c",
- "srtp/crypto/rng/rand_source.c",
-]
-
-# Try "public" too. It should be treated the same.
-public = [
- # Let's sort
- "this", "into", "word", "salad",
-
- # But leave
- "these", "two"
- # alone!
-]
diff --git a/chromium/tools/gn/format_test_data/062.golden b/chromium/tools/gn/format_test_data/062.golden
deleted file mode 100644
index b55451011f7..00000000000
--- a/chromium/tools/gn/format_test_data/062.golden
+++ /dev/null
@@ -1,132 +0,0 @@
-# Sorting, making sure we don't detach comments.
-
-sources = []
-
-sources = [
- "x.cc",
-]
-
-sources = [
- "/a",
- "/b",
- "/c",
-
- # End of block.
-]
-
-sources += [
- # Start of block, separate.
-
- "a",
- "b",
- "c",
-]
-
-sources += [
- "a",
- "y.cc",
-
- # Attached comment.
- "y.h",
- "y.mm",
- "y.rc",
- "z",
- "z2",
-]
-
-sources += [
- "z",
- "z2",
-
- # Block comment.
-
- "a",
- "y.cc",
- "y.h",
- "y.mm",
- "y.rc",
-]
-
-sources += [
- "z",
- "z2",
-
- #
- # Multiline block comment.
- #
-
- "a",
- "y.cc",
- "y.h",
- "y.mm",
- "y.rc",
-]
-
-# With identifiers.
-sources += [
- "a",
- "b",
- "c",
- abcd,
- some_other_thing,
-]
-
-# With accessors.
-sources += [
- "a",
- "b",
- "c",
- invoker.stuff,
- wee[0],
-]
-
-# Various separated blocks.
-sources -= [
- # Fix this test to build on Windows.
- "focus_cycler_unittest.cc",
-
- # All tests for multiple displays: not supported on Windows Ash.
- "wm/drag_window_resizer_unittest.cc",
-
- # Accelerometer is only available on Chrome OS.
- "wm/maximize_mode/maximize_mode_controller_unittest.cc",
-
- # Can't resize on Windows Ash. http://crbug.com/165962
- "autoclick/autoclick_unittest.cc",
- "magnifier/magnification_controller_unittest.cc",
- "sticky_keys/sticky_keys_overlay_unittest.cc",
- "system/tray/media_security/multi_profile_media_tray_item_unittest.cc",
- "virtual_keyboard_controller_unittest.cc",
-
- # Attached 1.
- # Attached 2.
- "wm/workspace/workspace_window_resizer_unittest.cc",
-
- # Separated at end.
- "zzzzzzzzzzzzzz.cc",
-]
-
-sources += [
- "srtp/crypto/include/xfm.h",
-
- # sources
- "srtp/crypto/rng/prng.c",
- "srtp/crypto/rng/rand_source.c",
- "srtp/srtp/ekt.c",
- "srtp/srtp/srtp.c",
-]
-
-# Try "public" too. It should be treated the same.
-public = [
- # Let's sort
- "into",
- "salad",
- "this",
- "word",
-
- # But leave
- "these",
- "two",
-
- # alone!
-]
diff --git a/chromium/tools/gn/format_test_data/063.gn b/chromium/tools/gn/format_test_data/063.gn
deleted file mode 100644
index 9fd8211b692..00000000000
--- a/chromium/tools/gn/format_test_data/063.gn
+++ /dev/null
@@ -1,36 +0,0 @@
-source_set("test") {
- a = "a"
- b = "b"
- deps = [
- "//a",
- "//a/a",
- "//a/b",
- "//a:a",
- "//a:b",
- "//b",
- ":a",
- ":b",
- "a",
- "a/a",
- "a/b",
- "a:a",
- "a:b",
- "b",
- a,
- b,
- ]
-
- public_deps = []
- if (condition) {
- public_deps += [
- "//a",
- "//a/a",
- "//a:a",
- ":a",
- "a",
- "a/a",
- "a:a",
- a,
- ]
- }
-}
diff --git a/chromium/tools/gn/format_test_data/063.golden b/chromium/tools/gn/format_test_data/063.golden
deleted file mode 100644
index 3dc4bedfae7..00000000000
--- a/chromium/tools/gn/format_test_data/063.golden
+++ /dev/null
@@ -1,36 +0,0 @@
-source_set("test") {
- a = "a"
- b = "b"
- deps = [
- ":a",
- ":b",
- "a",
- "a:a",
- "a:b",
- "a/a",
- "a/b",
- "b",
- "//a",
- "//a:a",
- "//a:b",
- "//a/a",
- "//a/b",
- "//b",
- a,
- b,
- ]
-
- public_deps = []
- if (condition) {
- public_deps += [
- ":a",
- "a",
- "a:a",
- "a/a",
- "//a",
- "//a:a",
- "//a/a",
- a,
- ]
- }
-}
diff --git a/chromium/tools/gn/format_test_data/064.gn b/chromium/tools/gn/format_test_data/064.gn
deleted file mode 100644
index c1867250fe5..00000000000
--- a/chromium/tools/gn/format_test_data/064.gn
+++ /dev/null
@@ -1,3 +0,0 @@
-source_set("test") {
- deps = [ rebase_path(sdk_dep, ".", mojo_root) ]
-}
diff --git a/chromium/tools/gn/format_test_data/064.golden b/chromium/tools/gn/format_test_data/064.golden
deleted file mode 100644
index 3ff56f6490f..00000000000
--- a/chromium/tools/gn/format_test_data/064.golden
+++ /dev/null
@@ -1,5 +0,0 @@
-source_set("test") {
- deps = [
- rebase_path(sdk_dep, ".", mojo_root),
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/065.gn b/chromium/tools/gn/format_test_data/065.gn
deleted file mode 100644
index a4489092232..00000000000
--- a/chromium/tools/gn/format_test_data/065.gn
+++ /dev/null
@@ -1,4 +0,0 @@
-source_set("test") {
- some_target_name = ":some_target"
- deps = [ some_target_name, "//last_target", ":another_target" ]
-}
diff --git a/chromium/tools/gn/format_test_data/065.golden b/chromium/tools/gn/format_test_data/065.golden
deleted file mode 100644
index 5df85fda4df..00000000000
--- a/chromium/tools/gn/format_test_data/065.golden
+++ /dev/null
@@ -1,8 +0,0 @@
-source_set("test") {
- some_target_name = ":some_target"
- deps = [
- ":another_target",
- "//last_target",
- some_target_name,
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/066.gn b/chromium/tools/gn/format_test_data/066.gn
deleted file mode 100644
index c62eb2ae6ec..00000000000
--- a/chromium/tools/gn/format_test_data/066.gn
+++ /dev/null
@@ -1,30 +0,0 @@
-# Suppress sorting based on comment.
-
-# NOSORT
-sources = []
-
-# NOSORT
-sources = [
- "a",
-]
-
-# NOSORT
-sources += [
- "a",
-]
-
-# NOSORT
-sources = [
- "z",
- "z2",
- "a",
- "y.cc",
-]
-
-# NOSORT
-sources += [
- "z",
- "z2",
- "a",
- "y.cc",
-]
diff --git a/chromium/tools/gn/format_test_data/066.golden b/chromium/tools/gn/format_test_data/066.golden
deleted file mode 100644
index 45467b880f5..00000000000
--- a/chromium/tools/gn/format_test_data/066.golden
+++ /dev/null
@@ -1,28 +0,0 @@
-# Suppress sorting based on comment.
-
-# NOSORT
-sources = []
-
-# NOSORT
-sources = [
- "a",
-]
-
-# NOSORT
-sources += [ "a" ]
-
-# NOSORT
-sources = [
- "z",
- "z2",
- "a",
- "y.cc",
-]
-
-# NOSORT
-sources += [
- "z",
- "z2",
- "a",
- "y.cc",
-]
diff --git a/chromium/tools/gn/format_test_data/067.gn b/chromium/tools/gn/format_test_data/067.gn
deleted file mode 100644
index b3d5eaa6ce0..00000000000
--- a/chromium/tools/gn/format_test_data/067.gn
+++ /dev/null
@@ -1,8 +0,0 @@
-# Scope wrapping.
-
-myscope = {
-}
-myscope = { a = 1 }
-myscope = { a = 1 b = 2}
-# Comment
-SomeFunction({a=1}, "foo")
diff --git a/chromium/tools/gn/format_test_data/067.golden b/chromium/tools/gn/format_test_data/067.golden
deleted file mode 100644
index 9ce2fa77276..00000000000
--- a/chromium/tools/gn/format_test_data/067.golden
+++ /dev/null
@@ -1,17 +0,0 @@
-# Scope wrapping.
-
-myscope = {
-}
-myscope = {
- a = 1
-}
-myscope = {
- a = 1
- b = 2
-}
-
-# Comment
-SomeFunction({
- a = 1
- },
- "foo")
diff --git a/chromium/tools/gn/format_test_data/068.gn b/chromium/tools/gn/format_test_data/068.gn
deleted file mode 100644
index 7fb8e1b00d4..00000000000
--- a/chromium/tools/gn/format_test_data/068.gn
+++ /dev/null
@@ -1,3 +0,0 @@
-# Initial comment
-
-# Comment that should be separate, no subsequent content in file.
diff --git a/chromium/tools/gn/format_test_data/068.golden b/chromium/tools/gn/format_test_data/068.golden
deleted file mode 100644
index 7fb8e1b00d4..00000000000
--- a/chromium/tools/gn/format_test_data/068.golden
+++ /dev/null
@@ -1,3 +0,0 @@
-# Initial comment
-
-# Comment that should be separate, no subsequent content in file.
diff --git a/chromium/tools/gn/format_test_data/069.gn b/chromium/tools/gn/format_test_data/069.gn
deleted file mode 100644
index 200b3131272..00000000000
--- a/chromium/tools/gn/format_test_data/069.gn
+++ /dev/null
@@ -1,3 +0,0 @@
-if (true) {
- configs -= [ "//third_party/mini_chromium/mini_chromium/build:Wexit_time_destructors", ]
-}
diff --git a/chromium/tools/gn/format_test_data/069.golden b/chromium/tools/gn/format_test_data/069.golden
deleted file mode 100644
index 64d4acce040..00000000000
--- a/chromium/tools/gn/format_test_data/069.golden
+++ /dev/null
@@ -1,5 +0,0 @@
-if (true) {
- configs -= [
- "//third_party/mini_chromium/mini_chromium/build:Wexit_time_destructors",
- ]
-}
diff --git a/chromium/tools/gn/format_test_data/070.gn b/chromium/tools/gn/format_test_data/070.gn
deleted file mode 100644
index 09d80d2b02e..00000000000
--- a/chromium/tools/gn/format_test_data/070.gn
+++ /dev/null
@@ -1,15 +0,0 @@
-multiple = [
- {
- name = "elements_test"
- },
- {
- name = "eapol_crypto_test"
- },
- ]
-
-
-single = [
- {
- name = "elements_test"
- },
- ]
diff --git a/chromium/tools/gn/format_test_data/070.golden b/chromium/tools/gn/format_test_data/070.golden
deleted file mode 100644
index 0997aa47743..00000000000
--- a/chromium/tools/gn/format_test_data/070.golden
+++ /dev/null
@@ -1,14 +0,0 @@
-multiple = [
- {
- name = "elements_test"
- },
- {
- name = "eapol_crypto_test"
- },
-]
-
-single = [
- {
- name = "elements_test"
- },
-]
diff --git a/chromium/tools/gn/function_exec_script.cc b/chromium/tools/gn/function_exec_script.cc
deleted file mode 100644
index 0f6397c95f1..00000000000
--- a/chromium/tools/gn/function_exec_script.cc
+++ /dev/null
@@ -1,271 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "tools/gn/err.h"
-#include "tools/gn/exec_process.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/input_conversion.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/trace.h"
-#include "tools/gn/value.h"
-
-namespace functions {
-
-namespace {
-
-bool CheckExecScriptPermissions(const BuildSettings* build_settings,
- const FunctionCallNode* function,
- Err* err) {
- const std::set<SourceFile>* whitelist =
- build_settings->exec_script_whitelist();
- if (!whitelist)
- return true; // No whitelist specified, don't check.
-
- LocationRange function_range = function->GetRange();
- if (!function_range.begin().file())
- return true; // No file, might be some internal thing, implicitly pass.
-
- if (whitelist->find(function_range.begin().file()->name()) !=
- whitelist->end())
- return true; // Whitelisted, this is OK.
-
- // Disallowed case.
- *err = Err(function, "Disallowed exec_script call.",
- "The use of exec_script use is restricted in this build. exec_script\n"
- "is discouraged because it can slow down the GN run and is easily\n"
- "abused.\n"
- "\n"
- "Generally nontrivial work should be done as build steps rather than\n"
- "when GN is run. For example, if you need to compute a nontrivial\n"
- "preprocessor define, it will be better to have an action target\n"
- "generate a header containing the define rather than blocking the GN\n"
- "run to compute the value.\n"
- "\n"
- "The allowed callers of exec_script is maintained in the \"//.gn\" file\n"
- "if you need to modify the whitelist.");
- return false;
-}
-
-} // namespace
-
-const char kExecScript[] = "exec_script";
-const char kExecScript_HelpShort[] =
- "exec_script: Synchronously run a script and return the output.";
-const char kExecScript_Help[] =
- R"(exec_script: Synchronously run a script and return the output.
-
- exec_script(filename,
- arguments = [],
- input_conversion = "",
- file_dependencies = [])
-
- Runs the given script, returning the stdout of the script. The build
- generation will fail if the script does not exist or returns a nonzero exit
- code.
-
- The current directory when executing the script will be the root build
- directory. If you are passing file names, you will want to use the
- rebase_path() function to make file names relative to this path (see "gn help
- rebase_path").
-
-Arguments:
-
- filename:
- File name of python script to execute. Non-absolute names will be treated
- as relative to the current build file.
-
- arguments:
- A list of strings to be passed to the script as arguments. May be
- unspecified or the empty list which means no arguments.
-
- input_conversion:
- Controls how the file is read and parsed. See "gn help input_conversion".
-
- If unspecified, defaults to the empty string which causes the script
- result to be discarded. exec script will return None.
-
- dependencies:
- (Optional) A list of files that this script reads or otherwise depends
- on. These dependencies will be added to the build result such that if any
- of them change, the build will be regenerated and the script will be
- re-run.
-
- The script itself will be an implicit dependency so you do not need to
- list it.
-
-Example
-
- all_lines = exec_script(
- "myscript.py", [some_input], "list lines",
- [ rebase_path("data_file.txt", root_build_dir) ])
-
- # This example just calls the script with no arguments and discards the
- # result.
- exec_script("//foo/bar/myscript.py")
-)";
-
-class ExecScriptScopedAllowBaseSyncPrimitives
- : public base::ScopedAllowBaseSyncPrimitives {};
-
-Value RunExecScript(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- if (args.size() < 1 || args.size() > 4) {
- *err = Err(function->function(), "Wrong number of arguments to exec_script",
- "I expected between one and four arguments.");
- return Value();
- }
-
- const Settings* settings = scope->settings();
- const BuildSettings* build_settings = settings->build_settings();
- const SourceDir& cur_dir = scope->GetSourceDir();
-
- if (!CheckExecScriptPermissions(build_settings, function, err))
- return Value();
-
- // Find the python script to run.
- std::string script_source_path = cur_dir.ResolveRelativeAs(
- true, args[0], err,
- scope->settings()->build_settings()->root_path_utf8());
- if (err->has_error())
- return Value();
- base::FilePath script_path =
- build_settings->GetFullPath(script_source_path, true);
- if (!build_settings->secondary_source_path().empty() &&
- !base::PathExists(script_path)) {
- // Fall back to secondary source root when the file doesn't exist.
- script_path =
- build_settings->GetFullPathSecondary(script_source_path, true);
- }
-
- ScopedTrace trace(TraceItem::TRACE_SCRIPT_EXECUTE, script_source_path);
- trace.SetToolchain(settings->toolchain_label());
-
- // Add all dependencies of this script, including the script itself, to the
- // build deps.
- g_scheduler->AddGenDependency(script_path);
- if (args.size() == 4) {
- const Value& deps_value = args[3];
- if (!deps_value.VerifyTypeIs(Value::LIST, err))
- return Value();
-
- for (const auto& dep : deps_value.list_value()) {
- if (!dep.VerifyTypeIs(Value::STRING, err))
- return Value();
- g_scheduler->AddGenDependency(build_settings->GetFullPath(
- cur_dir.ResolveRelativeAs(
- true, dep, err,
- scope->settings()->build_settings()->root_path_utf8()),
- true));
- if (err->has_error())
- return Value();
- }
- }
-
- // Make the command line.
- const base::FilePath& python_path = build_settings->python_path();
- base::CommandLine cmdline(python_path);
-
- // CommandLine tries to interpret arguments by default. Passing "--" disables
- // this for everything following the "--", so pass this as the very first
- // thing to python. Python ignores a -- before the .py file, and this makes
- // CommandLine let through arguments without modifying them.
- cmdline.AppendArg("--");
-
- cmdline.AppendArgPath(script_path);
-
- if (args.size() >= 2) {
- // Optional command-line arguments to the script.
- const Value& script_args = args[1];
- if (!script_args.VerifyTypeIs(Value::LIST, err))
- return Value();
- for (const auto& arg : script_args.list_value()) {
- if (!arg.VerifyTypeIs(Value::STRING, err))
- return Value();
- cmdline.AppendArg(arg.string_value());
- }
- }
-
- // Log command line for debugging help.
- trace.SetCommandLine(cmdline);
- base::TimeTicks begin_exec;
- if (g_scheduler->verbose_logging()) {
-#if defined(OS_WIN)
- g_scheduler->Log("Pythoning",
- base::UTF16ToUTF8(cmdline.GetCommandLineString()));
-#else
- g_scheduler->Log("Pythoning", cmdline.GetCommandLineString());
-#endif
- begin_exec = base::TimeTicks::Now();
- }
-
- base::FilePath startup_dir =
- build_settings->GetFullPath(build_settings->build_dir());
- // The first time a build is run, no targets will have been written so the
- // build output directory won't exist. We need to make sure it does before
- // running any scripts with this as its startup directory, although it will
- // be relatively rare that the directory won't exist by the time we get here.
- //
- // If this shows up on benchmarks, we can cache whether we've done this
- // or not and skip creating the directory.
- base::CreateDirectory(startup_dir);
-
- // Execute the process.
- // TODO(brettw) set the environment block.
- std::string output;
- std::string stderr_output;
- int exit_code = 0;
- {
- ExecScriptScopedAllowBaseSyncPrimitives allow_base_sync_primitives;
- if (!internal::ExecProcess(cmdline, startup_dir, &output, &stderr_output,
- &exit_code)) {
- *err = Err(
- function->function(), "Could not execute python.",
- "I was trying to execute \"" + FilePathToUTF8(python_path) + "\".");
- return Value();
- }
- }
- if (g_scheduler->verbose_logging()) {
- g_scheduler->Log(
- "Pythoning",
- script_source_path + " took " +
- base::Int64ToString(
- (base::TimeTicks::Now() - begin_exec).InMilliseconds()) +
- "ms");
- }
-
- if (exit_code != 0) {
- std::string msg = "Current dir: " + FilePathToUTF8(startup_dir) +
- "\nCommand: " + FilePathToUTF8(cmdline.GetCommandLineString()) +
- "\nReturned " + base::IntToString(exit_code);
- if (!output.empty())
- msg += " and printed out:\n\n" + output;
- else
- msg += ".";
- if (!stderr_output.empty())
- msg += "\nstderr:\n\n" + stderr_output;
-
- *err = Err(function->function(), "Script returned non-zero exit code.",
- msg);
- return Value();
- }
-
- // Default to None value for the input conversion if unspecified.
- return ConvertInputToValue(scope->settings(), output, function,
- args.size() >= 3 ? args[2] : Value(), err);
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/function_foreach.cc b/chromium/tools/gn/function_foreach.cc
deleted file mode 100644
index b0af694bc30..00000000000
--- a/chromium/tools/gn/function_foreach.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/err.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-
-namespace functions {
-
-const char kForEach[] = "foreach";
-const char kForEach_HelpShort[] =
- "foreach: Iterate over a list.";
-const char kForEach_Help[] =
- R"(foreach: Iterate over a list.
-
- foreach(<loop_var>, <list>) {
- <loop contents>
- }
-
- Executes the loop contents block over each item in the list, assigning the
- loop_var to each item in sequence. The <loop_var> will be a copy so assigning
- to it will not mutate the list. The loop will iterate over a copy of <list>
- so mutating it inside the loop will not affect iteration.
-
- The block does not introduce a new scope, so that variable assignments inside
- the loop will be visible once the loop terminates.
-
- The loop variable will temporarily shadow any existing variables with the
- same name for the duration of the loop. After the loop terminates the loop
- variable will no longer be in scope, and the previous value (if any) will be
- restored.
-
-Example
-
- mylist = [ "a", "b", "c" ]
- foreach(i, mylist) {
- print(i)
- }
-
- Prints:
- a
- b
- c
-)";
-
-Value RunForEach(Scope* scope,
- const FunctionCallNode* function,
- const ListNode* args_list,
- Err* err) {
- const auto& args_vector = args_list->contents();
- if (args_vector.size() != 2) {
- *err = Err(function, "Wrong number of arguments to foreach().",
- "Expecting exactly two.");
- return Value();
- }
-
- // Extract the loop variable.
- const IdentifierNode* identifier = args_vector[0]->AsIdentifier();
- if (!identifier) {
- *err =
- Err(args_vector[0].get(), "Expected an identifier for the loop var.");
- return Value();
- }
- base::StringPiece loop_var(identifier->value().value());
-
- // Extract the list to iterate over. Always copy in case the code changes
- // the list variable inside the loop.
- Value list_value = args_vector[1]->Execute(scope, err);
- if (err->has_error())
- return Value();
- list_value.VerifyTypeIs(Value::Type::LIST, err);
- if (err->has_error())
- return Value();
- const std::vector<Value>& list = list_value.list_value();
-
- // Block to execute.
- const BlockNode* block = function->block();
- if (!block) {
- *err = Err(function, "Expected { after foreach.");
- return Value();
- }
-
- // If the loop variable was previously defined in this scope, save it so we
- // can put it back after the loop is done.
- const Value* old_loop_value_ptr = scope->GetValue(loop_var);
- Value old_loop_value;
- if (old_loop_value_ptr)
- old_loop_value = *old_loop_value_ptr;
-
- for (const auto& cur : list) {
- scope->SetValue(loop_var, cur, function);
- block->Execute(scope, err);
- if (err->has_error())
- return Value();
- }
-
- // Put back loop var.
- if (old_loop_value_ptr) {
- // Put back old value. Use the copy we made, rather than use the pointer,
- // which will probably point to the new value now in the scope.
- scope->SetValue(loop_var, std::move(old_loop_value),
- old_loop_value.origin());
- } else {
- // Loop variable was undefined before loop, delete it.
- scope->RemoveIdentifier(loop_var);
- }
-
- return Value();
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/function_foreach_unittest.cc b/chromium/tools/gn/function_foreach_unittest.cc
deleted file mode 100644
index 3886724b7b8..00000000000
--- a/chromium/tools/gn/function_foreach_unittest.cc
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/test_with_scope.h"
-
-TEST(FunctionForeach, CollisionOnLoopVar) {
- TestWithScope setup;
- TestParseInput input(
- "a = 5\n"
- "i = 6\n"
- "foreach(i, [1, 2, 3]) {\n" // Use same loop var name previously defined.
- " print(\"$a $i\")\n"
- " a = a + 1\n" // Test for side effects inside loop.
- "}\n"
- "print(\"$a $i\")"); // Make sure that i goes back to original value.
- ASSERT_FALSE(input.has_error());
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- EXPECT_EQ("5 1\n6 2\n7 3\n8 6\n", setup.print_output());
-}
-
-TEST(FunctionForeach, UniqueLoopVar) {
- TestWithScope setup;
- TestParseInput input_good(
- "foreach(i, [1, 2, 3]) {\n"
- " print(i)\n"
- "}\n");
- ASSERT_FALSE(input_good.has_error());
-
- Err err;
- input_good.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- EXPECT_EQ("1\n2\n3\n", setup.print_output());
- setup.print_output().clear();
-
- // Same thing but try to use the loop var after loop is done. It should be
- // undefined and throw an error.
- TestParseInput input_bad(
- "foreach(i, [1, 2, 3]) {\n"
- " print(i)\n"
- "}\n"
- "print(i)");
- ASSERT_FALSE(input_bad.has_error()); // Should parse OK.
-
- input_bad.parsed()->Execute(setup.scope(), &err);
- ASSERT_TRUE(err.has_error()); // Shouldn't actually run.
-}
-
-// Checks that the identifier used as the list is marked as "used".
-TEST(FunctionForeach, MarksIdentAsUsed) {
- TestWithScope setup;
- TestParseInput input_good(
- "a = [1, 2]\n"
- "foreach(i, a) {\n"
- " print(i)\n"
- "}\n");
- ASSERT_FALSE(input_good.has_error());
-
- Err err;
- input_good.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- EXPECT_EQ("1\n2\n", setup.print_output());
- setup.print_output().clear();
-
- // Check for unused vars.
- EXPECT_TRUE(setup.scope()->CheckForUnusedVars(&err));
- EXPECT_FALSE(err.has_error());
-}
-
-// Checks that the list can be modified during iteration without crashing.
-TEST(FunctionForeach, ListModification) {
- TestWithScope setup;
- TestParseInput input_grow(
- "a = [1, 2]\n"
- "foreach(i, a) {\n"
- " print(i)\n"
- " if (i <= 8) {\n"
- " a += [ i + 2 ]\n"
- " }\n"
- "}\n"
- "print(a)");
- ASSERT_FALSE(input_grow.has_error());
-
- Err err;
- input_grow.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- // The result of the loop should have been unaffected by the mutations of
- // the list variable inside the loop, but the modifications made to it
- // should have been persisted.
- EXPECT_EQ("1\n2\n[1, 2, 3, 4]\n", setup.print_output());
- setup.print_output().clear();
-}
diff --git a/chromium/tools/gn/function_forward_variables_from.cc b/chromium/tools/gn/function_forward_variables_from.cc
deleted file mode 100644
index 93531e49f4e..00000000000
--- a/chromium/tools/gn/function_forward_variables_from.cc
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/err.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-
-namespace functions {
-
-namespace {
-
-void ForwardAllValues(const FunctionCallNode* function,
- Scope* source,
- Scope* dest,
- const std::set<std::string>& exclusion_set,
- Err* err) {
- Scope::MergeOptions options;
- // This function needs to clobber existing for it to be useful. It will be
- // called in a template to forward all values, but there will be some
- // default stuff like configs set up in both scopes, so it would always
- // fail if it didn't clobber.
- options.clobber_existing = true;
- options.skip_private_vars = true;
- options.mark_dest_used = false;
- options.excluded_values = exclusion_set;
- source->NonRecursiveMergeTo(dest, options, function,
- "source scope", err);
- source->MarkAllUsed();
-}
-
-void ForwardValuesFromList(Scope* source,
- Scope* dest,
- const std::vector<Value>& list,
- const std::set<std::string>& exclusion_set,
- Err* err) {
- for (const Value& cur : list) {
- if (!cur.VerifyTypeIs(Value::STRING, err))
- return;
- if (exclusion_set.find(cur.string_value()) != exclusion_set.end())
- continue;
- const Value* value = source->GetValue(cur.string_value(), true);
- if (value) {
- // Use the storage key for the original value rather than the string in
- // "cur" because "cur" is a temporary that will be deleted, and Scopes
- // expect a persistent StringPiece (it won't copy). Not doing this will
- // lead the scope's key to point to invalid memory after this returns.
- base::StringPiece storage_key = source->GetStorageKey(cur.string_value());
- if (storage_key.empty()) {
- // Programmatic value, don't allow copying.
- *err = Err(cur, "This value can't be forwarded.",
- "The variable \"" + cur.string_value() + "\" is a built-in.");
- return;
- }
-
- // Don't allow clobbering existing values.
- const Value* existing_value = dest->GetValue(storage_key);
- if (existing_value) {
- *err = Err(cur, "Clobbering existing value.",
- "The current scope already defines a value \"" +
- cur.string_value() + "\".\nforward_variables_from() won't clobber "
- "existing values. If you want to\nmerge lists, you'll need to "
- "do this explicitly.");
- err->AppendSubErr(Err(*existing_value, "value being clobbered."));
- return;
- }
-
- // Keep the origin information from the original value. The normal
- // usage is for this to be used in a template, and if there's an error,
- // the user expects to see the line where they set the variable
- // blamed, rather than a template call to forward_variables_from().
- dest->SetValue(storage_key, *value, value->origin());
- }
- }
-}
-
-} // namespace
-
-const char kForwardVariablesFrom[] = "forward_variables_from";
-const char kForwardVariablesFrom_HelpShort[] =
- "forward_variables_from: Copies variables from a different scope.";
-const char kForwardVariablesFrom_Help[] =
- R"(forward_variables_from: Copies variables from a different scope.
-
- forward_variables_from(from_scope, variable_list_or_star,
- variable_to_not_forward_list = [])
-
- Copies the given variables from the given scope to the local scope if they
- exist. This is normally used in the context of templates to use the values of
- variables defined in the template invocation to a template-defined target.
-
- The variables in the given variable_list will be copied if they exist in the
- given scope or any enclosing scope. If they do not exist, nothing will happen
- and they be left undefined in the current scope.
-
- As a special case, if the variable_list is a string with the value of "*",
- all variables from the given scope will be copied. "*" only copies variables
- set directly on the from_scope, not enclosing ones. Otherwise it would
- duplicate all global variables.
-
- When an explicit list of variables is supplied, if the variable exists in the
- current (destination) scope already, an error will be thrown. If "*" is
- specified, variables in the current scope will be clobbered (the latter is
- important because most targets have an implicit configs list, which means it
- wouldn't work at all if it didn't clobber).
-
- The sources assignment filter (see "gn help set_sources_assignment_filter")
- is never applied by this function. It's assumed than any desired filtering
- was already done when sources was set on the from_scope.
-
- If variables_to_not_forward_list is non-empty, then it must contains a list
- of variable names that will not be forwarded. This is mostly useful when
- variable_list_or_star has a value of "*".
-
-Examples
-
- # This is a common action template. It would invoke a script with some given
- # parameters, and wants to use the various types of deps and the visibility
- # from the invoker if it's defined. It also injects an additional dependency
- # to all targets.
- template("my_test") {
- action(target_name) {
- forward_variables_from(invoker, [ "data_deps", "deps",
- "public_deps", "visibility" "
- "])
- # Add our test code to the dependencies.
- # "deps" may or may not be defined at this point.
- if (defined(deps)) {
- deps += [ "//tools/doom_melon" ]
- } else {
- deps = [ "//tools/doom_melon" ]
- }
- }
- }
-
- # This is a template around either a target whose type depends on a global
- # variable. It forwards all values from the invoker.
- template("my_wrapper") {
- target(my_wrapper_target_type, target_name) {
- forward_variables_from(invoker, "*")
- }
- }
-
- # A template that wraps another. It adds behavior based on one
- # variable, and forwards all others to the nested target.
- template("my_ios_test_app") {
- ios_test_app(target_name) {
- forward_variables_from(invoker, "*", ["test_bundle_name"])
- if (!defined(extra_substitutions)) {
- extra_substitutions = []
- }
- extra_substitutions += [ "BUNDLE_ID_TEST_NAME=$test_bundle_name" ]
- }
- }
-)";
-
-// This function takes a ListNode rather than a resolved vector of values
-// both avoid copying the potentially-large source scope, and so the variables
-// in the source scope can be marked as used.
-Value RunForwardVariablesFrom(Scope* scope,
- const FunctionCallNode* function,
- const ListNode* args_list,
- Err* err) {
- const auto& args_vector = args_list->contents();
- if (args_vector.size() != 2 && args_vector.size() != 3) {
- *err = Err(function, "Wrong number of arguments.",
- "Expecting two or three arguments.");
- return Value();
- }
-
- Value* value = nullptr; // Value to use, may point to result_value.
- Value result_value; // Storage for the "evaluate" case.
- const IdentifierNode* identifier = args_vector[0]->AsIdentifier();
- if (identifier) {
- // Optimize the common case where the input scope is an identifier. This
- // prevents a copy of a potentially large Scope object.
- value = scope->GetMutableValue(identifier->value().value(),
- Scope::SEARCH_NESTED, true);
- if (!value) {
- *err = Err(identifier, "Undefined identifier.");
- return Value();
- }
- } else {
- // Non-optimized case, just evaluate the argument.
- result_value = args_vector[0]->Execute(scope, err);
- if (err->has_error())
- return Value();
- value = &result_value;
- }
-
- // Extract the source scope.
- if (!value->VerifyTypeIs(Value::SCOPE, err))
- return Value();
- Scope* source = value->scope_value();
-
- // Extract the exclusion list if defined.
- std::set<std::string> exclusion_set;
- if (args_vector.size() == 3) {
- Value exclusion_value = args_vector[2]->Execute(scope, err);
- if (err->has_error())
- return Value();
-
- if (exclusion_value.type() != Value::LIST) {
- *err = Err(exclusion_value, "Not a valid list of variables to exclude.",
- "Expecting a list of strings.");
- return Value();
- }
-
- for (const Value& cur : exclusion_value.list_value()) {
- if (!cur.VerifyTypeIs(Value::STRING, err))
- return Value();
-
- exclusion_set.insert(cur.string_value());
- }
- }
-
- // Extract the list. If all_values is not set, the what_value will be a list.
- Value what_value = args_vector[1]->Execute(scope, err);
- if (err->has_error())
- return Value();
- if (what_value.type() == Value::STRING) {
- if (what_value.string_value() == "*") {
- ForwardAllValues(function, source, scope, exclusion_set, err);
- return Value();
- }
- } else {
- if (what_value.type() == Value::LIST) {
- ForwardValuesFromList(source, scope, what_value.list_value(),
- exclusion_set, err);
- return Value();
- }
- }
-
- // Not the right type of argument.
- *err = Err(what_value, "Not a valid list of variables to copy.",
- "Expecting either the string \"*\" or a list of strings.");
- return Value();
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/function_forward_variables_from_unittest.cc b/chromium/tools/gn/function_forward_variables_from_unittest.cc
deleted file mode 100644
index 3d697886233..00000000000
--- a/chromium/tools/gn/function_forward_variables_from_unittest.cc
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/test_with_scheduler.h"
-#include "tools/gn/test_with_scope.h"
-
-using FunctionForwardVariablesFromTest = TestWithScheduler;
-
-TEST_F(FunctionForwardVariablesFromTest, List) {
- Err err;
- std::string program =
- "template(\"a\") {\n"
- " forward_variables_from(invoker, [\"x\", \"y\", \"z\"])\n"
- " assert(!defined(z))\n" // "z" should still be undefined.
- " print(\"$target_name, $x, $y\")\n"
- "}\n"
- "a(\"target\") {\n"
- " x = 1\n"
- " y = 2\n"
- "}\n";
-
- {
- TestWithScope setup;
-
- // Defines a template and copy the two x and y, and z values out.
- TestParseInput input(program);
- ASSERT_FALSE(input.has_error());
-
- input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- EXPECT_EQ("target, 1, 2\n", setup.print_output());
- setup.print_output().clear();
- }
-
- {
- TestWithScope setup;
-
- // Test that the same input but forwarding a variable with the name of
- // something in the given scope throws an error rather than clobbering it.
- // This uses the same known-good program as before, but adds another
- // variable in the scope before it.
- TestParseInput clobber("x = 1\n" + program);
- ASSERT_FALSE(clobber.has_error());
-
- clobber.parsed()->Execute(setup.scope(), &err);
- ASSERT_TRUE(err.has_error()); // Should thow a clobber error.
- EXPECT_EQ("Clobbering existing value.", err.message());
- }
-}
-
-TEST_F(FunctionForwardVariablesFromTest, LiteralList) {
- TestWithScope setup;
-
- // Forwards all variables from a literal scope into another scope definition.
- TestParseInput input(
- "a = {\n"
- " forward_variables_from({x = 1 y = 2}, \"*\")\n"
- " z = 3\n"
- "}\n"
- "print(\"${a.x} ${a.y} ${a.z}\")\n");
-
- ASSERT_FALSE(input.has_error());
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- EXPECT_EQ("1 2 3\n", setup.print_output());
- setup.print_output().clear();
-}
-
-TEST_F(FunctionForwardVariablesFromTest, ListWithExclusion) {
- TestWithScope setup;
-
- // Defines a template and copy the two x and y, and z values out.
- TestParseInput input(
- "template(\"a\") {\n"
- " forward_variables_from(invoker, [\"x\", \"y\", \"z\"], [\"z\"])\n"
- " assert(!defined(z))\n" // "z" should still be undefined.
- " print(\"$target_name, $x, $y\")\n"
- "}\n"
- "a(\"target\") {\n"
- " x = 1\n"
- " y = 2\n"
- " z = 3\n"
- " print(\"$z\")\n"
- "}\n");
-
- ASSERT_FALSE(input.has_error());
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- EXPECT_EQ("3\ntarget, 1, 2\n", setup.print_output());
- setup.print_output().clear();
-}
-
-TEST_F(FunctionForwardVariablesFromTest, ErrorCases) {
- TestWithScope setup;
-
- // Type check the source scope.
- TestParseInput invalid_source(
- "template(\"a\") {\n"
- " forward_variables_from(42, [\"x\"])\n"
- " print(\"$target_name\")\n" // Prevent unused var error.
- "}\n"
- "a(\"target\") {\n"
- "}\n");
- ASSERT_FALSE(invalid_source.has_error());
- Err err;
- invalid_source.parsed()->Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
- EXPECT_EQ("This is not a scope.", err.message());
-
- // Type check the list. We need to use a new template name each time since
- // all of these invocations are executing in sequence in the same scope.
- TestParseInput invalid_list(
- "template(\"b\") {\n"
- " forward_variables_from(invoker, 42)\n"
- " print(\"$target_name\")\n"
- "}\n"
- "b(\"target\") {\n"
- "}\n");
- ASSERT_FALSE(invalid_list.has_error());
- err = Err();
- invalid_list.parsed()->Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
- EXPECT_EQ("Not a valid list of variables to copy.", err.message());
-
- // Type check the exclusion list.
- TestParseInput invalid_exclusion_list(
- "template(\"c\") {\n"
- " forward_variables_from(invoker, \"*\", 42)\n"
- " print(\"$target_name\")\n"
- "}\n"
- "c(\"target\") {\n"
- "}\n");
- ASSERT_FALSE(invalid_exclusion_list.has_error());
- err = Err();
- invalid_exclusion_list.parsed()->Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
- EXPECT_EQ("Not a valid list of variables to exclude.", err.message());
-
- // Programmatic values should error.
- TestParseInput prog(
- "template(\"d\") {\n"
- " forward_variables_from(invoker, [\"root_out_dir\"])\n"
- " print(\"$target_name\")\n"
- "}\n"
- "d(\"target\") {\n"
- "}\n");
- ASSERT_FALSE(prog.has_error());
- err = Err();
- prog.parsed()->Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
- EXPECT_EQ("This value can't be forwarded.", err.message());
-
- // Not enough arguments.
- TestParseInput not_enough_arguments(
- "template(\"e\") {\n"
- " forward_variables_from(invoker)\n"
- " print(\"$target_name\")\n"
- "}\n"
- "e(\"target\") {\n"
- "}\n");
- ASSERT_FALSE(not_enough_arguments.has_error());
- err = Err();
- not_enough_arguments.parsed()->Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
- EXPECT_EQ("Wrong number of arguments.", err.message());
-
- // Too many arguments.
- TestParseInput too_many_arguments(
- "template(\"f\") {\n"
- " forward_variables_from(invoker, \"*\", [], [])\n"
- " print(\"$target_name\")\n"
- "}\n"
- "f(\"target\") {\n"
- "}\n");
- ASSERT_FALSE(too_many_arguments.has_error());
- err = Err();
- too_many_arguments.parsed()->Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
- EXPECT_EQ("Wrong number of arguments.", err.message());
-}
-
-TEST_F(FunctionForwardVariablesFromTest, Star) {
- TestWithScope setup;
-
- // Defines a template and copy the two x and y values out. The "*" behavior
- // should clobber existing variables with the same name.
- TestParseInput input(
- "template(\"a\") {\n"
- " x = 1000000\n" // Should be clobbered.
- " forward_variables_from(invoker, \"*\")\n"
- " print(\"$target_name, $x, $y\")\n"
- "}\n"
- "a(\"target\") {\n"
- " x = 1\n"
- " y = 2\n"
- "}\n");
-
- ASSERT_FALSE(input.has_error());
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- EXPECT_EQ("target, 1, 2\n", setup.print_output());
- setup.print_output().clear();
-}
-
-TEST_F(FunctionForwardVariablesFromTest, StarWithExclusion) {
- TestWithScope setup;
-
- // Defines a template and copy all values except z value. The "*" behavior
- // should clobber existing variables with the same name.
- TestParseInput input(
- "template(\"a\") {\n"
- " x = 1000000\n" // Should be clobbered.
- " forward_variables_from(invoker, \"*\", [\"z\"])\n"
- " print(\"$target_name, $x, $y\")\n"
- "}\n"
- "a(\"target\") {\n"
- " x = 1\n"
- " y = 2\n"
- " z = 3\n"
- " print(\"$z\")\n"
- "}\n");
-
- ASSERT_FALSE(input.has_error());
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- EXPECT_EQ("3\ntarget, 1, 2\n", setup.print_output());
- setup.print_output().clear();
-}
diff --git a/chromium/tools/gn/function_get_label_info.cc b/chromium/tools/gn/function_get_label_info.cc
deleted file mode 100644
index a67a3719921..00000000000
--- a/chromium/tools/gn/function_get_label_info.cc
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/label.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/value.h"
-
-namespace functions {
-
-const char kGetLabelInfo[] = "get_label_info";
-const char kGetLabelInfo_HelpShort[] =
- "get_label_info: Get an attribute from a target's label.";
-const char kGetLabelInfo_Help[] =
- R"*(get_label_info: Get an attribute from a target's label.
-
- get_label_info(target_label, what)
-
- Given the label of a target, returns some attribute of that target. The
- target need not have been previously defined in the same file, since none of
- the attributes depend on the actual target definition, only the label itself.
-
- See also "gn help get_target_outputs".
-
-Possible values for the "what" parameter
-
- "name"
- The short name of the target. This will match the value of the
- "target_name" variable inside that target's declaration. For the label
- "//foo/bar:baz" this will return "baz".
-
- "dir"
- The directory containing the target's definition, with no slash at the
- end. For the label "//foo/bar:baz" this will return "//foo/bar".
-
- "target_gen_dir"
- The generated file directory for the target. This will match the value of
- the "target_gen_dir" variable when inside that target's declaration.
-
- "root_gen_dir"
- The root of the generated file tree for the target. This will match the
- value of the "root_gen_dir" variable when inside that target's
- declaration.
-
- "target_out_dir
- The output directory for the target. This will match the value of the
- "target_out_dir" variable when inside that target's declaration.
-
- "root_out_dir"
- The root of the output file tree for the target. This will match the
- value of the "root_out_dir" variable when inside that target's
- declaration.
-
- "label_no_toolchain"
- The fully qualified version of this label, not including the toolchain.
- For the input ":bar" it might return "//foo:bar".
-
- "label_with_toolchain"
- The fully qualified version of this label, including the toolchain. For
- the input ":bar" it might return "//foo:bar(//toolchain:x64)".
-
- "toolchain"
- The label of the toolchain. This will match the value of the
- "current_toolchain" variable when inside that target's declaration.
-
-Examples
-
- get_label_info(":foo", "name")
- # Returns string "foo".
-
- get_label_info("//foo/bar:baz", "target_gen_dir")
- # Returns string "//out/Debug/gen/foo/bar".
-)*";
-
-Value RunGetLabelInfo(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- if (args.size() != 2) {
- *err = Err(function, "Expected two arguments.");
- return Value();
- }
-
- // Resolve the requested label.
- Label label = Label::Resolve(scope->GetSourceDir(),
- ToolchainLabelForScope(scope), args[0], err);
- if (label.is_null())
- return Value();
-
- // Extract the "what" parameter.
- if (!args[1].VerifyTypeIs(Value::STRING, err))
- return Value();
- const std::string& what = args[1].string_value();
-
- Value result(function, Value::STRING);
- if (what == "name") {
- result.string_value() = label.name();
-
- } else if (what == "dir") {
- result.string_value() = DirectoryWithNoLastSlash(label.dir());
-
- } else if (what == "target_gen_dir") {
- result.string_value() = DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir(
- BuildDirContext(scope, label.GetToolchainLabel()),
- label.dir(),
- BuildDirType::GEN));
-
- } else if (what == "root_gen_dir") {
- result.string_value() = DirectoryWithNoLastSlash(GetBuildDirAsSourceDir(
- BuildDirContext(scope, label.GetToolchainLabel()), BuildDirType::GEN));
-
- } else if (what == "target_out_dir") {
- result.string_value() = DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir(
- BuildDirContext(scope, label.GetToolchainLabel()),
- label.dir(),
- BuildDirType::OBJ));
-
- } else if (what == "root_out_dir") {
- result.string_value() = DirectoryWithNoLastSlash(GetBuildDirAsSourceDir(
- BuildDirContext(scope, label.GetToolchainLabel()),
- BuildDirType::TOOLCHAIN_ROOT));
-
- } else if (what == "toolchain") {
- result.string_value() = label.GetToolchainLabel().GetUserVisibleName(false);
-
- } else if (what == "label_no_toolchain") {
- result.string_value() =
- label.GetWithNoToolchain().GetUserVisibleName(false);
-
- } else if (what == "label_with_toolchain") {
- result.string_value() = label.GetUserVisibleName(true);
-
- } else {
- *err = Err(args[1], "Unknown value for \"what\" parameter.");
- return Value();
- }
-
- return result;
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/function_get_label_info_unittest.cc b/chromium/tools/gn/function_get_label_info_unittest.cc
deleted file mode 100644
index 65e46d050e9..00000000000
--- a/chromium/tools/gn/function_get_label_info_unittest.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-class GetLabelInfoTest : public testing::Test {
- public:
- GetLabelInfoTest() : testing::Test() {
- setup_.scope()->set_source_dir(SourceDir("//src/foo/"));
- }
-
- // Convenience wrapper to call GetLabelInfo.
- std::string Call(const std::string& label, const std::string& what) {
- FunctionCallNode function;
-
- std::vector<Value> args;
- args.push_back(Value(nullptr, label));
- args.push_back(Value(nullptr, what));
-
- Err err;
- Value result = functions::RunGetLabelInfo(setup_.scope(), &function,
- args, &err);
- if (err.has_error()) {
- EXPECT_TRUE(result.type() == Value::NONE);
- return std::string();
- }
- return result.string_value();
- }
-
- protected:
- // Note: TestWithScope's default toolchain is "//toolchain:default" and
- // output dir is "//out/Debug".
- TestWithScope setup_;
-};
-
-} // namespace
-
-TEST_F(GetLabelInfoTest, BadInput) {
- EXPECT_EQ("", Call(":name", "incorrect_value"));
- EXPECT_EQ("", Call("", "name"));
-}
-
-TEST_F(GetLabelInfoTest, Name) {
- EXPECT_EQ("name", Call(":name", "name"));
- EXPECT_EQ("name", Call("//foo/bar:name", "name"));
- EXPECT_EQ("name", Call("//foo/bar:name(//other:tc)", "name"));
-}
-
-TEST_F(GetLabelInfoTest, Dir) {
- EXPECT_EQ("//src/foo", Call(":name", "dir"));
- EXPECT_EQ("//foo/bar", Call("//foo/bar:baz", "dir"));
- EXPECT_EQ("//foo/bar", Call("//foo/bar:baz(//other:tc)", "dir"));
-}
-
-TEST_F(GetLabelInfoTest, RootOutDir) {
- EXPECT_EQ("//out/Debug", Call(":name", "root_out_dir"));
- EXPECT_EQ("//out/Debug/random",
- Call(":name(//toolchain:random)", "root_out_dir"));
-}
-
-TEST_F(GetLabelInfoTest, RootGenDir) {
- EXPECT_EQ("//out/Debug/gen", Call(":name", "root_gen_dir"));
- EXPECT_EQ("//out/Debug/gen",
- Call(":name(//toolchain:default)", "root_gen_dir"));
- EXPECT_EQ("//out/Debug/random/gen",
- Call(":name(//toolchain:random)", "root_gen_dir"));
-}
-
-TEST_F(GetLabelInfoTest, TargetOutDir) {
- EXPECT_EQ("//out/Debug/obj/src/foo", Call(":name", "target_out_dir"));
- EXPECT_EQ("//out/Debug/obj/foo",
- Call("//foo:name(//toolchain:default)", "target_out_dir"));
- EXPECT_EQ("//out/Debug/random/obj/foo",
- Call("//foo:name(//toolchain:random)", "target_out_dir"));
-}
-
-TEST_F(GetLabelInfoTest, TargetGenDir) {
- EXPECT_EQ("//out/Debug/gen/src/foo", Call(":name", "target_gen_dir"));
- EXPECT_EQ("//out/Debug/gen/foo",
- Call("//foo:name(//toolchain:default)", "target_gen_dir"));
- EXPECT_EQ("//out/Debug/random/gen/foo",
- Call("//foo:name(//toolchain:random)", "target_gen_dir"));
-}
-
-TEST_F(GetLabelInfoTest, LabelNoToolchain) {
- EXPECT_EQ("//src/foo:name", Call(":name", "label_no_toolchain"));
- EXPECT_EQ("//src/foo:name",
- Call("//src/foo:name(//toolchain:random)", "label_no_toolchain"));
-}
-
-TEST_F(GetLabelInfoTest, LabelWithToolchain) {
- EXPECT_EQ("//src/foo:name(//toolchain:default)",
- Call(":name", "label_with_toolchain"));
- EXPECT_EQ("//src/foo:name(//toolchain:random)",
- Call(":name(//toolchain:random)", "label_with_toolchain"));
-}
-
-TEST_F(GetLabelInfoTest, Toolchain) {
- EXPECT_EQ("//toolchain:default", Call(":name", "toolchain"));
- EXPECT_EQ("//toolchain:random",
- Call(":name(//toolchain:random)", "toolchain"));
-}
diff --git a/chromium/tools/gn/function_get_path_info.cc b/chromium/tools/gn/function_get_path_info.cc
deleted file mode 100644
index e08eca1d443..00000000000
--- a/chromium/tools/gn/function_get_path_info.cc
+++ /dev/null
@@ -1,250 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/value.h"
-
-namespace functions {
-
-namespace {
-
-// Corresponds to the various values of "what" in the function call.
-enum What {
- WHAT_FILE,
- WHAT_NAME,
- WHAT_EXTENSION,
- WHAT_DIR,
- WHAT_ABSPATH,
- WHAT_GEN_DIR,
- WHAT_OUT_DIR,
-};
-
-// Returns the directory containing the input (resolving it against the
-// |current_dir|), regardless of whether the input is a directory or a file.
-SourceDir DirForInput(const Settings* settings,
- const SourceDir& current_dir,
- const Value& input,
- Err* err) {
- // Input should already have been validated as a string.
- const std::string& input_string = input.string_value();
-
- if (!input_string.empty() && input_string[input_string.size() - 1] == '/') {
- // Input is a directory.
- return current_dir.ResolveRelativeDir(input, err,
- settings->build_settings()->root_path_utf8());
- }
-
- // Input is a file.
- return current_dir.ResolveRelativeFile(input, err,
- settings->build_settings()->root_path_utf8()).GetDir();
-}
-
-std::string GetOnePathInfo(const Settings* settings,
- const SourceDir& current_dir,
- What what,
- const Value& input,
- Err* err) {
- if (!input.VerifyTypeIs(Value::STRING, err))
- return std::string();
- const std::string& input_string = input.string_value();
- if (input_string.empty()) {
- *err = Err(input, "Calling get_path_info on an empty string.");
- return std::string();
- }
-
- switch (what) {
- case WHAT_FILE: {
- return FindFilename(&input_string).as_string();
- }
- case WHAT_NAME: {
- std::string file = FindFilename(&input_string).as_string();
- size_t extension_offset = FindExtensionOffset(file);
- if (extension_offset == std::string::npos)
- return file;
- // Trim extension and dot.
- return file.substr(0, extension_offset - 1);
- }
- case WHAT_EXTENSION: {
- return FindExtension(&input_string).as_string();
- }
- case WHAT_DIR: {
- base::StringPiece dir_incl_slash = FindDir(&input_string);
- if (dir_incl_slash.empty())
- return std::string(".");
- // Trim slash since this function doesn't return trailing slashes. The
- // times we don't do this are if the result is "/" and "//" since those
- // slashes can't be trimmed.
- if (dir_incl_slash == "/")
- return std::string("/.");
- if (dir_incl_slash == "//")
- return std::string("//.");
- return dir_incl_slash.substr(0, dir_incl_slash.size() - 1).as_string();
- }
- case WHAT_GEN_DIR: {
- return DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir(
- BuildDirContext(settings),
- DirForInput(settings, current_dir, input, err),
- BuildDirType::GEN));
- }
- case WHAT_OUT_DIR: {
- return DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir(
- BuildDirContext(settings),
- DirForInput(settings, current_dir, input, err),
- BuildDirType::OBJ));
- }
- case WHAT_ABSPATH: {
- bool as_dir =
- !input_string.empty() && input_string[input_string.size() - 1] == '/';
-
- return current_dir.ResolveRelativeAs(
- !as_dir, input, err, settings->build_settings()->root_path_utf8(),
- &input_string);
- }
- default:
- NOTREACHED();
- return std::string();
- }
-}
-
-} // namespace
-
-const char kGetPathInfo[] = "get_path_info";
-const char kGetPathInfo_HelpShort[] =
- "get_path_info: Extract parts of a file or directory name.";
-const char kGetPathInfo_Help[] =
- R"(get_path_info: Extract parts of a file or directory name.
-
- get_path_info(input, what)
-
- The first argument is either a string representing a file or directory name,
- or a list of such strings. If the input is a list the return value will be a
- list containing the result of applying the rule to each item in the input.
-
-Possible values for the "what" parameter
-
- "file"
- The substring after the last slash in the path, including the name and
- extension. If the input ends in a slash, the empty string will be
- returned.
- "foo/bar.txt" => "bar.txt"
- "bar.txt" => "bar.txt"
- "foo/" => ""
- "" => ""
-
- "name"
- The substring of the file name not including the extension.
- "foo/bar.txt" => "bar"
- "foo/bar" => "bar"
- "foo/" => ""
-
- "extension"
- The substring following the last period following the last slash, or the
- empty string if not found. The period is not included.
- "foo/bar.txt" => "txt"
- "foo/bar" => ""
-
- "dir"
- The directory portion of the name, not including the slash.
- "foo/bar.txt" => "foo"
- "//foo/bar" => "//foo"
- "foo" => "."
-
- The result will never end in a slash, so if the resulting is empty, the
- system ("/") or source ("//") roots, a "." will be appended such that it
- is always legal to append a slash and a filename and get a valid path.
-
- "out_dir"
- The output file directory corresponding to the path of the given file,
- not including a trailing slash.
- "//foo/bar/baz.txt" => "//out/Default/obj/foo/bar"
-
- "gen_dir"
- The generated file directory corresponding to the path of the given file,
- not including a trailing slash.
- "//foo/bar/baz.txt" => "//out/Default/gen/foo/bar"
-
- "abspath"
- The full absolute path name to the file or directory. It will be resolved
- relative to the current directory, and then the source- absolute version
- will be returned. If the input is system- absolute, the same input will
- be returned.
- "foo/bar.txt" => "//mydir/foo/bar.txt"
- "foo/" => "//mydir/foo/"
- "//foo/bar" => "//foo/bar" (already absolute)
- "/usr/include" => "/usr/include" (already absolute)
-
- If you want to make the path relative to another directory, or to be
- system-absolute, see rebase_path().
-
-Examples
- sources = [ "foo.cc", "foo.h" ]
- result = get_path_info(source, "abspath")
- # result will be [ "//mydir/foo.cc", "//mydir/foo.h" ]
-
- result = get_path_info("//foo/bar/baz.cc", "dir")
- # result will be "//foo/bar"
-
- # Extract the source-absolute directory name,
- result = get_path_info(get_path_info(path, "dir"), "abspath"
-)";
-
-Value RunGetPathInfo(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- if (args.size() != 2) {
- *err = Err(function, "Expecting two arguments to get_path_info.");
- return Value();
- }
-
- // Extract the "what".
- if (!args[1].VerifyTypeIs(Value::STRING, err))
- return Value();
- What what;
- if (args[1].string_value() == "file") {
- what = WHAT_FILE;
- } else if (args[1].string_value() == "name") {
- what = WHAT_NAME;
- } else if (args[1].string_value() == "extension") {
- what = WHAT_EXTENSION;
- } else if (args[1].string_value() == "dir") {
- what = WHAT_DIR;
- } else if (args[1].string_value() == "out_dir") {
- what = WHAT_OUT_DIR;
- } else if (args[1].string_value() == "gen_dir") {
- what = WHAT_GEN_DIR;
- } else if (args[1].string_value() == "abspath") {
- what = WHAT_ABSPATH;
- } else {
- *err = Err(args[1], "Unknown value for 'what'.");
- return Value();
- }
-
- const SourceDir& current_dir = scope->GetSourceDir();
- if (args[0].type() == Value::STRING) {
- return Value(function, GetOnePathInfo(scope->settings(), current_dir, what,
- args[0], err));
- } else if (args[0].type() == Value::LIST) {
- const std::vector<Value>& input_list = args[0].list_value();
- Value result(function, Value::LIST);
- for (const auto& cur : input_list) {
- result.list_value().push_back(Value(function,
- GetOnePathInfo(scope->settings(), current_dir, what, cur, err)));
- if (err->has_error())
- return Value();
- }
- return result;
- }
-
- *err = Err(args[0], "Path must be a string or a list of strings.");
- return Value();
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/function_get_path_info_unittest.cc b/chromium/tools/gn/function_get_path_info_unittest.cc
deleted file mode 100644
index 79020df0824..00000000000
--- a/chromium/tools/gn/function_get_path_info_unittest.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-class GetPathInfoTest : public testing::Test {
- public:
- GetPathInfoTest() : testing::Test() {
- setup_.scope()->set_source_dir(SourceDir("//src/foo/"));
- }
-
- // Convenience wrapper to call GetLabelInfo.
- std::string Call(const std::string& input, const std::string& what) {
- FunctionCallNode function;
-
- std::vector<Value> args;
- args.push_back(Value(nullptr, input));
- args.push_back(Value(nullptr, what));
-
- Err err;
- Value result = functions::RunGetPathInfo(setup_.scope(), &function,
- args, &err);
- if (err.has_error()) {
- EXPECT_TRUE(result.type() == Value::NONE);
- return std::string();
- }
- return result.string_value();
- }
-
- protected:
- TestWithScope setup_;
-};
-
-} // namespace
-
-TEST_F(GetPathInfoTest, File) {
- EXPECT_EQ("bar.txt", Call("foo/bar.txt", "file"));
- EXPECT_EQ("bar.txt", Call("bar.txt", "file"));
- EXPECT_EQ("bar.txt", Call("/bar.txt", "file"));
- EXPECT_EQ("", Call("foo/", "file"));
- EXPECT_EQ("", Call("//", "file"));
- EXPECT_EQ("", Call("/", "file"));
-}
-
-TEST_F(GetPathInfoTest, Name) {
- EXPECT_EQ("bar", Call("foo/bar.txt", "name"));
- EXPECT_EQ("bar", Call("bar.", "name"));
- EXPECT_EQ("", Call("/.txt", "name"));
- EXPECT_EQ("", Call("foo/", "name"));
- EXPECT_EQ("", Call("//", "name"));
- EXPECT_EQ("", Call("/", "name"));
-}
-
-TEST_F(GetPathInfoTest, Extension) {
- EXPECT_EQ("txt", Call("foo/bar.txt", "extension"));
- EXPECT_EQ("", Call("bar.", "extension"));
- EXPECT_EQ("txt", Call("/.txt", "extension"));
- EXPECT_EQ("", Call("f.oo/", "extension"));
- EXPECT_EQ("", Call("//", "extension"));
- EXPECT_EQ("", Call("/", "extension"));
-}
-
-TEST_F(GetPathInfoTest, Dir) {
- EXPECT_EQ("foo", Call("foo/bar.txt", "dir"));
- EXPECT_EQ(".", Call("bar.txt", "dir"));
- EXPECT_EQ("foo/bar", Call("foo/bar/baz", "dir"));
- EXPECT_EQ("//foo", Call("//foo/", "dir"));
- EXPECT_EQ("//.", Call("//", "dir"));
- EXPECT_EQ("/foo", Call("/foo/", "dir"));
- EXPECT_EQ("/.", Call("/", "dir"));
-}
-
-// Note "current dir" is "//src/foo"
-TEST_F(GetPathInfoTest, AbsPath) {
- EXPECT_EQ("//src/foo/foo/bar.txt", Call("foo/bar.txt", "abspath"));
- EXPECT_EQ("//src/foo/bar.txt", Call("bar.txt", "abspath"));
- EXPECT_EQ("//src/foo/bar/", Call("bar/", "abspath"));
- EXPECT_EQ("//foo", Call("//foo", "abspath"));
- EXPECT_EQ("//foo/", Call("//foo/", "abspath"));
- EXPECT_EQ("//", Call("//", "abspath"));
- EXPECT_EQ("/foo", Call("/foo", "abspath"));
- EXPECT_EQ("/foo/", Call("/foo/", "abspath"));
- EXPECT_EQ("/", Call("/", "abspath"));
-}
-
-// Note build dir is "//out/Debug/".
-TEST_F(GetPathInfoTest, OutDir) {
- EXPECT_EQ("//out/Debug/obj/src/foo/foo", Call("foo/bar.txt", "out_dir"));
- EXPECT_EQ("//out/Debug/obj/src/foo/bar", Call("bar/", "out_dir"));
- EXPECT_EQ("//out/Debug/obj/src/foo", Call(".", "out_dir"));
- EXPECT_EQ("//out/Debug/obj/src/foo", Call("bar", "out_dir"));
- EXPECT_EQ("//out/Debug/obj/foo", Call("//foo/bar.txt", "out_dir"));
- // System paths go into the ABS_PATH obj directory.
- EXPECT_EQ("//out/Debug/obj/ABS_PATH/foo", Call("/foo/bar.txt", "out_dir"));
-#if defined(OS_WIN)
- EXPECT_EQ("//out/Debug/obj/ABS_PATH/C/foo",
- Call("/C:/foo/bar.txt", "out_dir"));
-#endif
-}
-
-// Note build dir is "//out/Debug/".
-TEST_F(GetPathInfoTest, GenDir) {
- EXPECT_EQ("//out/Debug/gen/src/foo/foo", Call("foo/bar.txt", "gen_dir"));
- EXPECT_EQ("//out/Debug/gen/src/foo/bar", Call("bar/", "gen_dir"));
- EXPECT_EQ("//out/Debug/gen/src/foo", Call(".", "gen_dir"));
- EXPECT_EQ("//out/Debug/gen/src/foo", Call("bar", "gen_dir"));
- EXPECT_EQ("//out/Debug/gen/foo", Call("//foo/bar.txt", "gen_dir"));
- // System paths go into the ABS_PATH gen directory
- EXPECT_EQ("//out/Debug/gen/ABS_PATH/foo", Call("/foo/bar.txt", "gen_dir"));
-#if defined(OS_WIN)
- EXPECT_EQ("//out/Debug/gen/ABS_PATH/C/foo",
- Call("/C:/foo/bar.txt", "gen_dir"));
-#endif
-}
diff --git a/chromium/tools/gn/function_get_target_outputs.cc b/chromium/tools/gn/function_get_target_outputs.cc
deleted file mode 100644
index e13e1e3a546..00000000000
--- a/chromium/tools/gn/function_get_target_outputs.cc
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/build_settings.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/target.h"
-#include "tools/gn/value.h"
-
-namespace functions {
-
-const char kGetTargetOutputs[] = "get_target_outputs";
-const char kGetTargetOutputs_HelpShort[] =
- "get_target_outputs: [file list] Get the list of outputs from a target.";
-const char kGetTargetOutputs_Help[] =
- R"(get_target_outputs: [file list] Get the list of outputs from a target.
-
- get_target_outputs(target_label)
-
- Returns a list of output files for the named target. The named target must
- have been previously defined in the current file before this function is
- called (it can't reference targets in other files because there isn't a
- defined execution order, and it obviously can't reference targets that are
- defined after the function call).
-
- Only copy and action targets are supported. The outputs from binary targets
- will depend on the toolchain definition which won't necessarily have been
- loaded by the time a given line of code has run, and source sets and groups
- have no useful output file.
-
-Return value
-
- The names in the resulting list will be absolute file paths (normally like
- "//out/Debug/bar.exe", depending on the build directory).
-
- action targets: this will just return the files specified in the "outputs"
- variable of the target.
-
- action_foreach targets: this will return the result of applying the output
- template to the sources (see "gn help source_expansion"). This will be the
- same result (though with guaranteed absolute file paths), as
- process_file_template will return for those inputs (see "gn help
- process_file_template").
-
- binary targets (executables, libraries): this will return a list of the
- resulting binary file(s). The "main output" (the actual binary or library)
- will always be the 0th element in the result. Depending on the platform and
- output type, there may be other output files as well (like import libraries)
- which will follow.
-
- source sets and groups: this will return a list containing the path of the
- "stamp" file that Ninja will produce once all outputs are generated. This
- probably isn't very useful.
-
-Example
-
- # Say this action generates a bunch of C source files.
- action_foreach("my_action") {
- sources = [ ... ]
- outputs = [ ... ]
- }
-
- # Compile the resulting source files into a source set.
- source_set("my_lib") {
- sources = get_target_outputs(":my_action")
- }
-)";
-
-Value RunGetTargetOutputs(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- if (args.size() != 1) {
- *err = Err(function, "Expected one argument.");
- return Value();
- }
-
- // Resolve the requested label.
- Label label = Label::Resolve(scope->GetSourceDir(),
- ToolchainLabelForScope(scope), args[0], err);
- if (label.is_null())
- return Value();
-
- // Find the referenced target. The targets previously encountered in this
- // scope will have been stashed in the item collector (they'll be dispatched
- // when this file is done running) so we can look through them.
- const Target* target = nullptr;
- Scope::ItemVector* collector = scope->GetItemCollector();
- if (!collector) {
- *err = Err(function, "No targets defined in this context.");
- return Value();
- }
- for (const auto& item : *collector) {
- if (item->label() != label)
- continue;
-
- const Target* as_target = item->AsTarget();
- if (!as_target) {
- *err = Err(function, "Label does not refer to a target.",
- label.GetUserVisibleName(false) +
- "\nrefers to a " + item->GetItemTypeName());
- return Value();
- }
- target = as_target;
- break;
- }
-
- if (!target) {
- *err = Err(function, "Target not found in this context.",
- label.GetUserVisibleName(false) +
- "\nwas not found. get_target_outputs() can only be used for targets\n"
- "previously defined in the current file.");
- return Value();
- }
-
- // Compute the output list.
- std::vector<SourceFile> files;
- if (target->output_type() == Target::ACTION ||
- target->output_type() == Target::COPY_FILES ||
- target->output_type() == Target::ACTION_FOREACH) {
- target->action_values().GetOutputsAsSourceFiles(target, &files);
- } else {
- // Other types of targets are not supported.
- *err = Err(args[0], "Target is not an action, action_foreach, or copy.",
- "Only these target types are supported by get_target_outputs.");
- return Value();
- }
-
- // Convert to Values.
- Value ret(function, Value::LIST);
- ret.list_value().reserve(files.size());
- for (const auto& file : files)
- ret.list_value().push_back(Value(function, file.value()));
-
- return ret;
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/function_get_target_outputs_unittest.cc b/chromium/tools/gn/function_get_target_outputs_unittest.cc
deleted file mode 100644
index d7354ebe566..00000000000
--- a/chromium/tools/gn/function_get_target_outputs_unittest.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <memory>
-#include <utility>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-class GetTargetOutputsTest : public testing::Test {
- public:
- GetTargetOutputsTest() {
- setup_.scope()->set_item_collector(&items_);
- }
-
- Value GetTargetOutputs(const std::string& name, Err* err) {
- FunctionCallNode function;
- std::vector<Value> args;
- args.push_back(Value(nullptr, name));
- return functions::RunGetTargetOutputs(setup_.scope(), &function, args, err);
- }
-
- // Shortcut to get a label with the current toolchain.
- Label GetLabel(const std::string& dir, const std::string& name) {
- return Label(SourceDir(dir), name, setup_.toolchain()->label().dir(),
- setup_.toolchain()->label().name());
- }
-
- // Asserts that the given list contains a single string with the given value.
- void AssertSingleStringEquals(const Value& list,
- const std::string& expected) {
- ASSERT_TRUE(list.type() == Value::LIST);
- ASSERT_EQ(1u, list.list_value().size());
- ASSERT_TRUE(list.list_value()[0].type() == Value::STRING);
- ASSERT_EQ(expected, list.list_value()[0].string_value());
- }
-
- void AssertTwoStringsEqual(const Value& list,
- const std::string& expected1,
- const std::string& expected2) {
- ASSERT_TRUE(list.type() == Value::LIST);
- ASSERT_EQ(2u, list.list_value().size());
- ASSERT_TRUE(list.list_value()[0].type() == Value::STRING);
- ASSERT_EQ(expected1, list.list_value()[0].string_value());
- ASSERT_TRUE(list.list_value()[1].type() == Value::STRING);
- ASSERT_EQ(expected2, list.list_value()[1].string_value());
- }
-
- protected:
- TestWithScope setup_;
-
- Scope::ItemVector items_;
-};
-
-} // namespace
-
-TEST_F(GetTargetOutputsTest, Copy) {
- auto action =
- std::make_unique<Target>(setup_.settings(), GetLabel("//foo/", "bar"));
- action->set_output_type(Target::COPY_FILES);
- action->sources().push_back(SourceFile("//file.txt"));
- action->action_values().outputs() =
- SubstitutionList::MakeForTest("//out/Debug/{{source_file_part}}.one");
-
- items_.push_back(std::move(action));
-
- Err err;
- Value result = GetTargetOutputs("//foo:bar", &err);
- ASSERT_FALSE(err.has_error());
- AssertSingleStringEquals(result, "//out/Debug/file.txt.one");
-}
-
-TEST_F(GetTargetOutputsTest, Action) {
- auto action =
- std::make_unique<Target>(setup_.settings(), GetLabel("//foo/", "bar"));
- action->set_output_type(Target::ACTION);
- action->action_values().outputs() = SubstitutionList::MakeForTest(
- "//output1.txt",
- "//output2.txt");
-
- items_.push_back(std::move(action));
-
- Err err;
- Value result = GetTargetOutputs("//foo:bar", &err);
- ASSERT_FALSE(err.has_error());
- AssertTwoStringsEqual(result, "//output1.txt", "//output2.txt");
-}
-
-TEST_F(GetTargetOutputsTest, ActionForeach) {
- auto action =
- std::make_unique<Target>(setup_.settings(), GetLabel("//foo/", "bar"));
- action->set_output_type(Target::ACTION_FOREACH);
- action->sources().push_back(SourceFile("//file.txt"));
- action->action_values().outputs() = SubstitutionList::MakeForTest(
- "//out/Debug/{{source_file_part}}.one",
- "//out/Debug/{{source_file_part}}.two");
-
- items_.push_back(std::move(action));
-
- Err err;
- Value result = GetTargetOutputs("//foo:bar", &err);
- ASSERT_FALSE(err.has_error());
- AssertTwoStringsEqual(result, "//out/Debug/file.txt.one",
- "//out/Debug/file.txt.two");
-}
diff --git a/chromium/tools/gn/function_process_file_template.cc b/chromium/tools/gn/function_process_file_template.cc
deleted file mode 100644
index 47de6407f1a..00000000000
--- a/chromium/tools/gn/function_process_file_template.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/stl_util.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/substitution_list.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/target.h"
-#include "tools/gn/value_extractors.h"
-
-namespace functions {
-
-const char kProcessFileTemplate[] = "process_file_template";
-const char kProcessFileTemplate_HelpShort[] =
- "process_file_template: Do template expansion over a list of files.";
-const char kProcessFileTemplate_Help[] =
- R"(process_file_template: Do template expansion over a list of files.
-
- process_file_template(source_list, template)
-
- process_file_template applies a template list to a source file list,
- returning the result of applying each template to each source. This is
- typically used for computing output file names from input files.
-
- In most cases, get_target_outputs() will give the same result with shorter,
- more maintainable code. This function should only be used when that function
- can't be used (like there's no target or the target is defined in another
- build file).
-
-Arguments
-
- The source_list is a list of file names.
-
- The template can be a string or a list. If it is a list, multiple output
- strings are generated for each input.
-
- The template should contain source expansions to which each name in the
- source list is applied. See "gn help source_expansion".
-
-Example
-
- sources = [
- "foo.idl",
- "bar.idl",
- ]
- myoutputs = process_file_template(
- sources,
- [ "$target_gen_dir/{{source_name_part}}.cc",
- "$target_gen_dir/{{source_name_part}}.h" ])
-
- The result in this case will be:
- [ "//out/Debug/foo.cc"
- "//out/Debug/foo.h"
- "//out/Debug/bar.cc"
- "//out/Debug/bar.h" ]
-)";
-
-Value RunProcessFileTemplate(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- if (args.size() != 2) {
- *err = Err(function->function(), "Expected two arguments");
- return Value();
- }
-
- // Source list.
- Target::FileList input_files;
- if (!ExtractListOfRelativeFiles(scope->settings()->build_settings(), args[0],
- scope->GetSourceDir(), &input_files, err))
- return Value();
-
- std::vector<std::string> result_files;
- SubstitutionList subst;
-
- // Template.
- const Value& template_arg = args[1];
- if (template_arg.type() == Value::STRING) {
- // Convert the string to a SubstitutionList with one pattern in it to
- // simplify the code below.
- std::vector<std::string> list;
- list.push_back(template_arg.string_value());
- if (!subst.Parse(list, template_arg.origin(), err))
- return Value();
- } else if (template_arg.type() == Value::LIST) {
- if (!subst.Parse(template_arg, err))
- return Value();
- } else {
- *err = Err(template_arg, "Not a string or a list.");
- return Value();
- }
-
- auto& types = subst.required_types();
- if (base::ContainsValue(types, SUBSTITUTION_SOURCE_TARGET_RELATIVE)) {
- *err = Err(template_arg, "Not a valid substitution type for the function.");
- return Value();
- }
-
- SubstitutionWriter::ApplyListToSourcesAsString(
- nullptr, scope->settings(), subst, input_files, &result_files);
-
- // Convert the list of strings to the return Value.
- Value ret(function, Value::LIST);
- ret.list_value().reserve(result_files.size());
- for (const auto& file : result_files)
- ret.list_value().push_back(Value(function, file));
-
- return ret;
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/function_process_file_template_unittest.cc b/chromium/tools/gn/function_process_file_template_unittest.cc
deleted file mode 100644
index a455222a549..00000000000
--- a/chromium/tools/gn/function_process_file_template_unittest.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/test_with_scope.h"
-
-TEST(FunctionProcessFileTemplates, SingleString) {
- TestWithScope setup;
-
- std::vector<Value> args;
-
- Value sources(nullptr, Value::LIST);
- sources.list_value().push_back(Value(nullptr, "//src/foo.txt"));
- args.push_back(sources);
-
- Value expansion(nullptr, "1234{{source_name_part}}5678");
- args.push_back(expansion);
-
- Err err;
- Value result =
- functions::RunProcessFileTemplate(setup.scope(), nullptr, args, &err);
- EXPECT_FALSE(err.has_error());
-
- ASSERT_TRUE(result.type() == Value::LIST);
- ASSERT_EQ(1u, result.list_value().size());
- ASSERT_TRUE(result.list_value()[0].type() == Value::STRING);
- ASSERT_EQ("1234foo5678", result.list_value()[0].string_value());
-}
-
-TEST(FunctionProcessFileTemplates, MultipleStrings) {
- TestWithScope setup;
-
- std::vector<Value> args;
-
- Value sources(nullptr, Value::LIST);
- sources.list_value().push_back(Value(nullptr, "//src/one.txt"));
- sources.list_value().push_back(Value(nullptr, "//src/two.txt"));
- args.push_back(sources);
-
- Value expansions(nullptr, Value::LIST);
- expansions.list_value().push_back(
- Value(nullptr, "1234{{source_name_part}}5678"));
- expansions.list_value().push_back(
- Value(nullptr, "ABCD{{source_file_part}}EFGH"));
- args.push_back(expansions);
-
- Err err;
- Value result =
- functions::RunProcessFileTemplate(setup.scope(), nullptr, args, &err);
- EXPECT_FALSE(err.has_error());
-
- ASSERT_TRUE(result.type() == Value::LIST);
- ASSERT_EQ(4u, result.list_value().size());
- ASSERT_TRUE(result.list_value()[0].type() == Value::STRING);
- ASSERT_TRUE(result.list_value()[1].type() == Value::STRING);
- ASSERT_TRUE(result.list_value()[2].type() == Value::STRING);
- ASSERT_TRUE(result.list_value()[3].type() == Value::STRING);
- ASSERT_EQ("1234one5678", result.list_value()[0].string_value());
- ASSERT_EQ("ABCDone.txtEFGH", result.list_value()[1].string_value());
- ASSERT_EQ("1234two5678", result.list_value()[2].string_value());
- ASSERT_EQ("ABCDtwo.txtEFGH", result.list_value()[3].string_value());
-}
diff --git a/chromium/tools/gn/function_read_file.cc b/chromium/tools/gn/function_read_file.cc
deleted file mode 100644
index ed37ef0cac2..00000000000
--- a/chromium/tools/gn/function_read_file.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/files/file_util.h"
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/input_conversion.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/scheduler.h"
-
-// TODO(brettw) consider removing this. I originally wrote it for making the
-// WebKit bindings but misundersood what was required, and didn't need to
-// use this. This seems to have a high potential for misuse.
-
-namespace functions {
-
-const char kReadFile[] = "read_file";
-const char kReadFile_HelpShort[] =
- "read_file: Read a file into a variable.";
-const char kReadFile_Help[] =
- R"(read_file: Read a file into a variable.
-
- read_file(filename, input_conversion)
-
- Whitespace will be trimmed from the end of the file. Throws an error if the
- file can not be opened.
-
-Arguments
-
- filename
- Filename to read, relative to the build file.
-
- input_conversion
- Controls how the file is read and parsed. See "gn help input_conversion".
-
-Example
-
- lines = read_file("foo.txt", "list lines")
-)";
-
-Value RunReadFile(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- if (args.size() != 2) {
- *err = Err(function->function(), "Wrong number of arguments to read_file",
- "I expected two arguments.");
- return Value();
- }
- if (!args[0].VerifyTypeIs(Value::STRING, err))
- return Value();
-
- // Compute the file name.
- const SourceDir& cur_dir = scope->GetSourceDir();
- SourceFile source_file = cur_dir.ResolveRelativeFile(args[0], err,
- scope->settings()->build_settings()->root_path_utf8());
- if (err->has_error())
- return Value();
- base::FilePath file_path =
- scope->settings()->build_settings()->GetFullPath(source_file);
-
- // Ensure that everything is recomputed if the read file changes.
- g_scheduler->AddGenDependency(file_path);
-
- // Read contents.
- std::string file_contents;
- if (!base::ReadFileToString(file_path, &file_contents)) {
- *err = Err(args[0], "Could not read file.",
- "I resolved this to \"" + FilePathToUTF8(file_path) + "\".");
- return Value();
- }
-
- return ConvertInputToValue(scope->settings(), file_contents, function,
- args[1], err);
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/function_rebase_path.cc b/chromium/tools/gn/function_rebase_path.cc
deleted file mode 100644
index 7626551b4fd..00000000000
--- a/chromium/tools/gn/function_rebase_path.cc
+++ /dev/null
@@ -1,295 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include "tools/gn/build_settings.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/source_dir.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/value.h"
-
-namespace functions {
-
-namespace {
-
-// We want the output to match the input in terms of ending in a slash or not.
-// Through all the transformations, these can get added or removed in various
-// cases.
-void MakeSlashEndingMatchInput(const std::string& input, std::string* output) {
- if (EndsWithSlash(input)) {
- if (!EndsWithSlash(*output)) // Preserve same slash type as input.
- output->push_back(input[input.size() - 1]);
- } else {
- if (EndsWithSlash(*output))
- output->resize(output->size() - 1);
- }
-}
-
-// Returns true if the given value looks like a directory, otherwise we'll
-// assume it's a file.
-bool ValueLooksLikeDir(const std::string& value) {
- if (value.empty())
- return true;
- size_t value_size = value.size();
-
- // Count the number of dots at the end of the string.
- size_t num_dots = 0;
- while (num_dots < value_size && value[value_size - num_dots - 1] == '.')
- num_dots++;
-
- if (num_dots == value.size())
- return true; // String is all dots.
-
- if (IsSlash(value[value_size - num_dots - 1]))
- return true; // String is a [back]slash followed by 0 or more dots.
-
- // Anything else.
- return false;
-}
-
-Value ConvertOnePath(const Scope* scope,
- const FunctionCallNode* function,
- const Value& value,
- const SourceDir& from_dir,
- const SourceDir& to_dir,
- bool convert_to_system_absolute,
- Err* err) {
- Value result; // Ensure return value optimization.
-
- if (!value.VerifyTypeIs(Value::STRING, err))
- return result;
- const std::string& string_value = value.string_value();
-
- bool looks_like_dir = ValueLooksLikeDir(string_value);
-
- // System-absolute output special case.
- if (convert_to_system_absolute) {
- base::FilePath system_path;
- if (looks_like_dir) {
- system_path = scope->settings()->build_settings()->GetFullPath(
- from_dir.ResolveRelativeDir(value, err,
- scope->settings()->build_settings()->root_path_utf8()));
- } else {
- system_path = scope->settings()->build_settings()->GetFullPath(
- from_dir.ResolveRelativeFile(value, err,
- scope->settings()->build_settings()->root_path_utf8()));
- }
- if (err->has_error())
- return Value();
-
- result = Value(function, FilePathToUTF8(system_path));
- if (looks_like_dir)
- MakeSlashEndingMatchInput(string_value, &result.string_value());
- return result;
- }
-
- result = Value(function, Value::STRING);
- if (looks_like_dir) {
- result.string_value() = RebasePath(
- from_dir.ResolveRelativeDir(value, err,
- scope->settings()->build_settings()->root_path_utf8()).value(),
- to_dir,
- scope->settings()->build_settings()->root_path_utf8());
- MakeSlashEndingMatchInput(string_value, &result.string_value());
- } else {
- SourceFile resolved_file =
- from_dir.ResolveRelativeFile(value, err,
- scope->settings()->build_settings()->root_path_utf8());
- if (err->has_error())
- return Value();
- // Special case:
- // rebase_path("//foo", "//bar") ==> "../foo"
- // rebase_path("//foo", "//foo") ==> "." and not "../foo"
- if (resolved_file.value() ==
- to_dir.value().substr(0, to_dir.value().size() - 1)) {
- result.string_value() = ".";
- } else {
- result.string_value() = RebasePath(
- resolved_file.value(),
- to_dir,
- scope->settings()->build_settings()->root_path_utf8());
- }
- }
-
- return result;
-}
-
-} // namespace
-
-const char kRebasePath[] = "rebase_path";
-const char kRebasePath_HelpShort[] =
- "rebase_path: Rebase a file or directory to another location.";
-const char kRebasePath_Help[] =
- R"(rebase_path: Rebase a file or directory to another location.
-
- converted = rebase_path(input,
- new_base = "",
- current_base = ".")
-
- Takes a string argument representing a file name, or a list of such strings
- and converts it/them to be relative to a different base directory.
-
- When invoking the compiler or scripts, GN will automatically convert sources
- and include directories to be relative to the build directory. However, if
- you're passing files directly in the "args" array or doing other manual
- manipulations where GN doesn't know something is a file name, you will need
- to convert paths to be relative to what your tool is expecting.
-
- The common case is to use this to convert paths relative to the current
- directory to be relative to the build directory (which will be the current
- directory when executing scripts).
-
- If you want to convert a file path to be source-absolute (that is, beginning
- with a double slash like "//foo/bar"), you should use the get_path_info()
- function. This function won't work because it will always make relative
- paths, and it needs to support making paths relative to the source root, so
- can't also generate source-absolute paths without more special-cases.
-
-Arguments
-
- input
- A string or list of strings representing file or directory names These
- can be relative paths ("foo/bar.txt"), system absolute paths
- ("/foo/bar.txt"), or source absolute paths ("//foo/bar.txt").
-
- new_base
- The directory to convert the paths to be relative to. This can be an
- absolute path or a relative path (which will be treated as being relative
- to the current BUILD-file's directory).
-
- As a special case, if new_base is the empty string (the default), all
- paths will be converted to system-absolute native style paths with system
- path separators. This is useful for invoking external programs.
-
- current_base
- Directory representing the base for relative paths in the input. If this
- is not an absolute path, it will be treated as being relative to the
- current build file. Use "." (the default) to convert paths from the
- current BUILD-file's directory.
-
-Return value
-
- The return value will be the same type as the input value (either a string or
- a list of strings). All relative and source-absolute file names will be
- converted to be relative to the requested output System-absolute paths will
- be unchanged.
-
- Whether an output path will end in a slash will match whether the
- corresponding input path ends in a slash. It will return "." or "./"
- (depending on whether the input ends in a slash) to avoid returning empty
- strings. This means if you want a root path ("//" or "/") not ending in a
- slash, you can add a dot ("//.").
-
-Example
-
- # Convert a file in the current directory to be relative to the build
- # directory (the current dir when executing compilers and scripts).
- foo = rebase_path("myfile.txt", root_build_dir)
- # might produce "../../project/myfile.txt".
-
- # Convert a file to be system absolute:
- foo = rebase_path("myfile.txt")
- # Might produce "D:\\source\\project\\myfile.txt" on Windows or
- # "/home/you/source/project/myfile.txt" on Linux.
-
- # Typical usage for converting to the build directory for a script.
- action("myscript") {
- # Don't convert sources, GN will automatically convert these to be relative
- # to the build directory when it constructs the command line for your
- # script.
- sources = [ "foo.txt", "bar.txt" ]
-
- # Extra file args passed manually need to be explicitly converted
- # to be relative to the build directory:
- args = [
- "--data",
- rebase_path("//mything/data/input.dat", root_build_dir),
- "--rel",
- rebase_path("relative_path.txt", root_build_dir)
- ] + rebase_path(sources, root_build_dir)
- }
-)";
-
-Value RunRebasePath(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- Value result;
-
- // Argument indices.
- static const size_t kArgIndexInputs = 0;
- static const size_t kArgIndexDest = 1;
- static const size_t kArgIndexFrom = 2;
-
- // Inputs.
- if (args.size() < 1 || args.size() > 3) {
- *err = Err(function->function(), "Wrong # of arguments for rebase_path.");
- return result;
- }
- const Value& inputs = args[kArgIndexInputs];
-
- // To path.
- bool convert_to_system_absolute = true;
- SourceDir to_dir;
- const SourceDir& current_dir = scope->GetSourceDir();
- if (args.size() > kArgIndexDest) {
- if (!args[kArgIndexDest].VerifyTypeIs(Value::STRING, err))
- return result;
- if (!args[kArgIndexDest].string_value().empty()) {
- to_dir = current_dir.ResolveRelativeDir(
- args[kArgIndexDest], err,
- scope->settings()->build_settings()->root_path_utf8());
- if (err->has_error())
- return Value();
- convert_to_system_absolute = false;
- }
- }
-
- // From path.
- SourceDir from_dir;
- if (args.size() > kArgIndexFrom) {
- if (!args[kArgIndexFrom].VerifyTypeIs(Value::STRING, err))
- return result;
- from_dir = current_dir.ResolveRelativeDir(
- args[kArgIndexFrom], err,
- scope->settings()->build_settings()->root_path_utf8());
- if (err->has_error())
- return Value();
- } else {
- // Default to current directory if unspecified.
- from_dir = current_dir;
- }
-
- // Path conversion.
- if (inputs.type() == Value::STRING) {
- return ConvertOnePath(scope, function, inputs,
- from_dir, to_dir, convert_to_system_absolute, err);
-
- } else if (inputs.type() == Value::LIST) {
- result = Value(function, Value::LIST);
- result.list_value().reserve(inputs.list_value().size());
-
- for (const auto& input : inputs.list_value()) {
- result.list_value().push_back(
- ConvertOnePath(scope, function, input,
- from_dir, to_dir, convert_to_system_absolute, err));
- if (err->has_error()) {
- result = Value();
- return result;
- }
- }
- return result;
- }
-
- *err = Err(function->function(),
- "rebase_path requires a list or a string.");
- return result;
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/function_rebase_path_unittest.cc b/chromium/tools/gn/function_rebase_path_unittest.cc
deleted file mode 100644
index d89b56f616b..00000000000
--- a/chromium/tools/gn/function_rebase_path_unittest.cc
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-std::string RebaseOne(Scope* scope,
- const char* input,
- const char* to_dir,
- const char* from_dir) {
- std::vector<Value> args;
- args.push_back(Value(nullptr, input));
- args.push_back(Value(nullptr, to_dir));
- args.push_back(Value(nullptr, from_dir));
-
- Err err;
- FunctionCallNode function;
- Value result = functions::RunRebasePath(scope, &function, args, &err);
- bool is_string = result.type() == Value::STRING;
- EXPECT_TRUE(is_string);
-
- return result.string_value();
-}
-
-} // namespace
-
-TEST(RebasePath, Strings) {
- TestWithScope setup;
- Scope* scope = setup.scope();
- scope->set_source_dir(SourceDir("//tools/gn/"));
-
- // Build-file relative paths.
- EXPECT_EQ("../../tools/gn", RebaseOne(scope, ".", "//out/Debug", "."));
- EXPECT_EQ("../../tools/gn/", RebaseOne(scope, "./", "//out/Debug", "."));
- EXPECT_EQ("../../tools/gn/foo", RebaseOne(scope, "foo", "//out/Debug", "."));
- EXPECT_EQ("../..", RebaseOne(scope, "../..", "//out/Debug", "."));
- EXPECT_EQ("../../", RebaseOne(scope, "../../", "//out/Debug", "."));
-
- // Without a source root defined, we cannot move out of the source tree.
- EXPECT_EQ("../..", RebaseOne(scope, "../../..", "//out/Debug", "."));
-
- // Source-absolute input paths.
- EXPECT_EQ("./", RebaseOne(scope, "//", "//", "//"));
- EXPECT_EQ("foo", RebaseOne(scope, "//foo", "//", "//"));
- EXPECT_EQ("foo/", RebaseOne(scope, "//foo/", "//", "//"));
- EXPECT_EQ("../../foo/bar", RebaseOne(scope, "//foo/bar", "//out/Debug", "."));
- EXPECT_EQ("./", RebaseOne(scope, "//foo/", "//foo/", "//"));
- EXPECT_EQ(".", RebaseOne(scope, "//foo", "//foo", "//"));
-
- // Test slash conversion.
- EXPECT_EQ("foo/bar", RebaseOne(scope, "foo/bar", ".", "."));
- EXPECT_EQ("foo/bar", RebaseOne(scope, "foo\\bar", ".", "."));
-
- // Test system path output.
-#if defined(OS_WIN)
- setup.build_settings()->SetRootPath(base::FilePath(L"C:/path/to/src"));
- EXPECT_EQ("C:/path/to/src", RebaseOne(scope, ".", "", "//"));
- EXPECT_EQ("C:/path/to/src/", RebaseOne(scope, "//", "", "//"));
- EXPECT_EQ("C:/path/to/src/foo", RebaseOne(scope, "foo", "", "//"));
- EXPECT_EQ("C:/path/to/src/foo/", RebaseOne(scope, "foo/", "", "//"));
- EXPECT_EQ("C:/path/to/src/tools/gn/foo", RebaseOne(scope, "foo", "", "."));
- EXPECT_EQ("C:/path/to/other/tools",
- RebaseOne(scope, "//../other/tools", "", "//"));
- EXPECT_EQ("C:/path/to/src/foo/bar",
- RebaseOne(scope, "//../src/foo/bar", "", "//"));
- EXPECT_EQ("C:/path/to", RebaseOne(scope, "//..", "", "//"));
- EXPECT_EQ("C:/path", RebaseOne(scope, "../../../..", "", "."));
- EXPECT_EQ("C:/path/to/external/dir/",
- RebaseOne(scope, "//../external/dir/", "", "//"));
-
-#else
- setup.build_settings()->SetRootPath(base::FilePath("/path/to/src"));
- EXPECT_EQ("/path/to/src", RebaseOne(scope, ".", "", "//"));
- EXPECT_EQ("/path/to/src/", RebaseOne(scope, "//", "", "//"));
- EXPECT_EQ("/path/to/src/foo", RebaseOne(scope, "foo", "", "//"));
- EXPECT_EQ("/path/to/src/foo/", RebaseOne(scope, "foo/", "", "//"));
- EXPECT_EQ("/path/to/src/tools/gn/foo", RebaseOne(scope, "foo", "", "."));
- EXPECT_EQ("/path/to/other/tools",
- RebaseOne(scope, "//../other/tools", "", "//"));
- EXPECT_EQ("/path/to/src/foo/bar",
- RebaseOne(scope, "//../src/foo/bar", "", "//"));
- EXPECT_EQ("/path/to", RebaseOne(scope, "//..", "", "//"));
- EXPECT_EQ("/path", RebaseOne(scope, "../../../..", "", "."));
- EXPECT_EQ("/path/to/external/dir/",
- RebaseOne(scope, "//../external/dir/", "", "//"));
-#endif
-}
-
-TEST(RebasePath, StringsSystemPaths) {
- TestWithScope setup;
- Scope* scope = setup.scope();
-
-#if defined(OS_WIN)
- setup.build_settings()->SetBuildDir(SourceDir("C:/ssd/out/Debug"));
- setup.build_settings()->SetRootPath(base::FilePath(L"C:/hdd/src"));
-
- // Test system absolute to-dir.
- EXPECT_EQ("../../ssd/out/Debug",
- RebaseOne(scope, ".", "//", "C:/ssd/out/Debug"));
- EXPECT_EQ("../../ssd/out/Debug/",
- RebaseOne(scope, "./", "//", "C:/ssd/out/Debug"));
- EXPECT_EQ("../../ssd/out/Debug/foo",
- RebaseOne(scope, "foo", "//", "C:/ssd/out/Debug"));
- EXPECT_EQ("../../ssd/out/Debug/foo/",
- RebaseOne(scope, "foo/", "//", "C:/ssd/out/Debug"));
-
- // Test system absolute from-dir.
- EXPECT_EQ("../../../hdd/src",
- RebaseOne(scope, ".", "C:/ssd/out/Debug", "//"));
- EXPECT_EQ("../../../hdd/src/",
- RebaseOne(scope, "./", "C:/ssd/out/Debug", "//"));
- EXPECT_EQ("../../../hdd/src/foo",
- RebaseOne(scope, "foo", "C:/ssd/out/Debug", "//"));
- EXPECT_EQ("../../../hdd/src/foo/",
- RebaseOne(scope, "foo/", "C:/ssd/out/Debug", "//"));
-#else
- setup.build_settings()->SetBuildDir(SourceDir("/ssd/out/Debug"));
- setup.build_settings()->SetRootPath(base::FilePath("/hdd/src"));
-
- // Test system absolute to-dir.
- EXPECT_EQ("../../ssd/out/Debug",
- RebaseOne(scope, ".", "//", "/ssd/out/Debug"));
- EXPECT_EQ("../../ssd/out/Debug/",
- RebaseOne(scope, "./", "//", "/ssd/out/Debug"));
- EXPECT_EQ("../../ssd/out/Debug/foo",
- RebaseOne(scope, "foo", "//", "/ssd/out/Debug"));
- EXPECT_EQ("../../ssd/out/Debug/foo/",
- RebaseOne(scope, "foo/", "//", "/ssd/out/Debug"));
-
- // Test system absolute from-dir.
- EXPECT_EQ("../../../hdd/src",
- RebaseOne(scope, ".", "/ssd/out/Debug", "//"));
- EXPECT_EQ("../../../hdd/src/",
- RebaseOne(scope, "./", "/ssd/out/Debug", "//"));
- EXPECT_EQ("../../../hdd/src/foo",
- RebaseOne(scope, "foo", "/ssd/out/Debug", "//"));
- EXPECT_EQ("../../../hdd/src/foo/",
- RebaseOne(scope, "foo/", "/ssd/out/Debug", "//"));
-#endif
-}
-
-// Test list input.
-TEST(RebasePath, List) {
- TestWithScope setup;
- setup.scope()->set_source_dir(SourceDir("//tools/gn/"));
-
- std::vector<Value> args;
- args.push_back(Value(nullptr, Value::LIST));
- args[0].list_value().push_back(Value(nullptr, "foo.txt"));
- args[0].list_value().push_back(Value(nullptr, "bar.txt"));
- args.push_back(Value(nullptr, "//out/Debug/"));
- args.push_back(Value(nullptr, "."));
-
- Err err;
- FunctionCallNode function;
- Value ret = functions::RunRebasePath(setup.scope(), &function, args, &err);
- EXPECT_FALSE(err.has_error());
-
- ASSERT_EQ(Value::LIST, ret.type());
- ASSERT_EQ(2u, ret.list_value().size());
-
- EXPECT_EQ("../../tools/gn/foo.txt", ret.list_value()[0].string_value());
- EXPECT_EQ("../../tools/gn/bar.txt", ret.list_value()[1].string_value());
-}
-
-TEST(RebasePath, Errors) {
- TestWithScope setup;
-
- // No arg input should issue an error.
- Err err;
- std::vector<Value> args;
- FunctionCallNode function;
- Value ret = functions::RunRebasePath(setup.scope(), &function, args, &err);
- EXPECT_TRUE(err.has_error());
-}
diff --git a/chromium/tools/gn/function_set_default_toolchain.cc b/chromium/tools/gn/function_set_default_toolchain.cc
deleted file mode 100644
index f04cba88031..00000000000
--- a/chromium/tools/gn/function_set_default_toolchain.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/build_settings.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/loader.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/settings.h"
-
-namespace functions {
-
-const char kSetDefaultToolchain[] = "set_default_toolchain";
-const char kSetDefaultToolchain_HelpShort[] =
- "set_default_toolchain: Sets the default toolchain name.";
-const char kSetDefaultToolchain_Help[] =
- R"(set_default_toolchain: Sets the default toolchain name.
-
- set_default_toolchain(toolchain_label)
-
- The given label should identify a toolchain definition (see "gn help
- toolchain"). This toolchain will be used for all targets unless otherwise
- specified.
-
- This function is only valid to call during the processing of the build
- configuration file. Since the build configuration file is processed
- separately for each toolchain, this function will be a no-op when called
- under any non-default toolchains.
-
- For example, the default toolchain should be appropriate for the current
- environment. If the current environment is 32-bit and somebody references a
- target with a 64-bit toolchain, we wouldn't want processing of the build
- config file for the 64-bit toolchain to reset the default toolchain to
- 64-bit, we want to keep it 32-bits.
-
-Argument
-
- toolchain_label
- Toolchain name.
-
-Example
-
- # Set default toolchain only has an effect when run in the context of the
- # default toolchain. Pick the right one according to the current CPU
- # architecture.
- if (target_cpu == "x64") {
- set_default_toolchain("//toolchains:64")
- } else if (target_cpu == "x86") {
- set_default_toolchain("//toolchains:32")
- }
-)";
-
-Value RunSetDefaultToolchain(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- if (!scope->IsProcessingBuildConfig()) {
- *err = Err(function->function(), "Must be called from build config.",
- "set_default_toolchain can only be called from the build configuration "
- "file.");
- return Value();
- }
-
- // When the loader is expecting the default toolchain to be set, it will set
- // this key on the scope to point to the destination.
- Label* default_toolchain_dest = static_cast<Label*>(
- scope->GetProperty(Loader::kDefaultToolchainKey, nullptr));
- if (!default_toolchain_dest)
- return Value();
-
- const SourceDir& current_dir = scope->GetSourceDir();
- const Label& default_toolchain = ToolchainLabelForScope(scope);
-
- if (!EnsureSingleStringArg(function, args, err))
- return Value();
- Label toolchain_label(
- Label::Resolve(current_dir, default_toolchain, args[0], err));
- if (toolchain_label.is_null())
- return Value();
-
- *default_toolchain_dest = toolchain_label;
- return Value();
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/function_set_defaults.cc b/chromium/tools/gn/function_set_defaults.cc
deleted file mode 100644
index a2a14afcc7d..00000000000
--- a/chromium/tools/gn/function_set_defaults.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/err.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-
-namespace functions {
-
-const char kSetDefaults[] = "set_defaults";
-const char kSetDefaults_HelpShort[] =
- "set_defaults: Set default values for a target type.";
-const char kSetDefaults_Help[] =
- R"(set_defaults: Set default values for a target type.
-
- set_defaults(<target_type_name>) { <values...> }
-
- Sets the default values for a given target type. Whenever target_type_name is
- seen in the future, the values specified in set_default's block will be
- copied into the current scope.
-
- When the target type is used, the variable copying is very strict. If a
- variable with that name is already in scope, the build will fail with an
- error.
-
- set_defaults can be used for built-in target types ("executable",
- "shared_library", etc.) and custom ones defined via the "template" command.
- It can be called more than once and the most recent call in any scope will
- apply, but there is no way to refer to the previous defaults and modify them
- (each call to set_defaults must supply a complete list of all defaults it
- wants). If you want to share defaults, store them in a separate variable.
-
-Example
-
- set_defaults("static_library") {
- configs = [ "//tools/mything:settings" ]
- }
-
- static_library("mylib")
- # The configs will be auto-populated as above. You can remove it if
- # you don't want the default for a particular default:
- configs -= [ "//tools/mything:settings" ]
- }
-)";
-
-Value RunSetDefaults(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- if (!EnsureSingleStringArg(function, args, err))
- return Value();
- const std::string& target_type(args[0].string_value());
-
- if (!block) {
- FillNeedsBlockError(function, err);
- return Value();
- }
-
- // Run the block for the rule invocation.
- Scope block_scope(scope);
- block->Execute(&block_scope, err);
- if (err->has_error())
- return Value();
-
- // Now copy the values set on the scope we made into the free-floating one
- // (with no containing scope) used to hold the target defaults.
- Scope* dest = scope->MakeTargetDefaults(target_type);
- block_scope.NonRecursiveMergeTo(dest, Scope::MergeOptions(), function,
- "<SHOULD NOT FAIL>", err);
- return Value();
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/function_template.cc b/chromium/tools/gn/function_template.cc
deleted file mode 100644
index f5ea7b822a1..00000000000
--- a/chromium/tools/gn/function_template.cc
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/functions.h"
-
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/template.h"
-#include "tools/gn/value.h"
-
-namespace functions {
-
-const char kTemplate[] = "template";
-const char kTemplate_HelpShort[] =
- "template: Define a template rule.";
-const char kTemplate_Help[] =
- R"(template: Define a template rule.
-
- A template defines a custom name that acts like a function. It provides a way
- to add to the built-in target types.
-
- The template() function is used to declare a template. To invoke the
- template, just use the name of the template like any other target type.
-
- Often you will want to declare your template in a special file that other
- files will import (see "gn help import") so your template rule can be shared
- across build files.
-
-Variables and templates:
-
- When you call template() it creates a closure around all variables currently
- in scope with the code in the template block. When the template is invoked,
- the closure will be executed.
-
- When the template is invoked, the code in the caller is executed and passed
- to the template code as an implicit "invoker" variable. The template uses
- this to read state out of the invoking code.
-
- One thing explicitly excluded from the closure is the "current directory"
- against which relative file names are resolved. The current directory will be
- that of the invoking code, since typically that code specifies the file
- names. This means all files internal to the template should use absolute
- names.
-
- A template will typically forward some or all variables from the invoking
- scope to a target that it defines. Often, such variables might be optional.
- Use the pattern:
-
- if (defined(invoker.deps)) {
- deps = invoker.deps
- }
-
- The function forward_variables_from() provides a shortcut to forward one or
- more or possibly all variables in this manner:
-
- forward_variables_from(invoker, ["deps", "public_deps"])
-
-Target naming
-
- Your template should almost always define a built-in target with the name the
- template invoker specified. For example, if you have an IDL template and
- somebody does:
- idl("foo") {...
- you will normally want this to expand to something defining a source_set or
- static_library named "foo" (among other things you may need). This way, when
- another target specifies a dependency on "foo", the static_library or
- source_set will be linked.
-
- It is also important that any other targets your template expands to have
- unique names, or you will get collisions.
-
- Access the invoking name in your template via the implicit "target_name"
- variable. This should also be the basis for how other targets that a template
- expands to ensure uniqueness.
-
- A typical example would be a template that defines an action to generate some
- source files, and a source_set to compile that source. Your template would
- name the source_set "target_name" because that's what you want external
- targets to depend on to link your code. And you would name the action
- something like "${target_name}_action" to make it unique. The source set
- would have a dependency on the action to make it run.
-
-Overriding builtin targets
-
- You can use template to redefine a built-in target in which case your template
- takes a precedence over the built-in one. All uses of the target from within
- the template definition will refer to the built-in target which makes it
- possible to extend the behavior of the built-in target:
-
- template("shared_library") {
- shared_library(shlib) {
- forward_variables_from(invoker, "*")
- ...
- }
- }
-
-Example of defining a template
-
- template("my_idl") {
- # Be nice and help callers debug problems by checking that the variables
- # the template requires are defined. This gives a nice message rather than
- # giving the user an error about an undefined variable in the file defining
- # the template
- #
- # You can also use defined() to give default values to variables
- # unspecified by the invoker.
- assert(defined(invoker.sources),
- "Need sources in $target_name listing the idl files.")
-
- # Name of the intermediate target that does the code gen. This must
- # incorporate the target name so it's unique across template
- # instantiations.
- code_gen_target_name = target_name + "_code_gen"
-
- # Intermediate target to convert IDL to C source. Note that the name is
- # based on the name the invoker of the template specified. This way, each
- # time the template is invoked we get a unique intermediate action name
- # (since all target names are in the global scope).
- action_foreach(code_gen_target_name) {
- # Access the scope defined by the invoker via the implicit "invoker"
- # variable.
- sources = invoker.sources
-
- # Note that we need an absolute path for our script file name. The
- # current directory when executing this code will be that of the invoker
- # (this is why we can use the "sources" directly above without having to
- # rebase all of the paths). But if we need to reference a script relative
- # to the template file, we'll need to use an absolute path instead.
- script = "//tools/idl/idl_code_generator.py"
-
- # Tell GN how to expand output names given the sources.
- # See "gn help source_expansion" for more.
- outputs = [ "$target_gen_dir/{{source_name_part}}.cc",
- "$target_gen_dir/{{source_name_part}}.h" ]
- }
-
- # Name the source set the same as the template invocation so instancing
- # this template produces something that other targets can link to in their
- # deps.
- source_set(target_name) {
- # Generates the list of sources, we get these from the action_foreach
- # above.
- sources = get_target_outputs(":$code_gen_target_name")
-
- # This target depends on the files produced by the above code gen target.
- deps = [ ":$code_gen_target_name" ]
- }
- }
-
-Example of invoking the resulting template
-
- # This calls the template code above, defining target_name to be
- # "foo_idl_files" and "invoker" to be the set of stuff defined in the curly
- # brackets.
- my_idl("foo_idl_files") {
- # Goes into the template as "invoker.sources".
- sources = [ "foo.idl", "bar.idl" ]
- }
-
- # Here is a target that depends on our template.
- executable("my_exe") {
- # Depend on the name we gave the template call above. Internally, this will
- # produce a dependency from executable to the source_set inside the
- # template (since it has this name), which will in turn depend on the code
- # gen action.
- deps = [ ":foo_idl_files" ]
- }
-)";
-
-Value RunTemplate(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- // Of course you can have configs and targets in a template. But here, we're
- // not actually executing the block, only declaring it. Marking the template
- // declaration as non-nestable means that you can't put it inside a target,
- // for example.
- NonNestableBlock non_nestable(scope, function, "template");
- if (!non_nestable.Enter(err))
- return Value();
-
- // TODO(brettw) determine if the function is built-in and throw an error if
- // it is.
- if (args.size() != 1) {
- *err = Err(function->function(),
- "Need exactly one string arg to template.");
- return Value();
- }
- if (!args[0].VerifyTypeIs(Value::STRING, err))
- return Value();
- std::string template_name = args[0].string_value();
-
- const Template* existing_template = scope->GetTemplate(template_name);
- if (existing_template) {
- *err = Err(function, "Duplicate template definition.",
- "A template with this name was already defined.");
- err->AppendSubErr(Err(existing_template->GetDefinitionRange(),
- "Previous definition."));
- return Value();
- }
-
- scope->AddTemplate(template_name, new Template(scope, function));
-
- // The template object above created a closure around the variables in the
- // current scope. The template code will execute in that context when it's
- // invoked. But this means that any variables defined above that are used
- // by the template won't get marked used just by defining the template. The
- // result can be spurious unused variable errors.
- //
- // The "right" thing to do would be to walk the syntax tree inside the
- // template, find all identifier references, and mark those variables used.
- // This is annoying and error-prone to implement and takes extra time to run
- // for this narrow use case.
- //
- // Templates are most often defined in .gni files which don't get
- // used-variable checking anyway, and this case is annoying enough that the
- // incremental value of unused variable checking isn't worth the
- // alternatives. So all values in scope before this template definition are
- // exempted from unused variable checking.
- scope->MarkAllUsed();
-
- return Value();
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/function_template_unittest.cc b/chromium/tools/gn/function_template_unittest.cc
deleted file mode 100644
index cd98423a48c..00000000000
--- a/chromium/tools/gn/function_template_unittest.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/test_with_scope.h"
-
-// Checks that variables used inside template definitions aren't reported
-// unused if they were declared above the template.
-TEST(FunctionTemplate, MarkUsed) {
- TestWithScope setup;
- TestParseInput input(
- "a = 1\n" // Unused outside of template.
- "template(\"templ\") {\n"
- " print(a)\n"
- "}\n");
- ASSERT_FALSE(input.has_error()) << input.parse_err().message();
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- // Normally the loader calls CheckForUnusedVars() when it loads a file
- // since normal blocks don't do this check. To avoid having to make this
- // test much more complicated, just explicitly do the check to make sure
- // things are marked properly.
- setup.scope()->CheckForUnusedVars(&err);
- EXPECT_FALSE(err.has_error());
-}
diff --git a/chromium/tools/gn/function_toolchain.cc b/chromium/tools/gn/function_toolchain.cc
deleted file mode 100644
index 19eaea85963..00000000000
--- a/chromium/tools/gn/function_toolchain.cc
+++ /dev/null
@@ -1,1099 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <limits>
-#include <memory>
-#include <utility>
-
-#include "tools/gn/err.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/label.h"
-#include "tools/gn/label_ptr.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/tool.h"
-#include "tools/gn/toolchain.h"
-#include "tools/gn/value_extractors.h"
-#include "tools/gn/variables.h"
-
-namespace functions {
-
-namespace {
-
-// This is just a unique value to take the address of to use as the key for
-// the toolchain property on a scope.
-const int kToolchainPropertyKey = 0;
-
-bool ReadBool(Scope* scope,
- const char* var,
- Tool* tool,
- void (Tool::*set)(bool),
- Err* err) {
- const Value* v = scope->GetValue(var, true);
- if (!v)
- return true; // Not present is fine.
- if (!v->VerifyTypeIs(Value::BOOLEAN, err))
- return false;
-
- (tool->*set)(v->boolean_value());
- return true;
-}
-
-// Reads the given string from the scope (if present) and puts the result into
-// dest. If the value is not a string, sets the error and returns false.
-bool ReadString(Scope* scope,
- const char* var,
- Tool* tool,
- void (Tool::*set)(std::string),
- Err* err) {
- const Value* v = scope->GetValue(var, true);
- if (!v)
- return true; // Not present is fine.
- if (!v->VerifyTypeIs(Value::STRING, err))
- return false;
-
- (tool->*set)(v->string_value());
- return true;
-}
-
-// Reads the given label from the scope (if present) and puts the result into
-// dest. If the value is not a label, sets the error and returns false.
-bool ReadLabel(Scope* scope,
- const char* var,
- Tool* tool,
- const Label& current_toolchain,
- void (Tool::*set)(LabelPtrPair<Pool>),
- Err* err) {
- const Value* v = scope->GetValue(var, true);
- if (!v)
- return true; // Not present is fine.
-
- Label label =
- Label::Resolve(scope->GetSourceDir(), current_toolchain, *v, err);
- if (err->has_error())
- return false;
-
- LabelPtrPair<Pool> pair(label);
- pair.origin = tool->defined_from();
-
- (tool->*set)(std::move(pair));
- return true;
-}
-
-// Calls the given validate function on each type in the list. On failure,
-// sets the error, blame the value, and return false.
-bool ValidateSubstitutionList(const std::vector<SubstitutionType>& list,
- bool (*validate)(SubstitutionType),
- const Value* origin,
- Err* err) {
- for (const auto& cur_type : list) {
- if (!validate(cur_type)) {
- *err = Err(*origin, "Pattern not valid here.",
- "You used the pattern " + std::string(kSubstitutionNames[cur_type]) +
- " which is not valid\nfor this variable.");
- return false;
- }
- }
- return true;
-}
-
-bool ReadPattern(Scope* scope,
- const char* name,
- bool (*validate)(SubstitutionType),
- Tool* tool,
- void (Tool::*set)(SubstitutionPattern),
- Err* err) {
- const Value* value = scope->GetValue(name, true);
- if (!value)
- return true; // Not present is fine.
- if (!value->VerifyTypeIs(Value::STRING, err))
- return false;
-
- SubstitutionPattern pattern;
- if (!pattern.Parse(*value, err))
- return false;
- if (!ValidateSubstitutionList(pattern.required_types(), validate, value, err))
- return false;
-
- (tool->*set)(std::move(pattern));
- return true;
-}
-
-bool ReadPatternList(Scope* scope,
- const char* name,
- bool (*validate)(SubstitutionType),
- Tool* tool,
- void (Tool::*set)(SubstitutionList),
- Err* err) {
- const Value* value = scope->GetValue(name, true);
- if (!value)
- return true; // Not present is fine.
- if (!value->VerifyTypeIs(Value::LIST, err))
- return false;
-
- SubstitutionList list;
- if (!list.Parse(*value, err))
- return false;
-
- // Validate the right kinds of patterns are used.
- if (!ValidateSubstitutionList(list.required_types(), validate, value, err))
- return false;
-
- (tool->*set)(std::move(list));
- return true;
-}
-
-bool ReadOutputExtension(Scope* scope, Tool* tool, Err* err) {
- const Value* value = scope->GetValue("default_output_extension", true);
- if (!value)
- return true; // Not present is fine.
- if (!value->VerifyTypeIs(Value::STRING, err))
- return false;
-
- if (value->string_value().empty())
- return true; // Accept empty string.
-
- if (value->string_value()[0] != '.') {
- *err = Err(*value, "default_output_extension must begin with a '.'");
- return false;
- }
-
- tool->set_default_output_extension(value->string_value());
- return true;
-}
-
-bool ReadPrecompiledHeaderType(Scope* scope, Tool* tool, Err* err) {
- const Value* value = scope->GetValue("precompiled_header_type", true);
- if (!value)
- return true; // Not present is fine.
- if (!value->VerifyTypeIs(Value::STRING, err))
- return false;
-
- if (value->string_value().empty())
- return true; // Accept empty string, do nothing (default is "no PCH").
-
- if (value->string_value() == "gcc") {
- tool->set_precompiled_header_type(Tool::PCH_GCC);
- return true;
- } else if (value->string_value() == "msvc") {
- tool->set_precompiled_header_type(Tool::PCH_MSVC);
- return true;
- }
- *err = Err(*value, "Invalid precompiled_header_type",
- "Must either be empty, \"gcc\", or \"msvc\".");
- return false;
-}
-
-bool ReadDepsFormat(Scope* scope, Tool* tool, Err* err) {
- const Value* value = scope->GetValue("depsformat", true);
- if (!value)
- return true; // Not present is fine.
- if (!value->VerifyTypeIs(Value::STRING, err))
- return false;
-
- if (value->string_value() == "gcc") {
- tool->set_depsformat(Tool::DEPS_GCC);
- } else if (value->string_value() == "msvc") {
- tool->set_depsformat(Tool::DEPS_MSVC);
- } else {
- *err = Err(*value, "Deps format must be \"gcc\" or \"msvc\".");
- return false;
- }
- return true;
-}
-
-bool IsCompilerTool(Toolchain::ToolType type) {
- return type == Toolchain::TYPE_CC ||
- type == Toolchain::TYPE_CXX ||
- type == Toolchain::TYPE_OBJC ||
- type == Toolchain::TYPE_OBJCXX ||
- type == Toolchain::TYPE_RC ||
- type == Toolchain::TYPE_ASM;
-}
-
-bool IsLinkerTool(Toolchain::ToolType type) {
- // "alink" is not counted as in the generic "linker" tool list.
- return type == Toolchain::TYPE_SOLINK ||
- type == Toolchain::TYPE_SOLINK_MODULE ||
- type == Toolchain::TYPE_LINK;
-}
-
-bool IsPatternInOutputList(const SubstitutionList& output_list,
- const SubstitutionPattern& pattern) {
- for (const auto& cur : output_list.list()) {
- if (pattern.ranges().size() == cur.ranges().size() &&
- std::equal(pattern.ranges().begin(), pattern.ranges().end(),
- cur.ranges().begin()))
- return true;
- }
- return false;
-}
-
-
-bool ValidateOutputs(const Tool* tool, Err* err) {
- if (tool->outputs().list().empty()) {
- *err = Err(tool->defined_from(),
- "\"outputs\" must be specified for this tool.");
- return false;
- }
- return true;
-}
-
-// Validates either link_output or depend_output. To generalize to either, pass
-// the associated pattern, and the variable name that should appear in error
-// messages.
-bool ValidateLinkAndDependOutput(const Tool* tool,
- Toolchain::ToolType tool_type,
- const SubstitutionPattern& pattern,
- const char* variable_name,
- Err* err) {
- if (pattern.empty())
- return true; // Empty is always OK.
-
- // It should only be specified for certain tool types.
- if (tool_type != Toolchain::TYPE_SOLINK &&
- tool_type != Toolchain::TYPE_SOLINK_MODULE) {
- *err = Err(tool->defined_from(),
- "This tool specifies a " + std::string(variable_name) + ".",
- "This is only valid for solink and solink_module tools.");
- return false;
- }
-
- if (!IsPatternInOutputList(tool->outputs(), pattern)) {
- *err = Err(tool->defined_from(), "This tool's link_output is bad.",
- "It must match one of the outputs.");
- return false;
- }
-
- return true;
-}
-
-bool ValidateRuntimeOutputs(const Tool* tool,
- Toolchain::ToolType tool_type,
- Err* err) {
- if (tool->runtime_outputs().list().empty())
- return true; // Empty is always OK.
-
- if (!IsLinkerTool(tool_type)) {
- *err = Err(tool->defined_from(), "This tool specifies runtime_outputs.",
- "This is only valid for linker tools (alink doesn't count).");
- return false;
- }
-
- for (const SubstitutionPattern& pattern : tool->runtime_outputs().list()) {
- if (!IsPatternInOutputList(tool->outputs(), pattern)) {
- *err = Err(tool->defined_from(), "This tool's runtime_outputs is bad.",
- "It must be a subset of the outputs. The bad one is:\n " +
- pattern.AsString());
- return false;
- }
- }
- return true;
-}
-
-} // namespace
-
-// toolchain -------------------------------------------------------------------
-
-const char kToolchain[] = "toolchain";
-const char kToolchain_HelpShort[] =
- "toolchain: Defines a toolchain.";
-const char kToolchain_Help[] =
- R"*(toolchain: Defines a toolchain.
-
- A toolchain is a set of commands and build flags used to compile the source
- code. The toolchain() function defines these commands.
-
-Toolchain overview
-
- You can have more than one toolchain in use at once in a build and a target
- can exist simultaneously in multiple toolchains. A build file is executed
- once for each toolchain it is referenced in so the GN code can vary all
- parameters of each target (or which targets exist) on a per-toolchain basis.
-
- When you have a simple build with only one toolchain, the build config file
- is loaded only once at the beginning of the build. It must call
- set_default_toolchain() (see "gn help set_default_toolchain") to tell GN the
- label of the toolchain definition to use. The "toolchain_args" section of the
- toolchain definition is ignored.
-
- When a target has a dependency on a target using different toolchain (see "gn
- help labels" for how to specify this), GN will start a build using that
- secondary toolchain to resolve the target. GN will load the build config file
- with the build arguments overridden as specified in the toolchain_args.
- Because the default toolchain is already known, calls to
- set_default_toolchain() are ignored.
-
- To load a file in an alternate toolchain, GN does the following:
-
- 1. Loads the file with the toolchain definition in it (as determined by the
- toolchain label).
- 2. Re-runs the master build configuration file, applying the arguments
- specified by the toolchain_args section of the toolchain definition.
- 3. Loads the destination build file in the context of the configuration file
- in the previous step.
-
- The toolchain configuration is two-way. In the default toolchain (i.e. the
- main build target) the configuration flows from the build config file to the
- toolchain. The build config file looks at the state of the build (OS type,
- CPU architecture, etc.) and decides which toolchain to use (via
- set_default_toolchain()). In secondary toolchains, the configuration flows
- from the toolchain to the build config file: the "toolchain_args" in the
- toolchain definition specifies the arguments to re-invoke the build.
-
-Functions and variables
-
- tool()
- The tool() function call specifies the commands commands to run for a given
- step. See "gn help tool".
-
- toolchain_args
- Overrides for build arguments to pass to the toolchain when invoking it.
- This is a variable of type "scope" where the variable names correspond to
- variables in declare_args() blocks.
-
- When you specify a target using an alternate toolchain, the master build
- configuration file is re-interpreted in the context of that toolchain.
- toolchain_args allows you to control the arguments passed into this
- alternate invocation of the build.
-
- Any default system arguments or arguments passed in via "gn args" will also
- be passed to the alternate invocation unless explicitly overridden by
- toolchain_args.
-
- The toolchain_args will be ignored when the toolchain being defined is the
- default. In this case, it's expected you want the default argument values.
-
- See also "gn help buildargs" for an overview of these arguments.
-
- deps
- Dependencies of this toolchain. These dependencies will be resolved before
- any target in the toolchain is compiled. To avoid circular dependencies
- these must be targets defined in another toolchain.
-
- This is expressed as a list of targets, and generally these targets will
- always specify a toolchain:
- deps = [ "//foo/bar:baz(//build/toolchain:bootstrap)" ]
-
- This concept is somewhat inefficient to express in Ninja (it requires a lot
- of duplicate of rules) so should only be used when absolutely necessary.
-
-Example of defining a toolchain
-
- toolchain("32") {
- tool("cc") {
- command = "gcc {{source}}"
- ...
- }
-
- toolchain_args = {
- use_doom_melon = true # Doom melon always required for 32-bit builds.
- current_cpu = "x86"
- }
- }
-
- toolchain("64") {
- tool("cc") {
- command = "gcc {{source}}"
- ...
- }
-
- toolchain_args = {
- # use_doom_melon is not overridden here, it will take the default.
- current_cpu = "x64"
- }
- }
-
-Example of cross-toolchain dependencies
-
- If a 64-bit target wants to depend on a 32-bit binary, it would specify a
- dependency using data_deps (data deps are like deps that are only needed at
- runtime and aren't linked, since you can't link a 32-bit and a 64-bit
- library).
-
- executable("my_program") {
- ...
- if (target_cpu == "x64") {
- # The 64-bit build needs this 32-bit helper.
- data_deps = [ ":helper(//toolchains:32)" ]
- }
- }
-
- if (target_cpu == "x86") {
- # Our helper library is only compiled in 32-bits.
- shared_library("helper") {
- ...
- }
- }
-)*";
-
-Value RunToolchain(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- NonNestableBlock non_nestable(scope, function, "toolchain");
- if (!non_nestable.Enter(err))
- return Value();
-
- if (!EnsureNotProcessingImport(function, scope, err) ||
- !EnsureNotProcessingBuildConfig(function, scope, err))
- return Value();
-
- // Note that we don't want to use MakeLabelForScope since that will include
- // the toolchain name in the label, and toolchain labels don't themselves
- // have toolchain names.
- const SourceDir& input_dir = scope->GetSourceDir();
- Label label(input_dir, args[0].string_value());
- if (g_scheduler->verbose_logging())
- g_scheduler->Log("Defining toolchain", label.GetUserVisibleName(false));
-
- // This object will actually be copied into the one owned by the toolchain
- // manager, but that has to be done in the lock.
- std::unique_ptr<Toolchain> toolchain = std::make_unique<Toolchain>(
- scope->settings(), label, scope->build_dependency_files());
- toolchain->set_defined_from(function);
- toolchain->visibility().SetPublic();
-
- Scope block_scope(scope);
- block_scope.SetProperty(&kToolchainPropertyKey, toolchain.get());
- block->Execute(&block_scope, err);
- block_scope.SetProperty(&kToolchainPropertyKey, nullptr);
- if (err->has_error())
- return Value();
-
- // Read deps (if any).
- const Value* deps_value = block_scope.GetValue(variables::kDeps, true);
- if (deps_value) {
- ExtractListOfLabels(
- *deps_value, block_scope.GetSourceDir(),
- ToolchainLabelForScope(&block_scope), &toolchain->deps(), err);
- if (err->has_error())
- return Value();
- }
-
- // Read toolchain args (if any).
- const Value* toolchain_args = block_scope.GetValue("toolchain_args", true);
- if (toolchain_args) {
- if (!toolchain_args->VerifyTypeIs(Value::SCOPE, err))
- return Value();
-
- Scope::KeyValueMap values;
- toolchain_args->scope_value()->GetCurrentScopeValues(&values);
- toolchain->args() = values;
- }
-
- if (!block_scope.CheckForUnusedVars(err))
- return Value();
-
- // Save this toolchain.
- toolchain->ToolchainSetupComplete();
- Scope::ItemVector* collector = scope->GetItemCollector();
- if (!collector) {
- *err = Err(function, "Can't define a toolchain in this context.");
- return Value();
- }
- collector->push_back(std::move(toolchain));
- return Value();
-}
-
-// tool ------------------------------------------------------------------------
-
-const char kTool[] = "tool";
-const char kTool_HelpShort[] =
- "tool: Specify arguments to a toolchain tool.";
-const char kTool_Help[] =
- R"(tool: Specify arguments to a toolchain tool.
-
-Usage
-
- tool(<tool type>) {
- <tool variables...>
- }
-
-Tool types
-
- Compiler tools:
- "cc": C compiler
- "cxx": C++ compiler
- "objc": Objective C compiler
- "objcxx": Objective C++ compiler
- "rc": Resource compiler (Windows .rc files)
- "asm": Assembler
-
- Linker tools:
- "alink": Linker for static libraries (archives)
- "solink": Linker for shared libraries
- "link": Linker for executables
-
- Other tools:
- "stamp": Tool for creating stamp files
- "copy": Tool to copy files.
- "action": Defaults for actions
-
- Platform specific tools:
- "copy_bundle_data": [iOS, macOS] Tool to copy files in a bundle.
- "compile_xcassets": [iOS, macOS] Tool to compile asset catalogs.
-
-Tool variables
-
- command [string with substitutions]
- Valid for: all tools except "action" (required)
-
- The command to run.
-
- default_output_dir [string with substitutions]
- Valid for: linker tools
-
- Default directory name for the output file relative to the
- root_build_dir. It can contain other substitution patterns. This will
- be the default value for the {{output_dir}} expansion (discussed below)
- but will be overridden by the "output_dir" variable in a target, if one
- is specified.
-
- GN doesn't do anything with this string other than pass it along,
- potentially with target-specific overrides. It is the tool's job to use
- the expansion so that the files will be in the right place.
-
- default_output_extension [string]
- Valid for: linker tools
-
- Extension for the main output of a linkable tool. It includes the
- leading dot. This will be the default value for the
- {{output_extension}} expansion (discussed below) but will be overridden
- by by the "output extension" variable in a target, if one is specified.
- Empty string means no extension.
-
- GN doesn't actually do anything with this extension other than pass it
- along, potentially with target-specific overrides. One would typically
- use the {{output_extension}} value in the "outputs" to read this value.
-
- Example: default_output_extension = ".exe"
-
- depfile [string with substitutions]
- Valid for: compiler tools (optional)
-
- If the tool can write ".d" files, this specifies the name of the
- resulting file. These files are used to list header file dependencies
- (or other implicit input dependencies) that are discovered at build
- time. See also "depsformat".
-
- Example: depfile = "{{output}}.d"
-
- depsformat [string]
- Valid for: compiler tools (when depfile is specified)
-
- Format for the deps outputs. This is either "gcc" or "msvc". See the
- ninja documentation for "deps" for more information.
-
- Example: depsformat = "gcc"
-
- description [string with substitutions, optional]
- Valid for: all tools
-
- What to print when the command is run.
-
- Example: description = "Compiling {{source}}"
-
- lib_switch [string, optional, link tools only]
- lib_dir_switch [string, optional, link tools only]
- Valid for: Linker tools except "alink"
-
- These strings will be prepended to the libraries and library search
- directories, respectively, because linkers differ on how specify them.
- If you specified:
- lib_switch = "-l"
- lib_dir_switch = "-L"
- then the "{{libs}}" expansion for [ "freetype", "expat"] would be
- "-lfreetype -lexpat".
-
- outputs [list of strings with substitutions]
- Valid for: Linker and compiler tools (required)
-
- An array of names for the output files the tool produces. These are
- relative to the build output directory. There must always be at least
- one output file. There can be more than one output (a linker might
- produce a library and an import library, for example).
-
- This array just declares to GN what files the tool will produce. It is
- your responsibility to specify the tool command that actually produces
- these files.
-
- If you specify more than one output for shared library links, you
- should consider setting link_output, depend_output, and
- runtime_outputs.
-
- Example for a compiler tool that produces .obj files:
- outputs = [
- "{{source_out_dir}}/{{source_name_part}}.obj"
- ]
-
- Example for a linker tool that produces a .dll and a .lib. The use of
- {{target_output_name}}, {{output_extension}} and {{output_dir}} allows
- the target to override these values.
- outputs = [
- "{{output_dir}}/{{target_output_name}}"
- "{{output_extension}}",
- "{{output_dir}}/{{target_output_name}}.lib",
- ]
-
- pool [label, optional]
- Valid for: all tools (optional)
-
- Label of the pool to use for the tool. Pools are used to limit the
- number of tasks that can execute concurrently during the build.
-
- See also "gn help pool".
-
- link_output [string with substitutions]
- depend_output [string with substitutions]
- Valid for: "solink" only (optional)
-
- These two files specify which of the outputs from the solink tool
- should be used for linking and dependency tracking. These should match
- entries in the "outputs". If unspecified, the first item in the
- "outputs" array will be used for all. See "Separate linking and
- dependencies for shared libraries" below for more.
-
- On Windows, where the tools produce a .dll shared library and a .lib
- import library, you will want the first two to be the import library
- and the third one to be the .dll file. On Linux, if you're not doing
- the separate linking/dependency optimization, all of these should be
- the .so output.
-
- output_prefix [string]
- Valid for: Linker tools (optional)
-
- Prefix to use for the output name. Defaults to empty. This prefix will
- be prepended to the name of the target (or the output_name if one is
- manually specified for it) if the prefix is not already there. The
- result will show up in the {{output_name}} substitution pattern.
-
- Individual targets can opt-out of the output prefix by setting:
- output_prefix_override = true
- (see "gn help output_prefix_override").
-
- This is typically used to prepend "lib" to libraries on
- Posix systems:
- output_prefix = "lib"
-
- precompiled_header_type [string]
- Valid for: "cc", "cxx", "objc", "objcxx"
-
- Type of precompiled headers. If undefined or the empty string,
- precompiled headers will not be used for this tool. Otherwise use "gcc"
- or "msvc".
-
- For precompiled headers to be used for a given target, the target (or a
- config applied to it) must also specify a "precompiled_header" and, for
- "msvc"-style headers, a "precompiled_source" value. If the type is
- "gcc", then both "precompiled_header" and "precompiled_source" must
- resolve to the same file, despite the different formats required for
- each."
-
- See "gn help precompiled_header" for more.
-
- restat [boolean]
- Valid for: all tools (optional, defaults to false)
-
- Requests that Ninja check the file timestamp after this tool has run to
- determine if anything changed. Set this if your tool has the ability to
- skip writing output if the output file has not changed.
-
- Normally, Ninja will assume that when a tool runs the output be new and
- downstream dependents must be rebuild. When this is set to trye, Ninja
- can skip rebuilding downstream dependents for input changes that don't
- actually affect the output.
-
- Example:
- restat = true
-
- rspfile [string with substitutions]
- Valid for: all tools except "action" (optional)
-
- Name of the response file. If empty, no response file will be
- used. See "rspfile_content".
-
- rspfile_content [string with substitutions]
- Valid for: all tools except "action" (required when "rspfile" is used)
-
- The contents to be written to the response file. This may include all
- or part of the command to send to the tool which allows you to get
- around OS command-line length limits.
-
- This example adds the inputs and libraries to a response file, but
- passes the linker flags directly on the command line:
- tool("link") {
- command = "link -o {{output}} {{ldflags}} @{{output}}.rsp"
- rspfile = "{{output}}.rsp"
- rspfile_content = "{{inputs}} {{solibs}} {{libs}}"
- }
-
- runtime_outputs [string list with substitutions]
- Valid for: linker tools
-
- If specified, this list is the subset of the outputs that should be
- added to runtime deps (see "gn help runtime_deps"). By default (if
- runtime_outputs is empty or unspecified), it will be the link_output.
-
-Expansions for tool variables
-
- All paths are relative to the root build directory, which is the current
- directory for running all tools. These expansions are available to all tools:
-
- {{label}}
- The label of the current target. This is typically used in the
- "description" field for link tools. The toolchain will be omitted from
- the label for targets in the default toolchain, and will be included
- for targets in other toolchains.
-
- {{label_name}}
- The short name of the label of the target. This is the part after the
- colon. For "//foo/bar:baz" this will be "baz". Unlike
- {{target_output_name}}, this is not affected by the "output_prefix" in
- the tool or the "output_name" set on the target.
-
- {{output}}
- The relative path and name of the output(s) of the current build step.
- If there is more than one output, this will expand to a list of all of
- them. Example: "out/base/my_file.o"
-
- {{target_gen_dir}}
- {{target_out_dir}}
- The directory of the generated file and output directories,
- respectively, for the current target. There is no trailing slash. See
- also {{output_dir}} for linker tools. Example: "out/base/test"
-
- {{target_output_name}}
- The short name of the current target with no path information, or the
- value of the "output_name" variable if one is specified in the target.
- This will include the "output_prefix" if any. See also {{label_name}}.
-
- Example: "libfoo" for the target named "foo" and an output prefix for
- the linker tool of "lib".
-
-)" // String break to prevent overflowing the 16K max VC string length.
-R"( Compiler tools have the notion of a single input and a single output, along
- with a set of compiler-specific flags. The following expansions are
- available:
-
- {{asmflags}}
- {{cflags}}
- {{cflags_c}}
- {{cflags_cc}}
- {{cflags_objc}}
- {{cflags_objcc}}
- {{defines}}
- {{include_dirs}}
- Strings correspond that to the processed flags/defines/include
- directories specified for the target.
- Example: "--enable-foo --enable-bar"
-
- Defines will be prefixed by "-D" and include directories will be
- prefixed by "-I" (these work with Posix tools as well as Microsoft
- ones).
-
- {{source}}
- The relative path and name of the current input file.
- Example: "../../base/my_file.cc"
-
- {{source_file_part}}
- The file part of the source including the extension (with no directory
- information).
- Example: "foo.cc"
-
- {{source_name_part}}
- The filename part of the source file with no directory or extension.
- Example: "foo"
-
- {{source_gen_dir}}
- {{source_out_dir}}
- The directory in the generated file and output directories,
- respectively, for the current input file. If the source file is in the
- same directory as the target is declared in, they will will be the same
- as the "target" versions above. Example: "gen/base/test"
-
- Linker tools have multiple inputs and (potentially) multiple outputs The
- static library tool ("alink") is not considered a linker tool. The following
- expansions are available:
-
- {{inputs}}
- {{inputs_newline}}
- Expands to the inputs to the link step. This will be a list of object
- files and static libraries.
- Example: "obj/foo.o obj/bar.o obj/somelibrary.a"
-
- The "_newline" version will separate the input files with newlines
- instead of spaces. This is useful in response files: some linkers can
- take a "-filelist" flag which expects newline separated files, and some
- Microsoft tools have a fixed-sized buffer for parsing each line of a
- response file.
-
- {{ldflags}}
- Expands to the processed set of ldflags and library search paths
- specified for the target.
- Example: "-m64 -fPIC -pthread -L/usr/local/mylib"
-
- {{libs}}
- Expands to the list of system libraries to link to. Each will be
- prefixed by the "lib_switch".
-
- As a special case to support Mac, libraries with names ending in
- ".framework" will be added to the {{libs}} with "-framework" preceding
- it, and the lib prefix will be ignored.
-
- Example: "-lfoo -lbar"
-
- {{output_dir}}
- The value of the "output_dir" variable in the target, or the the value
- of the "default_output_dir" value in the tool if the target does not
- override the output directory. This will be relative to the
- root_build_dir and will not end in a slash. Will be "." for output to
- the root_build_dir.
-
- This is subtly different than {{target_out_dir}} which is defined by GN
- based on the target's path and not overridable. {{output_dir}} is for
- the final output, {{target_out_dir}} is generally for object files and
- other outputs.
-
- Usually {{output_dir}} would be defined in terms of either
- {{target_out_dir}} or {{root_out_dir}}
-
- {{output_extension}}
- The value of the "output_extension" variable in the target, or the
- value of the "default_output_extension" value in the tool if the target
- does not specify an output extension.
- Example: ".so"
-
- {{solibs}}
- Extra libraries from shared library dependencies not specified in the
- {{inputs}}. This is the list of link_output files from shared libraries
- (if the solink tool specifies a "link_output" variable separate from
- the "depend_output").
-
- These should generally be treated the same as libs by your tool.
-
- Example: "libfoo.so libbar.so"
-
-)" // String break to prevent overflowing the 16K max VC string length.
-R"( The static library ("alink") tool allows {{arflags}} plus the common tool
- substitutions.
-
- The copy tool allows the common compiler/linker substitutions, plus
- {{source}} which is the source of the copy. The stamp tool allows only the
- common tool substitutions.
-
- The copy_bundle_data and compile_xcassets tools only allows the common tool
- substitutions. Both tools are required to create iOS/macOS bundles and need
- only be defined on those platforms.
-
- The copy_bundle_data tool will be called with one source and needs to copy
- (optionally optimizing the data representation) to its output. It may be
- called with a directory as input and it needs to be recursively copied.
-
- The compile_xcassets tool will be called with one or more source (each an
- asset catalog) that needs to be compiled to a single output. The following
- substitutions are available:
-
- {{inputs}}
- Expands to the list of .xcassets to use as input to compile the asset
- catalog.
-
- {{bundle_product_type}}
- Expands to the product_type of the bundle that will contain the
- compiled asset catalog. Usually corresponds to the product_type
- property of the corresponding create_bundle target.
-
- {{bundle_partial_info_plist}}
- Expands to the path to the partial Info.plist generated by the
- assets catalog compiler. Usually based on the target_name of
- the create_bundle target.
-
-Separate linking and dependencies for shared libraries
-
- Shared libraries are special in that not all changes to them require that
- dependent targets be re-linked. If the shared library is changed but no
- imports or exports are different, dependent code needn't be relinked, which
- can speed up the build.
-
- If your link step can output a list of exports from a shared library and
- writes the file only if the new one is different, the timestamp of this file
- can be used for triggering re-links, while the actual shared library would be
- used for linking.
-
- You will need to specify
- restat = true
- in the linker tool to make this work, so Ninja will detect if the timestamp
- of the dependency file has changed after linking (otherwise it will always
- assume that running a command updates the output):
-
- tool("solink") {
- command = "..."
- outputs = [
- "{{output_dir}}/{{target_output_name}}{{output_extension}}",
- "{{output_dir}}/{{target_output_name}}"
- "{{output_extension}}.TOC",
- ]
- link_output =
- "{{output_dir}}/{{target_output_name}}{{output_extension}}"
- depend_output =
- "{{output_dir}}/{{target_output_name}}"
- "{{output_extension}}.TOC"
- restat = true
- }
-
-Example
-
- toolchain("my_toolchain") {
- # Put these at the top to apply to all tools below.
- lib_switch = "-l"
- lib_dir_switch = "-L"
-
- tool("cc") {
- command = "gcc {{source}} -o {{output}}"
- outputs = [ "{{source_out_dir}}/{{source_name_part}}.o" ]
- description = "GCC {{source}}"
- }
- tool("cxx") {
- command = "g++ {{source}} -o {{output}}"
- outputs = [ "{{source_out_dir}}/{{source_name_part}}.o" ]
- description = "G++ {{source}}"
- }
- };
-)";
-
-Value RunTool(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- // Find the toolchain definition we're executing inside of. The toolchain
- // function will set a property pointing to it that we'll pick up.
- Toolchain* toolchain = reinterpret_cast<Toolchain*>(
- scope->GetProperty(&kToolchainPropertyKey, nullptr));
- if (!toolchain) {
- *err = Err(function->function(), "tool() called outside of toolchain().",
- "The tool() function can only be used inside a toolchain() "
- "definition.");
- return Value();
- }
-
- if (!EnsureSingleStringArg(function, args, err))
- return Value();
- const std::string& tool_name = args[0].string_value();
- Toolchain::ToolType tool_type = Toolchain::ToolNameToType(tool_name);
- if (tool_type == Toolchain::TYPE_NONE) {
- *err = Err(args[0], "Unknown tool type");
- return Value();
- }
-
- // Run the tool block.
- Scope block_scope(scope);
- block->Execute(&block_scope, err);
- if (err->has_error())
- return Value();
-
- // Figure out which validator to use for the substitution pattern for this
- // tool type. There are different validators for the "outputs" than for the
- // rest of the strings.
- bool (*subst_validator)(SubstitutionType) = nullptr;
- bool (*subst_output_validator)(SubstitutionType) = nullptr;
- if (IsCompilerTool(tool_type)) {
- subst_validator = &IsValidCompilerSubstitution;
- subst_output_validator = &IsValidCompilerOutputsSubstitution;
- } else if (IsLinkerTool(tool_type)) {
- subst_validator = &IsValidLinkerSubstitution;
- subst_output_validator = &IsValidLinkerOutputsSubstitution;
- } else if (tool_type == Toolchain::TYPE_ALINK) {
- subst_validator = &IsValidALinkSubstitution;
- // ALink uses the standard output file patterns as other linker tools.
- subst_output_validator = &IsValidLinkerOutputsSubstitution;
- } else if (tool_type == Toolchain::TYPE_COPY ||
- tool_type == Toolchain::TYPE_COPY_BUNDLE_DATA) {
- subst_validator = &IsValidCopySubstitution;
- subst_output_validator = &IsValidCopySubstitution;
- } else if (tool_type == Toolchain::TYPE_COMPILE_XCASSETS) {
- subst_validator = &IsValidCompileXCassetsSubstitution;
- subst_output_validator = &IsValidCompileXCassetsSubstitution;
- } else {
- subst_validator = &IsValidToolSubstitution;
- subst_output_validator = &IsValidToolSubstitution;
- }
-
- std::unique_ptr<Tool> tool = std::make_unique<Tool>();
- tool->set_defined_from(function);
-
- if (!ReadPattern(&block_scope, "command", subst_validator, tool.get(),
- &Tool::set_command, err) ||
- !ReadOutputExtension(&block_scope, tool.get(), err) ||
- !ReadPattern(&block_scope, "depfile", subst_validator, tool.get(),
- &Tool::set_depfile, err) ||
- !ReadDepsFormat(&block_scope, tool.get(), err) ||
- !ReadPattern(&block_scope, "description", subst_validator, tool.get(),
- &Tool::set_description, err) ||
- !ReadString(&block_scope, "lib_switch", tool.get(), &Tool::set_lib_switch,
- err) ||
- !ReadString(&block_scope, "lib_dir_switch", tool.get(),
- &Tool::set_lib_dir_switch, err) ||
- !ReadPattern(&block_scope, "link_output", subst_validator, tool.get(),
- &Tool::set_link_output, err) ||
- !ReadPattern(&block_scope, "depend_output", subst_validator, tool.get(),
- &Tool::set_depend_output, err) ||
- !ReadPatternList(&block_scope, "runtime_outputs", subst_validator,
- tool.get(), &Tool::set_runtime_outputs, err) ||
- !ReadString(&block_scope, "output_prefix", tool.get(),
- &Tool::set_output_prefix, err) ||
- !ReadPattern(&block_scope, "default_output_dir", subst_validator,
- tool.get(), &Tool::set_default_output_dir, err) ||
- !ReadPrecompiledHeaderType(&block_scope, tool.get(), err) ||
- !ReadBool(&block_scope, "restat", tool.get(), &Tool::set_restat, err) ||
- !ReadPattern(&block_scope, "rspfile", subst_validator, tool.get(),
- &Tool::set_rspfile, err) ||
- !ReadPattern(&block_scope, "rspfile_content", subst_validator, tool.get(),
- &Tool::set_rspfile_content, err) ||
- !ReadLabel(&block_scope, "pool", tool.get(), toolchain->label(),
- &Tool::set_pool, err)) {
- return Value();
- }
-
- if (tool_type != Toolchain::TYPE_COPY && tool_type != Toolchain::TYPE_STAMP &&
- tool_type != Toolchain::TYPE_COPY_BUNDLE_DATA &&
- tool_type != Toolchain::TYPE_COMPILE_XCASSETS &&
- tool_type != Toolchain::TYPE_ACTION) {
- // All tools should have outputs, except the copy, stamp, copy_bundle_data
- // compile_xcassets and action tools that generate their outputs internally.
- if (!ReadPatternList(&block_scope, "outputs", subst_output_validator,
- tool.get(), &Tool::set_outputs, err) ||
- !ValidateOutputs(tool.get(), err))
- return Value();
- }
- if (!ValidateRuntimeOutputs(tool.get(), tool_type, err))
- return Value();
-
- // Validate link_output and depend_output.
- if (!ValidateLinkAndDependOutput(tool.get(), tool_type, tool->link_output(),
- "link_output", err))
- return Value();
- if (!ValidateLinkAndDependOutput(tool.get(), tool_type, tool->depend_output(),
- "depend_output", err))
- return Value();
- if ((!tool->link_output().empty() && tool->depend_output().empty()) ||
- (tool->link_output().empty() && !tool->depend_output().empty())) {
- *err = Err(function, "Both link_output and depend_output should either "
- "be specified or they should both be empty.");
- return Value();
- }
-
- // Make sure there weren't any vars set in this tool that were unused.
- if (!block_scope.CheckForUnusedVars(err))
- return Value();
-
- toolchain->SetTool(tool_type, std::move(tool));
- return Value();
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/function_toolchain_unittest.cc b/chromium/tools/gn/function_toolchain_unittest.cc
deleted file mode 100644
index eec8779e2ab..00000000000
--- a/chromium/tools/gn/function_toolchain_unittest.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/test_with_scheduler.h"
-#include "tools/gn/test_with_scope.h"
-
-using FunctionToolchain = TestWithScheduler;
-
-TEST_F(FunctionToolchain, RuntimeOutputs) {
- TestWithScope setup;
-
- // These runtime outputs are a subset of the outputs so are OK.
- {
- TestParseInput input(
- R"(toolchain("good") {
- tool("link") {
- outputs = [ "foo" ]
- runtime_outputs = [ "foo" ]
- }
- })");
- ASSERT_FALSE(input.has_error());
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- // It should have generated a toolchain.
- ASSERT_EQ(1u, setup.items().size());
- const Toolchain* toolchain = setup.items()[0]->AsToolchain();
- ASSERT_TRUE(toolchain);
-
- // The toolchain should have a link tool with the two outputs.
- const Tool* link = toolchain->GetTool(Toolchain::TYPE_LINK);
- ASSERT_TRUE(link);
- ASSERT_EQ(1u, link->outputs().list().size());
- EXPECT_EQ("foo", link->outputs().list()[0].AsString());
- ASSERT_EQ(1u, link->runtime_outputs().list().size());
- EXPECT_EQ("foo", link->runtime_outputs().list()[0].AsString());
- }
-
- // This one is not a subset so should throw an error.
- {
- TestParseInput input(
- R"(toolchain("bad") {
- tool("link") {
- outputs = [ "foo" ]
- runtime_outputs = [ "bar" ]
- }
- })");
- ASSERT_FALSE(input.has_error());
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- ASSERT_TRUE(err.has_error()) << err.message();
- }
-}
diff --git a/chromium/tools/gn/function_write_file.cc b/chromium/tools/gn/function_write_file.cc
deleted file mode 100644
index bfa79b62cf9..00000000000
--- a/chromium/tools/gn/function_write_file.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <iostream>
-#include <sstream>
-
-#include "base/files/file_util.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scheduler.h"
-
-namespace functions {
-
-const char kWriteFile[] = "write_file";
-const char kWriteFile_HelpShort[] =
- "write_file: Write a file to disk.";
-const char kWriteFile_Help[] =
- R"(write_file: Write a file to disk.
-
- write_file(filename, data)
-
- If data is a list, the list will be written one-item-per-line with no quoting
- or brackets.
-
- If the file exists and the contents are identical to that being written, the
- file will not be updated. This will prevent unnecessary rebuilds of targets
- that depend on this file.
-
- One use for write_file is to write a list of inputs to an script that might
- be too long for the command line. However, it is preferable to use response
- files for this purpose. See "gn help response_file_contents".
-
- TODO(brettw) we probably need an optional third argument to control list
- formatting.
-
-Arguments
-
- filename
- Filename to write. This must be within the output directory.
-
- data
- The list or string to write.
-)";
-
-Value RunWriteFile(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- if (args.size() != 2) {
- *err = Err(function->function(), "Wrong number of arguments to write_file",
- "I expected two arguments.");
- return Value();
- }
-
- // Compute the file name and make sure it's in the output dir.
- const SourceDir& cur_dir = scope->GetSourceDir();
- SourceFile source_file = cur_dir.ResolveRelativeFile(args[0], err,
- scope->settings()->build_settings()->root_path_utf8());
- if (err->has_error())
- return Value();
- if (!EnsureStringIsInOutputDir(
- scope->settings()->build_settings()->build_dir(),
- source_file.value(), args[0].origin(), err))
- return Value();
- g_scheduler->AddWrittenFile(source_file); // Track that we wrote this file.
-
- // Track how to recreate this file, since we write it a gen time.
- // Note this is a hack since the correct output is not a dependency proper,
- // but an addition of this file to the output of the gn rule that writes it.
- // This dependency will, however, cause the gen step to be re-run and the
- // build restarted if the file is missing.
- g_scheduler->AddGenDependency(
- scope->settings()->build_settings()->GetFullPath(source_file));
-
- // Compute output.
- std::ostringstream contents;
- if (args[1].type() == Value::LIST) {
- const std::vector<Value>& list = args[1].list_value();
- for (const auto& cur : list)
- contents << cur.ToString(false) << std::endl;
- } else {
- contents << args[1].ToString(false);
- }
-
- base::FilePath file_path =
- scope->settings()->build_settings()->GetFullPath(source_file);
-
- // Make sure we're not replacing the same contents.
- if (!WriteFileIfChanged(file_path, contents.str(), err))
- *err = Err(function->function(), err->message(), err->help_text());
-
- return Value();
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/function_write_file_unittest.cc b/chromium/tools/gn/function_write_file_unittest.cc
deleted file mode 100644
index db2ea1e0459..00000000000
--- a/chromium/tools/gn/function_write_file_unittest.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-
-#include "base/files/file.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/test_with_scheduler.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-// Returns true on success, false if write_file signaled an error.
-bool CallWriteFile(Scope* scope,
- const std::string& filename,
- const Value& data) {
- Err err;
-
- std::vector<Value> args;
- args.push_back(Value(nullptr, filename));
- args.push_back(data);
-
- FunctionCallNode function_call;
- Value result = functions::RunWriteFile(scope, &function_call, args, &err);
- EXPECT_EQ(Value::NONE, result.type()); // Should always return none.
-
- return !err.has_error();
-}
-
-} // namespace
-
-using WriteFileTest = TestWithScheduler;
-
-TEST_F(WriteFileTest, WithData) {
- TestWithScope setup;
-
- // Make a real directory for writing the files.
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- setup.build_settings()->SetRootPath(temp_dir.GetPath());
- setup.build_settings()->SetBuildDir(SourceDir("//out/"));
-
- Value some_string(nullptr, "some string contents");
-
- // Should refuse to write files outside of the output dir.
- EXPECT_FALSE(CallWriteFile(setup.scope(), "//in_root.txt", some_string));
- EXPECT_FALSE(CallWriteFile(setup.scope(), "//other_dir/foo.txt",
- some_string));
-
- // Should be able to write to a new dir inside the out dir.
- EXPECT_TRUE(CallWriteFile(setup.scope(), "//out/foo.txt", some_string));
- base::FilePath foo_name = temp_dir.GetPath()
- .Append(FILE_PATH_LITERAL("out"))
- .Append(FILE_PATH_LITERAL("foo.txt"));
- std::string result_contents;
- EXPECT_TRUE(base::ReadFileToString(foo_name, &result_contents));
- EXPECT_EQ(some_string.string_value(), result_contents);
-
- // Update the contents with a list of a string and a number.
- Value some_list(nullptr, Value::LIST);
- some_list.list_value().push_back(Value(nullptr, "line 1"));
- some_list.list_value().push_back(Value(nullptr, static_cast<int64_t>(2)));
- EXPECT_TRUE(CallWriteFile(setup.scope(), "//out/foo.txt", some_list));
- EXPECT_TRUE(base::ReadFileToString(foo_name, &result_contents));
- EXPECT_EQ("line 1\n2\n", result_contents);
-
- // Test that the file is not rewritten if the contents are not changed.
- // Start by setting the modified time to something old to avoid clock
- // resolution issues.
- base::Time old_time = base::Time::Now() - base::TimeDelta::FromDays(1);
- base::File foo_file(foo_name,
- base::File::FLAG_OPEN |
- base::File::FLAG_READ | base::File::FLAG_WRITE);
- ASSERT_TRUE(foo_file.IsValid());
- foo_file.SetTimes(old_time, old_time);
-
- // Read the current time to avoid timer resolution issues when comparing
- // below.
- base::File::Info original_info;
- foo_file.GetInfo(&original_info);
-
- EXPECT_TRUE(CallWriteFile(setup.scope(), "//out/foo.txt", some_list));
-
- // Verify that the last modified time is the same as before.
- base::File::Info new_info;
- foo_file.GetInfo(&new_info);
- EXPECT_EQ(original_info.last_modified, new_info.last_modified);
-}
diff --git a/chromium/tools/gn/functions.cc b/chromium/tools/gn/functions.cc
deleted file mode 100644
index e7fb5246620..00000000000
--- a/chromium/tools/gn/functions.cc
+++ /dev/null
@@ -1,1296 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/functions.h"
-
-#include <stddef.h>
-#include <iostream>
-#include <memory>
-#include <utility>
-
-#include "base/environment.h"
-#include "base/strings/string_util.h"
-#include "tools/gn/config.h"
-#include "tools/gn/config_values_generator.h"
-#include "tools/gn/err.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parse_node_value_adapter.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/pool.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/template.h"
-#include "tools/gn/token.h"
-#include "tools/gn/value.h"
-#include "tools/gn/value_extractors.h"
-#include "tools/gn/variables.h"
-
-namespace {
-
-// Some functions take a {} following them, and some don't. For the ones that
-// don't, this is used to verify that the given block node is null and will
-// set the error accordingly if it's not. Returns true if the block is null.
-bool VerifyNoBlockForFunctionCall(const FunctionCallNode* function,
- const BlockNode* block,
- Err* err) {
- if (!block)
- return true;
-
- *err = Err(block, "Unexpected '{'.",
- "This function call doesn't take a {} block following it, and you\n"
- "can't have a {} block that's not connected to something like an if\n"
- "statement or a target declaration.");
- err->AppendRange(function->function().range());
- return false;
-}
-
-// This key is set as a scope property on the scope of a declare_args() block,
-// in order to prevent reading a variable defined earlier in the same call
-// (see `gn help declare_args` for more).
-const void *kInDeclareArgsKey = nullptr;
-
-} // namespace
-
-
-bool EnsureNotReadingFromSameDeclareArgs(const ParseNode* node,
- const Scope* cur_scope,
- const Scope* val_scope,
- Err* err) {
- // If the value didn't come from a scope at all, we're safe.
- if (!val_scope)
- return true;
-
- const Scope* val_args_scope = nullptr;
- val_scope->GetProperty(&kInDeclareArgsKey, &val_args_scope);
-
- const Scope* cur_args_scope = nullptr;
- cur_scope->GetProperty(&kInDeclareArgsKey, &cur_args_scope);
- if (!val_args_scope || !cur_args_scope || (val_args_scope != cur_args_scope))
- return true;
-
- *err = Err(node,
- "Reading a variable defined in the same declare_args() call.\n"
- "\n"
- "If you need to set the value of one arg based on another, put\n"
- "them in two separate declare_args() calls, one after the other.\n");
- return false;
-}
-
-bool EnsureNotProcessingImport(const ParseNode* node,
- const Scope* scope,
- Err* err) {
- if (scope->IsProcessingImport()) {
- *err = Err(node, "Not valid from an import.",
- "Imports are for defining defaults, variables, and rules. The\n"
- "appropriate place for this kind of thing is really in a normal\n"
- "BUILD file.");
- return false;
- }
- return true;
-}
-
-bool EnsureNotProcessingBuildConfig(const ParseNode* node,
- const Scope* scope,
- Err* err) {
- if (scope->IsProcessingBuildConfig()) {
- *err = Err(node, "Not valid from the build config.",
- "You can't do this kind of thing from the build config script, "
- "silly!\nPut it in a regular BUILD file.");
- return false;
- }
- return true;
-}
-
-bool FillTargetBlockScope(const Scope* scope,
- const FunctionCallNode* function,
- const std::string& target_type,
- const BlockNode* block,
- const std::vector<Value>& args,
- Scope* block_scope,
- Err* err) {
- if (!block) {
- FillNeedsBlockError(function, err);
- return false;
- }
-
- // Copy the target defaults, if any, into the scope we're going to execute
- // the block in.
- const Scope* default_scope = scope->GetTargetDefaults(target_type);
- if (default_scope) {
- Scope::MergeOptions merge_options;
- merge_options.skip_private_vars = true;
- if (!default_scope->NonRecursiveMergeTo(block_scope, merge_options,
- function, "target defaults", err))
- return false;
- }
-
- // The name is the single argument to the target function.
- if (!EnsureSingleStringArg(function, args, err))
- return false;
-
- // Set the target name variable to the current target, and mark it used
- // because we don't want to issue an error if the script ignores it.
- const base::StringPiece target_name(variables::kTargetName);
- block_scope->SetValue(target_name, Value(function, args[0].string_value()),
- function);
- block_scope->MarkUsed(target_name);
- return true;
-}
-
-void FillNeedsBlockError(const FunctionCallNode* function, Err* err) {
- *err = Err(function->function(), "This function call requires a block.",
- "The block's \"{\" must be on the same line as the function "
- "call's \")\".");
-}
-
-bool EnsureSingleStringArg(const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- if (args.size() != 1) {
- *err = Err(function->function(), "Incorrect arguments.",
- "This function requires a single string argument.");
- return false;
- }
- return args[0].VerifyTypeIs(Value::STRING, err);
-}
-
-const Label& ToolchainLabelForScope(const Scope* scope) {
- return scope->settings()->toolchain_label();
-}
-
-Label MakeLabelForScope(const Scope* scope,
- const FunctionCallNode* function,
- const std::string& name) {
- const Label& toolchain_label = ToolchainLabelForScope(scope);
- return Label(scope->GetSourceDir(), name, toolchain_label.dir(),
- toolchain_label.name());
-}
-
-// static
-const int NonNestableBlock::kKey = 0;
-
-NonNestableBlock::NonNestableBlock(
- Scope* scope,
- const FunctionCallNode* function,
- const char* type_description)
- : scope_(scope),
- function_(function),
- type_description_(type_description),
- key_added_(false) {
-}
-
-NonNestableBlock::~NonNestableBlock() {
- if (key_added_)
- scope_->SetProperty(&kKey, nullptr);
-}
-
-bool NonNestableBlock::Enter(Err* err) {
- void* scope_value = scope_->GetProperty(&kKey, nullptr);
- if (scope_value) {
- // Existing block.
- const NonNestableBlock* existing =
- reinterpret_cast<const NonNestableBlock*>(scope_value);
- *err = Err(function_, "Can't nest these things.",
- std::string("You are trying to nest a ") + type_description_ +
- " inside a " + existing->type_description_ + ".");
- err->AppendSubErr(Err(existing->function_, "The enclosing block."));
- return false;
- }
-
- scope_->SetProperty(&kKey, this);
- key_added_ = true;
- return true;
-}
-
-namespace functions {
-
-// assert ----------------------------------------------------------------------
-
-const char kAssert[] = "assert";
-const char kAssert_HelpShort[] =
- "assert: Assert an expression is true at generation time.";
-const char kAssert_Help[] =
- R"(assert: Assert an expression is true at generation time.
-
- assert(<condition> [, <error string>])
-
- If the condition is false, the build will fail with an error. If the
- optional second argument is provided, that string will be printed
- with the error message.
-
-Examples
-
- assert(is_win)
- assert(defined(sources), "Sources must be defined");
-)";
-
-Value RunAssert(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- if (args.size() != 1 && args.size() != 2) {
- *err = Err(function->function(), "Wrong number of arguments.",
- "assert() takes one or two argument, "
- "were you expecting somethig else?");
- } else if (args[0].type() != Value::BOOLEAN) {
- *err = Err(function->function(), "Assertion value not a bool.");
- } else if (!args[0].boolean_value()) {
- if (args.size() == 2) {
- // Optional string message.
- if (args[1].type() != Value::STRING) {
- *err = Err(function->function(), "Assertion failed.",
- "<<<ERROR MESSAGE IS NOT A STRING>>>");
- } else {
- *err = Err(function->function(), "Assertion failed.",
- args[1].string_value());
- }
- } else {
- *err = Err(function->function(), "Assertion failed.");
- }
-
- if (args[0].origin()) {
- // If you do "assert(foo)" we'd ideally like to show you where foo was
- // set, and in this case the origin of the args will tell us that.
- // However, if you do "assert(foo && bar)" the source of the value will
- // be the assert like, which isn't so helpful.
- //
- // So we try to see if the args are from the same line or not. This will
- // break if you do "assert(\nfoo && bar)" and we may show the second line
- // as the source, oh well. The way around this is to check to see if the
- // origin node is inside our function call block.
- Location origin_location = args[0].origin()->GetRange().begin();
- if (origin_location.file() != function->function().location().file() ||
- origin_location.line_number() !=
- function->function().location().line_number()) {
- err->AppendSubErr(Err(args[0].origin()->GetRange(), "",
- "This is where it was set."));
- }
- }
- }
- return Value();
-}
-
-// config ----------------------------------------------------------------------
-
-const char kConfig[] = "config";
-const char kConfig_HelpShort[] =
- "config: Defines a configuration object.";
-const char kConfig_Help[] =
- R"(config: Defines a configuration object.
-
- Configuration objects can be applied to targets and specify sets of compiler
- flags, includes, defines, etc. They provide a way to conveniently group sets
- of this configuration information.
-
- A config is referenced by its label just like a target.
-
- The values in a config are additive only. If you want to remove a flag you
- need to remove the corresponding config that sets it. The final set of flags,
- defines, etc. for a target is generated in this order:
-
- 1. The values specified directly on the target (rather than using a config.
- 2. The configs specified in the target's "configs" list, in order.
- 3. Public_configs from a breadth-first traversal of the dependency tree in
- the order that the targets appear in "deps".
- 4. All dependent configs from a breadth-first traversal of the dependency
- tree in the order that the targets appear in "deps".
-
-Variables valid in a config definition
-)"
-
- CONFIG_VALUES_VARS_HELP
-
-R"( Nested configs: configs
-
-Variables on a target used to apply configs
-
- all_dependent_configs, configs, public_configs
-
-Example
-
- config("myconfig") {
- includes = [ "include/common" ]
- defines = [ "ENABLE_DOOM_MELON" ]
- }
-
- executable("mything") {
- configs = [ ":myconfig" ]
- }
-)";
-
-Value RunConfig(const FunctionCallNode* function,
- const std::vector<Value>& args,
- Scope* scope,
- Err* err) {
- NonNestableBlock non_nestable(scope, function, "config");
- if (!non_nestable.Enter(err))
- return Value();
-
- if (!EnsureSingleStringArg(function, args, err) ||
- !EnsureNotProcessingImport(function, scope, err))
- return Value();
-
- Label label(MakeLabelForScope(scope, function, args[0].string_value()));
-
- if (g_scheduler->verbose_logging())
- g_scheduler->Log("Defining config", label.GetUserVisibleName(true));
-
- // Create the new config.
- std::unique_ptr<Config> config = std::make_unique<Config>(
- scope->settings(), label, scope->build_dependency_files());
- config->set_defined_from(function);
- if (!Visibility::FillItemVisibility(config.get(), scope, err))
- return Value();
-
- // Fill the flags and such.
- const SourceDir& input_dir = scope->GetSourceDir();
- ConfigValuesGenerator gen(&config->own_values(), scope, input_dir, err);
- gen.Run();
- if (err->has_error())
- return Value();
-
- // Read sub-configs.
- const Value* configs_value = scope->GetValue(variables::kConfigs, true);
- if (configs_value) {
- ExtractListOfUniqueLabels(*configs_value, scope->GetSourceDir(),
- ToolchainLabelForScope(scope),
- &config->configs(), err);
- }
- if (err->has_error())
- return Value();
-
- // Save the generated item.
- Scope::ItemVector* collector = scope->GetItemCollector();
- if (!collector) {
- *err = Err(function, "Can't define a config in this context.");
- return Value();
- }
- collector->push_back(std::move(config));
-
- return Value();
-}
-
-// declare_args ----------------------------------------------------------------
-
-const char kDeclareArgs[] = "declare_args";
-const char kDeclareArgs_HelpShort[] =
- "declare_args: Declare build arguments.";
-const char kDeclareArgs_Help[] =
- R"(declare_args: Declare build arguments.
-
- Introduces the given arguments into the current scope. If they are not
- specified on the command line or in a toolchain's arguments, the default
- values given in the declare_args block will be used. However, these defaults
- will not override command-line values.
-
- See also "gn help buildargs" for an overview.
-
- The precise behavior of declare args is:
-
- 1. The declare_args() block executes. Any variable defined in the enclosing
- scope is available for reading, but any variable defined earlier in
- the current scope is not (since the overrides haven't been applied yet).
-
- 2. At the end of executing the block, any variables set within that scope
- are saved globally as build arguments, with their current values being
- saved as the "default value" for that argument.
-
- 3. User-defined overrides are applied. Anything set in "gn args" now
- overrides any default values. The resulting set of variables is promoted
- to be readable from the following code in the file.
-
- This has some ramifications that may not be obvious:
-
- - You should not perform difficult work inside a declare_args block since
- this only sets a default value that may be discarded. In particular,
- don't use the result of exec_script() to set the default value. If you
- want to have a script-defined default, set some default "undefined" value
- like [], "", or -1, and after the declare_args block, call exec_script if
- the value is unset by the user.
-
- - Because you cannot read the value of a variable defined in the same
- block, if you need to make the default value of one arg depend
- on the possibly-overridden value of another, write two separate
- declare_args() blocks:
-
- declare_args() {
- enable_foo = true
- }
- declare_args() {
- # Bar defaults to same user-overridden state as foo.
- enable_bar = enable_foo
- }
-
-Example
-
- declare_args() {
- enable_teleporter = true
- enable_doom_melon = false
- }
-
- If you want to override the (default disabled) Doom Melon:
- gn --args="enable_doom_melon=true enable_teleporter=true"
- This also sets the teleporter, but it's already defaulted to on so it will
- have no effect.
-)";
-
-Value RunDeclareArgs(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- NonNestableBlock non_nestable(scope, function, "declare_args");
- if (!non_nestable.Enter(err))
- return Value();
-
- Scope block_scope(scope);
- block_scope.SetProperty(&kInDeclareArgsKey, &block_scope);
- block->Execute(&block_scope, err);
- if (err->has_error())
- return Value();
-
- // Pass the values from our scope into the Args object for adding to the
- // scope with the proper values (taking into account the defaults given in
- // the block_scope, and arguments passed into the build).
- Scope::KeyValueMap values;
- block_scope.GetCurrentScopeValues(&values);
- scope->settings()->build_settings()->build_args().DeclareArgs(
- values, scope, err);
- return Value();
-}
-
-// defined ---------------------------------------------------------------------
-
-const char kDefined[] = "defined";
-const char kDefined_HelpShort[] =
- "defined: Returns whether an identifier is defined.";
-const char kDefined_Help[] =
- R"(defined: Returns whether an identifier is defined.
-
- Returns true if the given argument is defined. This is most useful in
- templates to assert that the caller set things up properly.
-
- You can pass an identifier:
- defined(foo)
- which will return true or false depending on whether foo is defined in the
- current scope.
-
- You can also check a named scope:
- defined(foo.bar)
- which will return true or false depending on whether bar is defined in the
- named scope foo. It will throw an error if foo is not defined or is not a
- scope.
-
-Example
-
- template("mytemplate") {
- # To help users call this template properly...
- assert(defined(invoker.sources), "Sources must be defined")
-
- # If we want to accept an optional "values" argument, we don't
- # want to dereference something that may not be defined.
- if (defined(invoker.values)) {
- values = invoker.values
- } else {
- values = "some default value"
- }
- }
-)";
-
-Value RunDefined(Scope* scope,
- const FunctionCallNode* function,
- const ListNode* args_list,
- Err* err) {
- const auto& args_vector = args_list->contents();
- if (args_vector.size() != 1) {
- *err = Err(function, "Wrong number of arguments to defined().",
- "Expecting exactly one.");
- return Value();
- }
-
- const IdentifierNode* identifier = args_vector[0]->AsIdentifier();
- if (identifier) {
- // Passed an identifier "defined(foo)".
- if (scope->GetValue(identifier->value().value()))
- return Value(function, true);
- return Value(function, false);
- }
-
- const AccessorNode* accessor = args_vector[0]->AsAccessor();
- if (accessor) {
- // Passed an accessor "defined(foo.bar)".
- if (accessor->member()) {
- // The base of the accessor must be a scope if it's defined.
- const Value* base = scope->GetValue(accessor->base().value());
- if (!base) {
- *err = Err(accessor, "Undefined identifier");
- return Value();
- }
- if (!base->VerifyTypeIs(Value::SCOPE, err))
- return Value();
-
- // Check the member inside the scope to see if its defined.
- if (base->scope_value()->GetValue(accessor->member()->value().value()))
- return Value(function, true);
- return Value(function, false);
- }
- }
-
- // Argument is invalid.
- *err = Err(function, "Bad thing passed to defined().",
- "It should be of the form defined(foo) or defined(foo.bar).");
- return Value();
-}
-
-// getenv ----------------------------------------------------------------------
-
-const char kGetEnv[] = "getenv";
-const char kGetEnv_HelpShort[] =
- "getenv: Get an environment variable.";
-const char kGetEnv_Help[] =
- R"(getenv: Get an environment variable.
-
- value = getenv(env_var_name)
-
- Returns the value of the given environment variable. If the value is not
- found, it will try to look up the variable with the "opposite" case (based on
- the case of the first letter of the variable), but is otherwise
- case-sensitive.
-
- If the environment variable is not found, the empty string will be returned.
- Note: it might be nice to extend this if we had the concept of "none" in the
- language to indicate lookup failure.
-
-Example
-
- home_dir = getenv("HOME")
-)";
-
-Value RunGetEnv(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- if (!EnsureSingleStringArg(function, args, err))
- return Value();
-
- std::unique_ptr<base::Environment> env(base::Environment::Create());
-
- std::string result;
- if (!env->GetVar(args[0].string_value().c_str(), &result))
- return Value(function, ""); // Not found, return empty string.
- return Value(function, result);
-}
-
-// import ----------------------------------------------------------------------
-
-const char kImport[] = "import";
-const char kImport_HelpShort[] =
- "import: Import a file into the current scope.";
-const char kImport_Help[] =
- R"(import: Import a file into the current scope.
-
- The import command loads the rules and variables resulting from executing the
- given file into the current scope.
-
- By convention, imported files are named with a .gni extension.
-
- An import is different than a C++ "include". The imported file is executed in
- a standalone environment from the caller of the import command. The results
- of this execution are cached for other files that import the same .gni file.
-
- Note that you can not import a BUILD.gn file that's otherwise used in the
- build. Files must either be imported or implicitly loaded as a result of deps
- rules, but not both.
-
- The imported file's scope will be merged with the scope at the point import
- was called. If there is a conflict (both the current scope and the imported
- file define some variable or rule with the same name but different value), a
- runtime error will be thrown. Therefore, it's good practice to minimize the
- stuff that an imported file defines.
-
- Variables and templates beginning with an underscore '_' are considered
- private and will not be imported. Imported files can use such variables for
- internal computation without affecting other files.
-
-Examples
-
- import("//build/rules/idl_compilation_rule.gni")
-
- # Looks in the current directory.
- import("my_vars.gni")
-)";
-
-Value RunImport(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- if (!EnsureSingleStringArg(function, args, err))
- return Value();
-
- const SourceDir& input_dir = scope->GetSourceDir();
- SourceFile import_file =
- input_dir.ResolveRelativeFile(args[0], err,
- scope->settings()->build_settings()->root_path_utf8());
- scope->AddBuildDependencyFile(import_file);
- if (!err->has_error()) {
- scope->settings()->import_manager().DoImport(import_file, function,
- scope, err);
- }
- return Value();
-}
-
-// not_needed -----------------------------------------------------------------
-
-const char kNotNeeded[] = "not_needed";
-const char kNotNeeded_HelpShort[] =
- "not_needed: Mark variables from scope as not needed.";
-const char kNotNeeded_Help[] =
- R"(not_needed: Mark variables from scope as not needed.
-
- not_needed(variable_list_or_star, variable_to_ignore_list = [])
- not_needed(from_scope, variable_list_or_star,
- variable_to_ignore_list = [])
-
- Mark the variables in the current or given scope as not needed, which means
- you will not get an error about unused variables for these. The
- variable_to_ignore_list allows excluding variables from "all matches" if
- variable_list_or_star is "*".
-
-Example
-
- not_needed("*", [ "config" ])
- not_needed([ "data_deps", "deps" ])
- not_needed(invoker, "*", [ "config" ])
- not_needed(invoker, [ "data_deps", "deps" ])
-)";
-
-Value RunNotNeeded(Scope* scope,
- const FunctionCallNode* function,
- const ListNode* args_list,
- Err* err) {
- const auto& args_vector = args_list->contents();
- if (args_vector.size() < 1 || args_vector.size() > 3) {
- *err = Err(function, "Wrong number of arguments.",
- "Expecting one, two or three arguments.");
- return Value();
- }
- auto args_cur = args_vector.begin();
-
- Value* value = nullptr; // Value to use, may point to result_value.
- Value result_value; // Storage for the "evaluate" case.
- const IdentifierNode* identifier = (*args_cur)->AsIdentifier();
- if (identifier) {
- // Optimize the common case where the input scope is an identifier. This
- // prevents a copy of a potentially large Scope object.
- value = scope->GetMutableValue(identifier->value().value(),
- Scope::SEARCH_NESTED, true);
- if (!value) {
- *err = Err(identifier, "Undefined identifier.");
- return Value();
- }
- } else {
- // Non-optimized case, just evaluate the argument.
- result_value = (*args_cur)->Execute(scope, err);
- if (err->has_error())
- return Value();
- value = &result_value;
- }
- args_cur++;
-
- // Extract the source scope if different from current one.
- Scope* source = scope;
- if (value->type() == Value::SCOPE) {
- source = value->scope_value();
- result_value = (*args_cur)->Execute(scope, err);
- if (err->has_error())
- return Value();
- value = &result_value;
- args_cur++;
- }
-
- // Extract the exclusion list if defined.
- Value exclusion_value;
- std::set<std::string> exclusion_set;
- if (args_cur != args_vector.end()) {
- exclusion_value = (*args_cur)->Execute(source, err);
- if (err->has_error())
- return Value();
-
- if (exclusion_value.type() != Value::LIST) {
- *err = Err(exclusion_value, "Not a valid list of variables to exclude.",
- "Expecting a list of strings.");
- return Value();
- }
-
- for (const Value& cur : exclusion_value.list_value()) {
- if (!cur.VerifyTypeIs(Value::STRING, err))
- return Value();
-
- exclusion_set.insert(cur.string_value());
- }
- }
-
- if (value->type() == Value::STRING) {
- if (value->string_value() == "*") {
- source->MarkAllUsed(exclusion_set);
- return Value();
- }
- } else if (value->type() == Value::LIST) {
- if (exclusion_value.type() != Value::NONE) {
- *err = Err(exclusion_value, "Not supported with a variable list.",
- "Exclusion list can only be used with the string \"*\".");
- return Value();
- }
- for (const Value& cur : value->list_value()) {
- if (!cur.VerifyTypeIs(Value::STRING, err))
- return Value();
- if (!source->GetValue(cur.string_value(), true)) {
- *err = Err(cur, "Undefined identifier");
- return Value();
- }
- }
- return Value();
- }
-
- // Not the right type of argument.
- *err = Err(*value, "Not a valid list of variables.",
- "Expecting either the string \"*\" or a list of strings.");
- return Value();
-}
-
-// set_sources_assignment_filter -----------------------------------------------
-
-const char kSetSourcesAssignmentFilter[] = "set_sources_assignment_filter";
-const char kSetSourcesAssignmentFilter_HelpShort[] =
- "set_sources_assignment_filter: Set a pattern to filter source files.";
-const char kSetSourcesAssignmentFilter_Help[] =
- R"(set_sources_assignment_filter: Set a pattern to filter source files.
-
- The sources assignment filter is a list of patterns that remove files from
- the list implicitly whenever the "sources" variable is assigned to. This will
- do nothing for non-lists.
-
- This is intended to be used to globally filter out files with
- platform-specific naming schemes when they don't apply, for example you may
- want to filter out all "*_win.cc" files on non-Windows platforms.
-
- Typically this will be called once in the master build config script to set
- up the filter for the current platform. Subsequent calls will overwrite the
- previous values.
-
- If you want to bypass the filter and add a file even if it might be filtered
- out, call set_sources_assignment_filter([]) to clear the list of filters.
- This will apply until the current scope exits
-
-How to use patterns
-
- File patterns are VERY limited regular expressions. They must match the
- entire input string to be counted as a match. In regular expression parlance,
- there is an implicit "^...$" surrounding your input. If you want to match a
- substring, you need to use wildcards at the beginning and end.
-
- There are only two special tokens understood by the pattern matcher.
- Everything else is a literal.
-
- - "*" Matches zero or more of any character. It does not depend on the
- preceding character (in regular expression parlance it is equivalent to
- ".*").
-
- - "\b" Matches a path boundary. This will match the beginning or end of a
- string, or a slash.
-
-Pattern examples
-
- "*asdf*"
- Matches a string containing "asdf" anywhere.
-
- "asdf"
- Matches only the exact string "asdf".
-
- "*.cc"
- Matches strings ending in the literal ".cc".
-
- "\bwin/*"
- Matches "win/foo" and "foo/win/bar.cc" but not "iwin/foo".
-
-Sources assignment example
-
- # Filter out all _win files.
- set_sources_assignment_filter([ "*_win.cc", "*_win.h" ])
- sources = [ "a.cc", "b_win.cc" ]
- print(sources)
- # Will print [ "a.cc" ]. b_win one was filtered out.
-)";
-
-Value RunSetSourcesAssignmentFilter(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- if (args.size() != 1) {
- *err = Err(function, "set_sources_assignment_filter takes one argument.");
- } else {
- std::unique_ptr<PatternList> f = std::make_unique<PatternList>();
- f->SetFromValue(args[0], err);
- if (!err->has_error())
- scope->set_sources_assignment_filter(std::move(f));
- }
- return Value();
-}
-
-// pool ------------------------------------------------------------------------
-
-const char kPool[] = "pool";
-const char kPool_HelpShort[] =
- "pool: Defines a pool object.";
-const char kPool_Help[] =
- R"*(pool: Defines a pool object.
-
- Pool objects can be applied to a tool to limit the parallelism of the
- build. This object has a single property "depth" corresponding to
- the number of tasks that may run simultaneously.
-
- As the file containing the pool definition may be executed in the
- context of more than one toolchain it is recommended to specify an
- explicit toolchain when defining and referencing a pool.
-
- A pool named "console" defined in the root build file represents Ninja's
- console pool. Targets using this pool will have access to the console's
- stdin and stdout, and output will not be buffered. This special pool must
- have a depth of 1. Pools not defined in the root must not be named "console".
- The console pool can only be defined for the default toolchain.
- Refer to the Ninja documentation on the console pool for more info.
-
- A pool is referenced by its label just like a target.
-
-Variables
-
- depth*
- * = required
-
-Example
-
- if (current_toolchain == default_toolchain) {
- pool("link_pool") {
- depth = 1
- }
- }
-
- toolchain("toolchain") {
- tool("link") {
- command = "..."
- pool = ":link_pool($default_toolchain)")
- }
- }
-)*";
-
-const char kDepth[] = "depth";
-
-Value RunPool(const FunctionCallNode* function,
- const std::vector<Value>& args,
- Scope* scope,
- Err* err) {
- NonNestableBlock non_nestable(scope, function, "pool");
- if (!non_nestable.Enter(err))
- return Value();
-
- if (!EnsureSingleStringArg(function, args, err) ||
- !EnsureNotProcessingImport(function, scope, err))
- return Value();
-
- Label label(MakeLabelForScope(scope, function, args[0].string_value()));
-
- if (g_scheduler->verbose_logging())
- g_scheduler->Log("Defining pool", label.GetUserVisibleName(true));
-
- // Get the pool depth. It is an error to define a pool without a depth,
- // so check first for the presence of the value.
- const Value* depth = scope->GetValue(kDepth, true);
- if (!depth) {
- *err = Err(function, "Can't define a pool without depth.");
- return Value();
- }
-
- if (!depth->VerifyTypeIs(Value::INTEGER, err))
- return Value();
-
- if (depth->int_value() < 0) {
- *err = Err(*depth, "depth must be positive or 0.");
- return Value();
- }
-
- // Create the new pool.
- std::unique_ptr<Pool> pool = std::make_unique<Pool>(
- scope->settings(), label, scope->build_dependency_files());
-
- if (label.name() == "console") {
- const Settings* settings = scope->settings();
- if (!settings->is_default()) {
- *err = Err(
- function,
- "\"console\" pool must be defined only in the default toolchain.");
- return Value();
- }
- if (label.dir() != settings->build_settings()->root_target_label().dir()) {
- *err = Err(function, "\"console\" pool must be defined in the root //.");
- return Value();
- }
- if (depth->int_value() != 1) {
- *err = Err(*depth, "\"console\" pool must have depth 1.");
- return Value();
- }
- }
- pool->set_depth(depth->int_value());
-
- // Save the generated item.
- Scope::ItemVector* collector = scope->GetItemCollector();
- if (!collector) {
- *err = Err(function, "Can't define a pool in this context.");
- return Value();
- }
- collector->push_back(std::move(pool));
-
- return Value();
-}
-
-// print -----------------------------------------------------------------------
-
-const char kPrint[] = "print";
-const char kPrint_HelpShort[] =
- "print: Prints to the console.";
-const char kPrint_Help[] =
- R"(print: Prints to the console.
-
- Prints all arguments to the console separated by spaces. A newline is
- automatically appended to the end.
-
- This function is intended for debugging. Note that build files are run in
- parallel so you may get interleaved prints. A buildfile may also be executed
- more than once in parallel in the context of different toolchains so the
- prints from one file may be duplicated or
- interleaved with itself.
-
-Examples
-
- print("Hello world")
-
- print(sources, deps)
-)";
-
-Value RunPrint(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err) {
- std::string output;
- for (size_t i = 0; i < args.size(); i++) {
- if (i != 0)
- output.push_back(' ');
- output.append(args[i].ToString(false));
- }
- output.push_back('\n');
-
- const BuildSettings::PrintCallback& cb =
- scope->settings()->build_settings()->print_callback();
- if (cb.is_null()) {
- printf("%s", output.c_str());
- fflush(stdout);
- } else
- cb.Run(output);
-
- return Value();
-}
-
-// split_list ------------------------------------------------------------------
-
-const char kSplitList[] = "split_list";
-const char kSplitList_HelpShort[] =
- "split_list: Splits a list into N different sub-lists.";
-const char kSplitList_Help[] =
- R"(split_list: Splits a list into N different sub-lists.
-
- result = split_list(input, n)
-
- Given a list and a number N, splits the list into N sub-lists of
- approximately equal size. The return value is a list of the sub-lists. The
- result will always be a list of size N. If N is greater than the number of
- elements in the input, it will be padded with empty lists.
-
- The expected use is to divide source files into smaller uniform chunks.
-
-Example
-
- The code:
- mylist = [1, 2, 3, 4, 5, 6]
- print(split_list(mylist, 3))
-
- Will print:
- [[1, 2], [3, 4], [5, 6]
-)";
-Value RunSplitList(Scope* scope,
- const FunctionCallNode* function,
- const ListNode* args_list,
- Err* err) {
- const auto& args_vector = args_list->contents();
- if (args_vector.size() != 2) {
- *err = Err(function, "Wrong number of arguments to split_list().",
- "Expecting exactly two.");
- return Value();
- }
-
- ParseNodeValueAdapter list_adapter;
- if (!list_adapter.InitForType(scope, args_vector[0].get(), Value::LIST, err))
- return Value();
- const std::vector<Value>& input = list_adapter.get().list_value();
-
- ParseNodeValueAdapter count_adapter;
- if (!count_adapter.InitForType(scope, args_vector[1].get(), Value::INTEGER,
- err))
- return Value();
- int64_t count = count_adapter.get().int_value();
- if (count <= 0) {
- *err = Err(function, "Requested result size is not positive.");
- return Value();
- }
-
- Value result(function, Value::LIST);
- result.list_value().resize(count);
-
- // Every result list gets at least this many items in it.
- int64_t min_items_per_list = static_cast<int64_t>(input.size()) / count;
-
- // This many result lists get an extra item which is the remainder from above.
- int64_t extra_items = static_cast<int64_t>(input.size()) % count;
-
- // Allocate all lists that have a remainder assigned to them (max items).
- int64_t max_items_per_list = min_items_per_list + 1;
- auto last_item_end = input.begin();
- for (int64_t i = 0; i < extra_items; i++) {
- result.list_value()[i] = Value(function, Value::LIST);
-
- auto begin_add = last_item_end;
- last_item_end += max_items_per_list;
- result.list_value()[i].list_value().assign(begin_add, last_item_end);
- }
-
- // Allocate all smaller items that don't have a remainder.
- for (int64_t i = extra_items; i < count; i++) {
- result.list_value()[i] = Value(function, Value::LIST);
-
- auto begin_add = last_item_end;
- last_item_end += min_items_per_list;
- result.list_value()[i].list_value().assign(begin_add, last_item_end);
- }
-
- return result;
-}
-
-// -----------------------------------------------------------------------------
-
-FunctionInfo::FunctionInfo()
- : self_evaluating_args_runner(nullptr),
- generic_block_runner(nullptr),
- executed_block_runner(nullptr),
- no_block_runner(nullptr),
- help_short(nullptr),
- help(nullptr),
- is_target(false) {
-}
-
-FunctionInfo::FunctionInfo(SelfEvaluatingArgsFunction seaf,
- const char* in_help_short,
- const char* in_help,
- bool in_is_target)
- : self_evaluating_args_runner(seaf),
- generic_block_runner(nullptr),
- executed_block_runner(nullptr),
- no_block_runner(nullptr),
- help_short(in_help_short),
- help(in_help),
- is_target(in_is_target) {
-}
-
-FunctionInfo::FunctionInfo(GenericBlockFunction gbf,
- const char* in_help_short,
- const char* in_help,
- bool in_is_target)
- : self_evaluating_args_runner(nullptr),
- generic_block_runner(gbf),
- executed_block_runner(nullptr),
- no_block_runner(nullptr),
- help_short(in_help_short),
- help(in_help),
- is_target(in_is_target) {
-}
-
-FunctionInfo::FunctionInfo(ExecutedBlockFunction ebf,
- const char* in_help_short,
- const char* in_help,
- bool in_is_target)
- : self_evaluating_args_runner(nullptr),
- generic_block_runner(nullptr),
- executed_block_runner(ebf),
- no_block_runner(nullptr),
- help_short(in_help_short),
- help(in_help),
- is_target(in_is_target) {
-}
-
-FunctionInfo::FunctionInfo(NoBlockFunction nbf,
- const char* in_help_short,
- const char* in_help,
- bool in_is_target)
- : self_evaluating_args_runner(nullptr),
- generic_block_runner(nullptr),
- executed_block_runner(nullptr),
- no_block_runner(nbf),
- help_short(in_help_short),
- help(in_help),
- is_target(in_is_target) {
-}
-
-// Setup the function map via a static initializer. We use this because it
-// avoids race conditions without having to do some global setup function or
-// locking-heavy singleton checks at runtime. In practice, we always need this
-// before we can do anything interesting, so it's OK to wait for the
-// initializer.
-struct FunctionInfoInitializer {
- FunctionInfoMap map;
-
- FunctionInfoInitializer() {
- #define INSERT_FUNCTION(command, is_target) \
- map[k##command] = FunctionInfo(&Run##command, \
- k##command##_HelpShort, \
- k##command##_Help, \
- is_target);
-
- INSERT_FUNCTION(Action, true)
- INSERT_FUNCTION(ActionForEach, true)
- INSERT_FUNCTION(BundleData, true)
- INSERT_FUNCTION(CreateBundle, true)
- INSERT_FUNCTION(Copy, true)
- INSERT_FUNCTION(Executable, true)
- INSERT_FUNCTION(Group, true)
- INSERT_FUNCTION(LoadableModule, true)
- INSERT_FUNCTION(SharedLibrary, true)
- INSERT_FUNCTION(SourceSet, true)
- INSERT_FUNCTION(StaticLibrary, true)
- INSERT_FUNCTION(Target, true)
-
- INSERT_FUNCTION(Assert, false)
- INSERT_FUNCTION(Config, false)
- INSERT_FUNCTION(DeclareArgs, false)
- INSERT_FUNCTION(Defined, false)
- INSERT_FUNCTION(ExecScript, false)
- INSERT_FUNCTION(ForEach, false)
- INSERT_FUNCTION(ForwardVariablesFrom, false)
- INSERT_FUNCTION(GetEnv, false)
- INSERT_FUNCTION(GetLabelInfo, false)
- INSERT_FUNCTION(GetPathInfo, false)
- INSERT_FUNCTION(GetTargetOutputs, false)
- INSERT_FUNCTION(Import, false)
- INSERT_FUNCTION(NotNeeded, false)
- INSERT_FUNCTION(Pool, false)
- INSERT_FUNCTION(Print, false)
- INSERT_FUNCTION(ProcessFileTemplate, false)
- INSERT_FUNCTION(ReadFile, false)
- INSERT_FUNCTION(RebasePath, false)
- INSERT_FUNCTION(SetDefaults, false)
- INSERT_FUNCTION(SetDefaultToolchain, false)
- INSERT_FUNCTION(SetSourcesAssignmentFilter, false)
- INSERT_FUNCTION(SplitList, false)
- INSERT_FUNCTION(Template, false)
- INSERT_FUNCTION(Tool, false)
- INSERT_FUNCTION(Toolchain, false)
- INSERT_FUNCTION(WriteFile, false)
-
- #undef INSERT_FUNCTION
- }
-};
-const FunctionInfoInitializer function_info;
-
-const FunctionInfoMap& GetFunctions() {
- return function_info.map;
-}
-
-Value RunFunction(Scope* scope,
- const FunctionCallNode* function,
- const ListNode* args_list,
- BlockNode* block,
- Err* err) {
- const Token& name = function->function();
-
- std::string template_name = function->function().value().as_string();
- const Template* templ = scope->GetTemplate(template_name);
- if (templ) {
- Value args = args_list->Execute(scope, err);
- if (err->has_error())
- return Value();
- return templ->Invoke(scope, function, template_name, args.list_value(),
- block, err);
- }
-
- // No template matching this, check for a built-in function.
- const FunctionInfoMap& function_map = GetFunctions();
- FunctionInfoMap::const_iterator found_function =
- function_map.find(name.value());
- if (found_function == function_map.end()) {
- *err = Err(name, "Unknown function.");
- return Value();
- }
-
- if (found_function->second.self_evaluating_args_runner) {
- // Self evaluating args functions are special weird built-ins like foreach.
- // Rather than force them all to check that they have a block or no block
- // and risk bugs for new additions, check a whitelist here.
- if (found_function->second.self_evaluating_args_runner != &RunForEach) {
- if (!VerifyNoBlockForFunctionCall(function, block, err))
- return Value();
- }
- return found_function->second.self_evaluating_args_runner(
- scope, function, args_list, err);
- }
-
- // All other function types take a pre-executed set of args.
- Value args = args_list->Execute(scope, err);
- if (err->has_error())
- return Value();
-
- if (found_function->second.generic_block_runner) {
- if (!block) {
- FillNeedsBlockError(function, err);
- return Value();
- }
- return found_function->second.generic_block_runner(
- scope, function, args.list_value(), block, err);
- }
-
- if (found_function->second.executed_block_runner) {
- if (!block) {
- FillNeedsBlockError(function, err);
- return Value();
- }
-
- Scope block_scope(scope);
- block->Execute(&block_scope, err);
- if (err->has_error())
- return Value();
-
- Value result = found_function->second.executed_block_runner(
- function, args.list_value(), &block_scope, err);
- if (err->has_error())
- return Value();
-
- if (!block_scope.CheckForUnusedVars(err))
- return Value();
- return result;
- }
-
- // Otherwise it's a no-block function.
- if (!VerifyNoBlockForFunctionCall(function, block, err))
- return Value();
- return found_function->second.no_block_runner(scope, function,
- args.list_value(), err);
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/functions.h b/chromium/tools/gn/functions.h
deleted file mode 100644
index c09612c40de..00000000000
--- a/chromium/tools/gn/functions.h
+++ /dev/null
@@ -1,512 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_FUNCTIONS_H_
-#define TOOLS_GN_FUNCTIONS_H_
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "base/strings/string_piece.h"
-
-class Err;
-class BlockNode;
-class FunctionCallNode;
-class Label;
-class ListNode;
-class ParseNode;
-class Scope;
-class Value;
-
-// -----------------------------------------------------------------------------
-
-namespace functions {
-
-// This type of function invocation has no block and evaluates its arguments
-// itself rather than taking a pre-executed list. This allows us to implement
-// certain built-in functions.
-typedef Value (*SelfEvaluatingArgsFunction)(Scope* scope,
- const FunctionCallNode* function,
- const ListNode* args_list,
- Err* err);
-
-// This type of function invocation takes a block node that it will execute.
-typedef Value (*GenericBlockFunction)(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-// This type of function takes a block, but does not need to control execution
-// of it. The dispatch function will pre-execute the block and pass the
-// resulting block_scope to the function.
-typedef Value(*ExecutedBlockFunction)(const FunctionCallNode* function,
- const std::vector<Value>& args,
- Scope* block_scope,
- Err* err);
-
-// This type of function does not take a block. It just has arguments.
-typedef Value (*NoBlockFunction)(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-extern const char kAction[];
-extern const char kAction_HelpShort[];
-extern const char kAction_Help[];
-Value RunAction(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kActionForEach[];
-extern const char kActionForEach_HelpShort[];
-extern const char kActionForEach_Help[];
-Value RunActionForEach(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kAssert[];
-extern const char kAssert_HelpShort[];
-extern const char kAssert_Help[];
-Value RunAssert(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-extern const char kBundleData[];
-extern const char kBundleData_HelpShort[];
-extern const char kBundleData_Help[];
-Value RunBundleData(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kCreateBundle[];
-extern const char kCreateBundle_HelpShort[];
-extern const char kCreateBundle_Help[];
-Value RunCreateBundle(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kConfig[];
-extern const char kConfig_HelpShort[];
-extern const char kConfig_Help[];
-Value RunConfig(const FunctionCallNode* function,
- const std::vector<Value>& args,
- Scope* block_scope,
- Err* err);
-
-extern const char kCopy[];
-extern const char kCopy_HelpShort[];
-extern const char kCopy_Help[];
-Value RunCopy(const FunctionCallNode* function,
- const std::vector<Value>& args,
- Scope* block_scope,
- Err* err);
-
-extern const char kDeclareArgs[];
-extern const char kDeclareArgs_HelpShort[];
-extern const char kDeclareArgs_Help[];
-Value RunDeclareArgs(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kDefined[];
-extern const char kDefined_HelpShort[];
-extern const char kDefined_Help[];
-Value RunDefined(Scope* scope,
- const FunctionCallNode* function,
- const ListNode* args_list,
- Err* err);
-
-extern const char kExecScript[];
-extern const char kExecScript_HelpShort[];
-extern const char kExecScript_Help[];
-Value RunExecScript(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-extern const char kExecutable[];
-extern const char kExecutable_HelpShort[];
-extern const char kExecutable_Help[];
-Value RunExecutable(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kForEach[];
-extern const char kForEach_HelpShort[];
-extern const char kForEach_Help[];
-Value RunForEach(Scope* scope,
- const FunctionCallNode* function,
- const ListNode* args_list,
- Err* err);
-
-extern const char kForwardVariablesFrom[];
-extern const char kForwardVariablesFrom_HelpShort[];
-extern const char kForwardVariablesFrom_Help[];
-Value RunForwardVariablesFrom(Scope* scope,
- const FunctionCallNode* function,
- const ListNode* args_list,
- Err* err);
-
-extern const char kGetEnv[];
-extern const char kGetEnv_HelpShort[];
-extern const char kGetEnv_Help[];
-Value RunGetEnv(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-extern const char kGetLabelInfo[];
-extern const char kGetLabelInfo_HelpShort[];
-extern const char kGetLabelInfo_Help[];
-Value RunGetLabelInfo(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-extern const char kGetPathInfo[];
-extern const char kGetPathInfo_HelpShort[];
-extern const char kGetPathInfo_Help[];
-Value RunGetPathInfo(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-extern const char kGetTargetOutputs[];
-extern const char kGetTargetOutputs_HelpShort[];
-extern const char kGetTargetOutputs_Help[];
-Value RunGetTargetOutputs(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-extern const char kGroup[];
-extern const char kGroup_HelpShort[];
-extern const char kGroup_Help[];
-Value RunGroup(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kImport[];
-extern const char kImport_HelpShort[];
-extern const char kImport_Help[];
-Value RunImport(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-extern const char kLoadableModule[];
-extern const char kLoadableModule_HelpShort[];
-extern const char kLoadableModule_Help[];
-Value RunLoadableModule(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kNotNeeded[];
-extern const char kNotNeeded_HelpShort[];
-extern const char kNotNeeded_Help[];
-Value RunNotNeeded(Scope* scope,
- const FunctionCallNode* function,
- const ListNode* args_list,
- Err* err);
-
-extern const char kPool[];
-extern const char kPool_HelpShort[];
-extern const char kPool_Help[];
-Value RunPool(const FunctionCallNode* function,
- const std::vector<Value>& args,
- Scope* block_scope,
- Err* err);
-
-extern const char kPrint[];
-extern const char kPrint_HelpShort[];
-extern const char kPrint_Help[];
-Value RunPrint(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-extern const char kProcessFileTemplate[];
-extern const char kProcessFileTemplate_HelpShort[];
-extern const char kProcessFileTemplate_Help[];
-Value RunProcessFileTemplate(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-extern const char kReadFile[];
-extern const char kReadFile_HelpShort[];
-extern const char kReadFile_Help[];
-Value RunReadFile(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-extern const char kRebasePath[];
-extern const char kRebasePath_HelpShort[];
-extern const char kRebasePath_Help[];
-Value RunRebasePath(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-extern const char kSetDefaults[];
-extern const char kSetDefaults_HelpShort[];
-extern const char kSetDefaults_Help[];
-Value RunSetDefaults(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kSetDefaultToolchain[];
-extern const char kSetDefaultToolchain_HelpShort[];
-extern const char kSetDefaultToolchain_Help[];
-Value RunSetDefaultToolchain(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-extern const char kSetSourcesAssignmentFilter[];
-extern const char kSetSourcesAssignmentFilter_HelpShort[];
-extern const char kSetSourcesAssignmentFilter_Help[];
-Value RunSetSourcesAssignmentFilter(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-extern const char kSharedLibrary[];
-extern const char kSharedLibrary_HelpShort[];
-extern const char kSharedLibrary_Help[];
-Value RunSharedLibrary(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kSourceSet[];
-extern const char kSourceSet_HelpShort[];
-extern const char kSourceSet_Help[];
-Value RunSourceSet(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kSplitList[];
-extern const char kSplitList_HelpShort[];
-extern const char kSplitList_Help[];
-Value RunSplitList(Scope* scope,
- const FunctionCallNode* function,
- const ListNode* args_list,
- Err* err);
-
-extern const char kStaticLibrary[];
-extern const char kStaticLibrary_HelpShort[];
-extern const char kStaticLibrary_Help[];
-Value RunStaticLibrary(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kTarget[];
-extern const char kTarget_HelpShort[];
-extern const char kTarget_Help[];
-Value RunTarget(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kTemplate[];
-extern const char kTemplate_HelpShort[];
-extern const char kTemplate_Help[];
-Value RunTemplate(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kTool[];
-extern const char kTool_HelpShort[];
-extern const char kTool_Help[];
-Value RunTool(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kToolchain[];
-extern const char kToolchain_HelpShort[];
-extern const char kToolchain_Help[];
-Value RunToolchain(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err);
-
-extern const char kWriteFile[];
-extern const char kWriteFile_HelpShort[];
-extern const char kWriteFile_Help[];
-Value RunWriteFile(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-// -----------------------------------------------------------------------------
-
-// One function record. Only one of the given runner types will be non-null
-// which indicates the type of function it is.
-struct FunctionInfo {
- FunctionInfo();
- FunctionInfo(SelfEvaluatingArgsFunction seaf,
- const char* in_help_short,
- const char* in_help,
- bool in_is_target);
- FunctionInfo(GenericBlockFunction gbf,
- const char* in_help_short,
- const char* in_help,
- bool in_is_target);
- FunctionInfo(ExecutedBlockFunction ebf,
- const char* in_help_short,
- const char* in_help,
- bool in_is_target);
- FunctionInfo(NoBlockFunction nbf,
- const char* in_help_short,
- const char* in_help,
- bool in_is_target);
-
- SelfEvaluatingArgsFunction self_evaluating_args_runner;
- GenericBlockFunction generic_block_runner;
- ExecutedBlockFunction executed_block_runner;
- NoBlockFunction no_block_runner;
-
- const char* help_short;
- const char* help;
-
- bool is_target;
-};
-
-typedef std::map<base::StringPiece, FunctionInfo> FunctionInfoMap;
-
-// Returns the mapping of all built-in functions.
-const FunctionInfoMap& GetFunctions();
-
-// Runs the given function.
-Value RunFunction(Scope* scope,
- const FunctionCallNode* function,
- const ListNode* args_list,
- BlockNode* block, // Optional.
- Err* err);
-
-} // namespace functions
-
-// Helper functions -----------------------------------------------------------
-
-// Validates that the scope that a value is defined in is not the scope
-// of the current declare_args() call, if that's what we're in. It is
-// illegal to read a value from inside the same declare_args() call, since
-// the overrides will not have been applied yet (see `gn help declare_args`
-// for more).
-bool EnsureNotReadingFromSameDeclareArgs(const ParseNode* node,
- const Scope* cur_scope,
- const Scope* val_scope,
- Err* err);
-
-// Verifies that the current scope is not processing an import. If it is, it
-// will set the error, blame the given parse node for it, and return false.
-bool EnsureNotProcessingImport(const ParseNode* node,
- const Scope* scope,
- Err* err);
-
-// Like EnsureNotProcessingImport but checks for running the build config.
-bool EnsureNotProcessingBuildConfig(const ParseNode* node,
- const Scope* scope,
- Err* err);
-
-// Sets up the |block_scope| for executing a target (or something like it).
-// The |scope| is the containing scope. It should have been already set as the
-// parent for the |block_scope| when the |block_scope| was created.
-//
-// This will set up the target defaults and set the |target_name| variable in
-// the block scope to the current target name, which is assumed to be the first
-// argument to the function.
-//
-// On success, returns true. On failure, sets the error and returns false.
-bool FillTargetBlockScope(const Scope* scope,
- const FunctionCallNode* function,
- const std::string& target_type,
- const BlockNode* block,
- const std::vector<Value>& args,
- Scope* block_scope,
- Err* err);
-
-// Sets the given error to a message explaining that the function call requires
-// a block.
-void FillNeedsBlockError(const FunctionCallNode* function, Err* err);
-
-// Validates that the given function call has one string argument. This is
-// the most common function signature, so it saves space to have this helper.
-// Returns false and sets the error on failure.
-bool EnsureSingleStringArg(const FunctionCallNode* function,
- const std::vector<Value>& args,
- Err* err);
-
-// Returns the name of the toolchain for the given scope.
-const Label& ToolchainLabelForScope(const Scope* scope);
-
-// Generates a label for the given scope, using the current directory and
-// toolchain, and the given name.
-Label MakeLabelForScope(const Scope* scope,
- const FunctionCallNode* function,
- const std::string& name);
-
-// Some types of blocks can't be nested inside other ones. For such cases,
-// instantiate this object upon entering the block and Enter() will fail if
-// there is already another non-nestable block on the stack.
-class NonNestableBlock {
- public:
- // type_description is a string that will be used in error messages
- // describing the type of the block, for example, "template" or "config".
- NonNestableBlock(Scope* scope,
- const FunctionCallNode* function,
- const char* type_description);
- ~NonNestableBlock();
-
- bool Enter(Err* err);
-
- private:
- // Used as a void* key for the Scope to track our property. The actual value
- // is never used.
- static const int kKey;
-
- Scope* scope_;
- const FunctionCallNode* function_;
- const char* type_description_;
-
- // Set to true when the key is added to the scope so we don't try to
- // delete nonexistant keys which will cause assertions.
- bool key_added_;
-};
-
-#endif // TOOLS_GN_FUNCTIONS_H_
diff --git a/chromium/tools/gn/functions_target.cc b/chromium/tools/gn/functions_target.cc
deleted file mode 100644
index 5fec1ffc3d2..00000000000
--- a/chromium/tools/gn/functions_target.cc
+++ /dev/null
@@ -1,797 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/functions.h"
-
-#include "tools/gn/config_values_generator.h"
-#include "tools/gn/err.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/target_generator.h"
-#include "tools/gn/template.h"
-#include "tools/gn/value.h"
-#include "tools/gn/variables.h"
-
-#define DEPENDENT_CONFIG_VARS \
- " Dependent configs: all_dependent_configs, public_configs\n"
-#define DEPS_VARS \
- " Deps: data_deps, deps, public_deps\n"
-#define GENERAL_TARGET_VARS \
- " General: check_includes, configs, data, friend, inputs, output_name,\n" \
- " output_extension, public, sources, testonly, visibility\n"
-
-namespace functions {
-
-namespace {
-
-Value ExecuteGenericTarget(const char* target_type,
- Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- NonNestableBlock non_nestable(scope, function, "target");
- if (!non_nestable.Enter(err))
- return Value();
-
- if (!EnsureNotProcessingImport(function, scope, err) ||
- !EnsureNotProcessingBuildConfig(function, scope, err))
- return Value();
- Scope block_scope(scope);
- if (!FillTargetBlockScope(scope, function, target_type, block,
- args, &block_scope, err))
- return Value();
-
- block->Execute(&block_scope, err);
- if (err->has_error())
- return Value();
-
- TargetGenerator::GenerateTarget(&block_scope, function, args,
- target_type, err);
- if (err->has_error())
- return Value();
-
- block_scope.CheckForUnusedVars(err);
- return Value();
-}
-
-} // namespace
-
-// action ----------------------------------------------------------------------
-
-// Common help paragraph on script runtime execution directories.
-#define SCRIPT_EXECUTION_CONTEXT \
- "\n" \
- " The script will be executed with the given arguments with the current\n" \
- " directory being that of the root build directory. If you pass files\n" \
- " to your script, see \"gn help rebase_path\" for how to convert\n" \
- " file names to be relative to the build directory (file names in the\n" \
- " sources, outputs, and inputs will be all treated as relative to the\n" \
- " current build file and converted as needed automatically).\n"
-
-// Common help paragraph on script output directories.
-#define SCRIPT_EXECUTION_OUTPUTS \
- "\n" \
- " All output files must be inside the output directory of the build.\n" \
- " You would generally use |$target_out_dir| or |$target_gen_dir| to\n" \
- " reference the output or generated intermediate file directories,\n" \
- " respectively.\n"
-
-#define ACTION_DEPS \
- "\n" \
- " The \"deps\" and \"public_deps\" for an action will always be\n" \
- " completed before any part of the action is run so it can depend on\n" \
- " the output of previous steps. The \"data_deps\" will be built if the\n" \
- " action is built, but may not have completed before all steps of the\n" \
- " action are started. This can give additional parallelism in the build\n" \
- " for runtime-only dependencies.\n"
-
-const char kAction[] = "action";
-const char kAction_HelpShort[] =
- "action: Declare a target that runs a script a single time.";
-const char kAction_Help[] =
- R"(action: Declare a target that runs a script a single time.
-
- This target type allows you to run a script a single time to produce one or
- more output files. If you want to run a script once for each of a set of
- input files, see "gn help action_foreach".
-
-Inputs
-
- In an action the "sources" and "inputs" are treated the same: they're both
- input dependencies on script execution with no special handling. If you want
- to pass the sources to your script, you must do so explicitly by including
- them in the "args". Note also that this means there is no special handling of
- paths since GN doesn't know which of the args are paths and not. You will
- want to use rebase_path() to convert paths to be relative to the
- root_build_dir.
-
- You can dynamically write input dependencies (for incremental rebuilds if an
- input file changes) by writing a depfile when the script is run (see "gn help
- depfile"). This is more flexible than "inputs".
-
- If the command line length is very long, you can use response files to pass
- args to your script. See "gn help response_file_contents".
-
- It is recommended you put inputs to your script in the "sources" variable,
- and stuff like other Python files required to run your script in the "inputs"
- variable.
-)"
-
- ACTION_DEPS
-
-R"(
-Outputs
-
- You should specify files created by your script by specifying them in the
- "outputs".
-)"
-
- SCRIPT_EXECUTION_CONTEXT
-
-R"(
-File name handling
-)"
-
- SCRIPT_EXECUTION_OUTPUTS
-
-R"(
-Variables
-
- args, data, data_deps, depfile, deps, inputs, outputs*, pool,
- response_file_contents, script*, sources
- * = required
-
-Example
-
- action("run_this_guy_once") {
- script = "doprocessing.py"
- sources = [ "my_configuration.txt" ]
- outputs = [ "$target_gen_dir/insightful_output.txt" ]
-
- # Our script imports this Python file so we want to rebuild if it changes.
- inputs = [ "helper_library.py" ]
-
- # Note that we have to manually pass the sources to our script if the
- # script needs them as inputs.
- args = [ "--out", rebase_path(target_gen_dir, root_build_dir) ] +
- rebase_path(sources, root_build_dir)
- }
-)";
-
-Value RunAction(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- return ExecuteGenericTarget(functions::kAction, scope, function, args,
- block, err);
-}
-
-// action_foreach --------------------------------------------------------------
-
-const char kActionForEach[] = "action_foreach";
-const char kActionForEach_HelpShort[] =
- "action_foreach: Declare a target that runs a script over a set of files.";
-const char kActionForEach_Help[] =
- R"(action_foreach: Declare a target that runs a script over a set of files.
-
- This target type allows you to run a script once-per-file over a set of
- sources. If you want to run a script once that takes many files as input, see
- "gn help action".
-
-Inputs
-
- The script will be run once per file in the "sources" variable. The "outputs"
- variable should specify one or more files with a source expansion pattern in
- it (see "gn help source_expansion"). The output file(s) for each script
- invocation should be unique. Normally you use "{{source_name_part}}" in each
- output file.
-
- If your script takes additional data as input, such as a shared configuration
- file or a Python module it uses, those files should be listed in the "inputs"
- variable. These files are treated as dependencies of each script invocation.
-
- If the command line length is very long, you can use response files to pass
- args to your script. See "gn help response_file_contents".
-
- You can dynamically write input dependencies (for incremental rebuilds if an
- input file changes) by writing a depfile when the script is run (see "gn help
- depfile"). This is more flexible than "inputs".
-)"
- ACTION_DEPS
-R"(
-Outputs
-)"
- SCRIPT_EXECUTION_CONTEXT
-R"(
-File name handling
-)"
- SCRIPT_EXECUTION_OUTPUTS
-R"(
-Variables
-
- args, data, data_deps, depfile, deps, inputs, outputs*, pool,
- response_file_contents, script*, sources*
- * = required
-
-Example
-
- # Runs the script over each IDL file. The IDL script will generate both a .cc
- # and a .h file for each input.
- action_foreach("my_idl") {
- script = "idl_processor.py"
- sources = [ "foo.idl", "bar.idl" ]
-
- # Our script reads this file each time, so we need to list is as a
- # dependency so we can rebuild if it changes.
- inputs = [ "my_configuration.txt" ]
-
- # Transformation from source file name to output file names.
- outputs = [ "$target_gen_dir/{{source_name_part}}.h",
- "$target_gen_dir/{{source_name_part}}.cc" ]
-
- # Note that since "args" is opaque to GN, if you specify paths here, you
- # will need to convert it to be relative to the build directory using
- # rebase_path().
- args = [
- "{{source}}",
- "-o",
- rebase_path(relative_target_gen_dir, root_build_dir) +
- "/{{source_name_part}}.h" ]
- }
-)";
-
-Value RunActionForEach(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- return ExecuteGenericTarget(functions::kActionForEach, scope, function, args,
- block, err);
-}
-
-// bundle_data -----------------------------------------------------------------
-
-const char kBundleData[] = "bundle_data";
-const char kBundleData_HelpShort[] =
- "bundle_data: [iOS/macOS] Declare a target without output.";
-const char kBundleData_Help[] =
- R"(bundle_data: [iOS/macOS] Declare a target without output.
-
- This target type allows to declare data that is required at runtime. It is
- used to inform "create_bundle" targets of the files to copy into generated
- bundle, see "gn help create_bundle" for help.
-
- The target must define a list of files as "sources" and a single "outputs".
- If there are multiple files, source expansions must be used to express the
- output. The output must reference a file inside of {{bundle_root_dir}}.
-
- This target can be used on all platforms though it is designed only to
- generate iOS/macOS bundle. In cross-platform projects, it is advised to put it
- behind iOS/macOS conditionals.
-
- See "gn help create_bundle" for more information.
-
-Variables
-
- sources*, outputs*, deps, data_deps, public_deps, visibility
- * = required
-
-Examples
-
- bundle_data("icudata") {
- sources = [ "sources/data/in/icudtl.dat" ]
- outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ]
- }
-
- bundle_data("base_unittests_bundle_data]") {
- sources = [ "test/data" ]
- outputs = [
- "{{bundle_resources_dir}}/{{source_root_relative_dir}}/" +
- "{{source_file_part}}"
- ]
- }
-
- bundle_data("material_typography_bundle_data") {
- sources = [
- "src/MaterialTypography.bundle/Roboto-Bold.ttf",
- "src/MaterialTypography.bundle/Roboto-Italic.ttf",
- "src/MaterialTypography.bundle/Roboto-Regular.ttf",
- "src/MaterialTypography.bundle/Roboto-Thin.ttf",
- ]
- outputs = [
- "{{bundle_resources_dir}}/MaterialTypography.bundle/"
- "{{source_file_part}}"
- ]
- }
-)";
-
-Value RunBundleData(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- return ExecuteGenericTarget(functions::kBundleData, scope, function, args,
- block, err);
-}
-
-// create_bundle ---------------------------------------------------------------
-
-const char kCreateBundle[] = "create_bundle";
-const char kCreateBundle_HelpShort[] =
- "create_bundle: [iOS/macOS] Build an iOS or macOS bundle.";
-const char kCreateBundle_Help[] =
- R"(create_bundle: [ios/macOS] Build an iOS or macOS bundle.
-
- This target generates an iOS or macOS bundle (which is a directory with a
- well-know structure). This target does not define any sources, instead they
- are computed from all "bundle_data" target this one depends on transitively
- (the recursion stops at "create_bundle" targets).
-
- The "bundle_*_dir" properties must be defined. They will be used for the
- expansion of {{bundle_*_dir}} rules in "bundle_data" outputs.
-
- This target can be used on all platforms though it is designed only to
- generate iOS or macOS bundle. In cross-platform projects, it is advised to put
- it behind iOS/macOS conditionals.
-
- If a create_bundle is specified as a data_deps for another target, the bundle
- is considered a leaf, and its public and private dependencies will not
- contribute to any data or data_deps. Required runtime dependencies should be
- placed in the bundle. A create_bundle can declare its own explicit data and
- data_deps, however.
-
-Code signing
-
- Some bundle needs to be code signed as part of the build (on iOS all
- application needs to be code signed to run on a device). The code signature
- can be configured via the code_signing_script variable.
-
- If set, code_signing_script is the path of a script that invoked after all
- files have been moved into the bundle. The script must not change any file in
- the bundle, but may add new files.
-
- If code_signing_script is defined, then code_signing_outputs must also be
- defined and non-empty to inform when the script needs to be re-run. The
- code_signing_args will be passed as is to the script (so path have to be
- rebased) and additional inputs may be listed with the variable
- code_signing_sources.
-
-Variables
-
- bundle_root_dir*, bundle_contents_dir*, bundle_resources_dir*,
- bundle_executable_dir*, bundle_plugins_dir*, bundle_deps_filter, deps,
- data_deps, public_deps, visibility, product_type, code_signing_args,
- code_signing_script, code_signing_sources, code_signing_outputs,
- xcode_extra_attributes, xcode_test_application_name, partial_info_plist
- * = required
-
-Example
-
- # Defines a template to create an application. On most platform, this is just
- # an alias for an "executable" target, but on iOS/macOS, it builds an
- # application bundle.
- template("app") {
- if (!is_ios && !is_mac) {
- executable(target_name) {
- forward_variables_from(invoker, "*")
- }
- } else {
- app_name = target_name
- gen_path = target_gen_dir
-
- action("${app_name}_generate_info_plist") {
- script = [ "//build/ios/ios_gen_plist.py" ]
- sources = [ "templates/Info.plist" ]
- outputs = [ "$gen_path/Info.plist" ]
- args = rebase_path(sources, root_build_dir) +
- rebase_path(outputs, root_build_dir)
- }
-
- bundle_data("${app_name}_bundle_info_plist") {
- deps = [ ":${app_name}_generate_info_plist" ]
- sources = [ "$gen_path/Info.plist" ]
- outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
- }
-
- executable("${app_name}_generate_executable") {
- forward_variables_from(invoker, "*", [
- "output_name",
- "visibility",
- ])
- output_name =
- rebase_path("$gen_path/$app_name", root_build_dir)
- }
-
- code_signing =
- defined(invoker.code_signing) && invoker.code_signing
-
- if (is_ios && !code_signing) {
- bundle_data("${app_name}_bundle_executable") {
- deps = [ ":${app_name}_generate_executable" ]
- sources = [ "$gen_path/$app_name" ]
- outputs = [ "{{bundle_executable_dir}}/$app_name" ]
- }
- }
-
- create_bundle("${app_name}.app") {
- product_type = "com.apple.product-type.application"
-
- if (is_ios) {
- bundle_root_dir = "${root_build_dir}/$target_name"
- bundle_contents_dir = bundle_root_dir
- bundle_resources_dir = bundle_contents_dir
- bundle_executable_dir = bundle_contents_dir
- bundle_plugins_dir = "${bundle_contents_dir}/Plugins"
-
- extra_attributes = {
- ONLY_ACTIVE_ARCH = "YES"
- DEBUG_INFORMATION_FORMAT = "dwarf"
- }
- } else {
- bundle_root_dir = "${root_build_dir}/target_name"
- bundle_contents_dir = "${bundle_root_dir}/Contents"
- bundle_resources_dir = "${bundle_contents_dir}/Resources"
- bundle_executable_dir = "${bundle_contents_dir}/MacOS"
- bundle_plugins_dir = "${bundle_contents_dir}/Plugins"
- }
- deps = [ ":${app_name}_bundle_info_plist" ]
- if (is_ios && code_signing) {
- deps += [ ":${app_name}_generate_executable" ]
- code_signing_script = "//build/config/ios/codesign.py"
- code_signing_sources = [
- invoker.entitlements_path,
- "$target_gen_dir/$app_name",
- ]
- code_signing_outputs = [
- "$bundle_root_dir/$app_name",
- "$bundle_root_dir/_CodeSignature/CodeResources",
- "$bundle_root_dir/embedded.mobileprovision",
- "$target_gen_dir/$app_name.xcent",
- ]
- code_signing_args = [
- "-i=" + ios_code_signing_identity,
- "-b=" + rebase_path(
- "$target_gen_dir/$app_name", root_build_dir),
- "-e=" + rebase_path(
- invoker.entitlements_path, root_build_dir),
- "-e=" + rebase_path(
- "$target_gen_dir/$app_name.xcent", root_build_dir),
- rebase_path(bundle_root_dir, root_build_dir),
- ]
- } else {
- deps += [ ":${app_name}_bundle_executable" ]
- }
- }
- }
- }
-)";
-
-Value RunCreateBundle(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- return ExecuteGenericTarget(functions::kCreateBundle, scope, function, args,
- block, err);
-}
-
-// copy ------------------------------------------------------------------------
-
-const char kCopy[] = "copy";
-const char kCopy_HelpShort[] =
- "copy: Declare a target that copies files.";
-const char kCopy_Help[] =
- R"(copy: Declare a target that copies files.
-
-File name handling
-
- All output files must be inside the output directory of the build. You would
- generally use |$target_out_dir| or |$target_gen_dir| to reference the output
- or generated intermediate file directories, respectively.
-
- Both "sources" and "outputs" must be specified. Sources can include as many
- files as you want, but there can only be one item in the outputs list (plural
- is used for the name for consistency with other target types).
-
- If there is more than one source file, your output name should specify a
- mapping from each source file to an output file name using source expansion
- (see "gn help source_expansion"). The placeholders will look like
- "{{source_name_part}}", for example.
-
-Examples
-
- # Write a rule that copies a checked-in DLL to the output directory.
- copy("mydll") {
- sources = [ "mydll.dll" ]
- outputs = [ "$target_out_dir/mydll.dll" ]
- }
-
- # Write a rule to copy several files to the target generated files directory.
- copy("myfiles") {
- sources = [ "data1.dat", "data2.dat", "data3.dat" ]
-
- # Use source expansion to generate output files with the corresponding file
- # names in the gen dir. This will just copy each file.
- outputs = [ "$target_gen_dir/{{source_file_part}}" ]
- }
-)";
-
-Value RunCopy(const FunctionCallNode* function,
- const std::vector<Value>& args,
- Scope* scope,
- Err* err) {
- if (!EnsureNotProcessingImport(function, scope, err) ||
- !EnsureNotProcessingBuildConfig(function, scope, err))
- return Value();
- TargetGenerator::GenerateTarget(scope, function, args, functions::kCopy, err);
- return Value();
-}
-
-// executable ------------------------------------------------------------------
-
-const char kExecutable[] = "executable";
-const char kExecutable_HelpShort[] =
- "executable: Declare an executable target.";
-const char kExecutable_Help[] =
- R"(executable: Declare an executable target.
-
-Variables
-
-)"
- CONFIG_VALUES_VARS_HELP
- DEPS_VARS
- DEPENDENT_CONFIG_VARS
- GENERAL_TARGET_VARS;
-
-Value RunExecutable(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- return ExecuteGenericTarget(functions::kExecutable, scope, function, args,
- block, err);
-}
-
-// group -----------------------------------------------------------------------
-
-const char kGroup[] = "group";
-const char kGroup_HelpShort[] =
- "group: Declare a named group of targets.";
-const char kGroup_Help[] =
- R"(group: Declare a named group of targets.
-
- This target type allows you to create meta-targets that just collect a set of
- dependencies into one named target. Groups can additionally specify configs
- that apply to their dependents.
-
-Variables
-
-)"
- DEPS_VARS
- DEPENDENT_CONFIG_VARS
-
-R"(
-Example
-
- group("all") {
- deps = [
- "//project:runner",
- "//project:unit_tests",
- ]
- }
-)";
-
-Value RunGroup(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- return ExecuteGenericTarget(functions::kGroup, scope, function, args,
- block, err);
-}
-
-// loadable_module -------------------------------------------------------------
-
-const char kLoadableModule[] = "loadable_module";
-const char kLoadableModule_HelpShort[] =
- "loadable_module: Declare a loadable module target.";
-const char kLoadableModule_Help[] =
- R"(loadable_module: Declare a loadable module target.
-
- This target type allows you to create an object file that is (and can only
- be) loaded and unloaded at runtime.
-
- A loadable module will be specified on the linker line for targets listing
- the loadable module in its "deps". If you don't want this (if you don't need
- to dynamically load the library at runtime), then you should use a
- "shared_library" target type instead.
-
-Variables
-
-)"
- CONFIG_VALUES_VARS_HELP
- DEPS_VARS
- DEPENDENT_CONFIG_VARS
- GENERAL_TARGET_VARS;
-
-Value RunLoadableModule(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- return ExecuteGenericTarget(functions::kLoadableModule, scope, function, args,
- block, err);
-}
-
-// shared_library --------------------------------------------------------------
-
-const char kSharedLibrary[] = "shared_library";
-const char kSharedLibrary_HelpShort[] =
- "shared_library: Declare a shared library target.";
-const char kSharedLibrary_Help[] =
- R"(shared_library: Declare a shared library target.
-
- A shared library will be specified on the linker line for targets listing the
- shared library in its "deps". If you don't want this (say you dynamically
- load the library at runtime), then you should depend on the shared library
- via "data_deps" or, on Darwin platforms, use a "loadable_module" target type
- instead.
-
-Variables
-
-)"
- CONFIG_VALUES_VARS_HELP
- DEPS_VARS
- DEPENDENT_CONFIG_VARS
- GENERAL_TARGET_VARS;
-
-Value RunSharedLibrary(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- return ExecuteGenericTarget(functions::kSharedLibrary, scope, function, args,
- block, err);
-}
-
-// source_set ------------------------------------------------------------------
-
-const char kSourceSet[] = "source_set";
-const char kSourceSet_HelpShort[] = "source_set: Declare a source set target.";
-const char kSourceSet_Help[] =
- R"(source_set: Declare a source set target.
-
- A source set is a collection of sources that get compiled, but are not linked
- to produce any kind of library. Instead, the resulting object files are
- implicitly added to the linker line of all targets that depend on the source
- set.
-
- In most cases, a source set will behave like a static library, except no
- actual library file will be produced. This will make the build go a little
- faster by skipping creation of a large static library, while maintaining the
- organizational benefits of focused build targets.
-
- The main difference between a source set and a static library is around
- handling of exported symbols. Most linkers assume declaring a function
- exported means exported from the static library. The linker can then do dead
- code elimination to delete code not reachable from exported functions.
-
- A source set will not do this code elimination since there is no link step.
- This allows you to link many sources sets into a shared library and have the
- "exported symbol" notation indicate "export from the final shared library and
- not from the intermediate targets." There is no way to express this concept
- when linking multiple static libraries into a shared library.
-
-Variables
-
-)" CONFIG_VALUES_VARS_HELP DEPS_VARS DEPENDENT_CONFIG_VARS GENERAL_TARGET_VARS;
-
-Value RunSourceSet(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- return ExecuteGenericTarget(functions::kSourceSet, scope, function, args,
- block, err);
-}
-
-// static_library --------------------------------------------------------------
-
-const char kStaticLibrary[] = "static_library";
-const char kStaticLibrary_HelpShort[] =
- "static_library: Declare a static library target.";
-const char kStaticLibrary_Help[] =
- R"(static_library: Declare a static library target.
-
- Make a ".a" / ".lib" file.
-
- If you only need the static library for intermediate results in the build,
- you should consider a source_set instead since it will skip the (potentially
- slow) step of creating the intermediate library file.
-
-Variables
-
- complete_static_lib
-)"
- CONFIG_VALUES_VARS_HELP
- DEPS_VARS
- DEPENDENT_CONFIG_VARS
- GENERAL_TARGET_VARS;
-
-Value RunStaticLibrary(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- return ExecuteGenericTarget(functions::kStaticLibrary, scope, function, args,
- block, err);
-}
-
-// target ---------------------------------------------------------------------
-
-const char kTarget[] = "target";
-const char kTarget_HelpShort[] =
- "target: Declare an target with the given programmatic type.";
-const char kTarget_Help[] =
- R"(target: Declare an target with the given programmatic type.
-
- target(target_type_string, target_name_string) { ... }
-
- The target() function is a way to invoke a built-in target or template with a
- type determined at runtime. This is useful for cases where the type of a
- target might not be known statically.
-
- Only templates and built-in target functions are supported for the
- target_type_string parameter. Arbitrary functions, configs, and toolchains
- are not supported.
-
- The call:
- target("source_set", "doom_melon") {
- Is equivalent to:
- source_set("doom_melon") {
-
-Example
-
- if (foo_build_as_shared) {
- my_type = "shared_library"
- } else {
- my_type = "source_set"
- }
-
- target(my_type, "foo") {
- ...
- }
-)";
-Value RunTarget(Scope* scope,
- const FunctionCallNode* function,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) {
- if (args.size() != 2) {
- *err = Err(function, "Expected two arguments.", "Try \"gn help target\".");
- return Value();
- }
-
- // The first argument must be a string (the target type). Don't type-check
- // the second argument since the target-specific function will do that.
- if (!args[0].VerifyTypeIs(Value::STRING, err))
- return Value();
- const std::string& target_type = args[0].string_value();
-
- // The rest of the args are passed to the function.
- std::vector<Value> sub_args(args.begin() + 1, args.end());
-
- // Run a template if it is one.
- const Template* templ = scope->GetTemplate(target_type);
- if (templ)
- return templ->Invoke(scope, function, target_type, sub_args, block, err);
-
- // Otherwise, assume the target is a built-in target type.
- return ExecuteGenericTarget(target_type.c_str(), scope, function, sub_args,
- block, err);
-}
-
-} // namespace functions
diff --git a/chromium/tools/gn/functions_target_unittest.cc b/chromium/tools/gn/functions_target_unittest.cc
deleted file mode 100644
index de701ef078c..00000000000
--- a/chromium/tools/gn/functions_target_unittest.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/test_with_scheduler.h"
-#include "tools/gn/test_with_scope.h"
-
-using FunctionsTarget = TestWithScheduler;
-
-// Checks that we find unused identifiers in targets.
-TEST_F(FunctionsTarget, CheckUnused) {
- TestWithScope setup;
-
- // The target generator needs a place to put the targets or it will fail.
- Scope::ItemVector item_collector;
- setup.scope()->set_item_collector(&item_collector);
-
- // Test a good one first.
- TestParseInput good_input(
- "source_set(\"foo\") {\n"
- "}\n");
- ASSERT_FALSE(good_input.has_error());
- Err err;
- good_input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- // Test a source set with an unused variable.
- TestParseInput source_set_input(
- "source_set(\"foo\") {\n"
- " unused = 5\n"
- "}\n");
- ASSERT_FALSE(source_set_input.has_error());
- err = Err();
- source_set_input.parsed()->Execute(setup.scope(), &err);
- ASSERT_TRUE(err.has_error());
-}
-
-// Checks that we find uses of identifiers marked as not needed.
-TEST_F(FunctionsTarget, CheckNotNeeded) {
- TestWithScope setup;
-
- // The target generator needs a place to put the targets or it will fail.
- Scope::ItemVector item_collector;
- setup.scope()->set_item_collector(&item_collector);
-
- TestParseInput nonscoped_input(
- "source_set(\"foo\") {\n"
- " a = 1\n"
- " not_needed([ \"a\" ])\n"
- "}\n");
- ASSERT_FALSE(nonscoped_input.has_error());
- Err err;
- nonscoped_input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- TestParseInput scoped_input(
- "source_set(\"foo\") {\n"
- " a = {x = 1 y = 2}\n"
- " not_needed(a, \"*\")\n"
- "}\n");
- ASSERT_FALSE(scoped_input.has_error());
- err = Err();
- scoped_input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- TestParseInput exclusion_input(
- "source_set(\"foo\") {\n"
- " x = 1\n"
- " y = 2\n"
- " not_needed(\"*\", [ \"y\" ])\n"
- "}\n");
- ASSERT_FALSE(exclusion_input.has_error());
- err = Err();
- exclusion_input.parsed()->Execute(setup.scope(), &err);
- ASSERT_TRUE(err.has_error()) << err.message();
- EXPECT_EQ("Assignment had no effect.", err.message());
-
- TestParseInput error_input(
- "source_set(\"foo\") {\n"
- " a = {x = 1 y = 2}\n"
- " not_needed(a, [ \"x \"], [ \"y\" ])\n"
- "}\n");
- ASSERT_FALSE(error_input.has_error());
- err = Err();
- error_input.parsed()->Execute(setup.scope(), &err);
- ASSERT_TRUE(err.has_error());
- EXPECT_EQ("Not supported with a variable list.", err.message());
-}
-
-// Checks that the defaults applied to a template invoked by target() use
-// the name of the template, rather than the string "target" (which is the
-// name of the actual function being called).
-TEST_F(FunctionsTarget, TemplateDefaults) {
- TestWithScope setup;
-
- // The target generator needs a place to put the targets or it will fail.
- Scope::ItemVector item_collector;
- setup.scope()->set_item_collector(&item_collector);
-
- // Test a good one first.
- TestParseInput good_input(
- R"(# Make a template with defaults set.
- template("my_templ") {
- source_set(target_name) {
- forward_variables_from(invoker, "*")
- }
- }
- set_defaults("my_templ") {
- default_value = 1
- }
-
- # Invoke the template with target(). This will fail to execute if the
- # defaults were not set properly, because "default_value" won't exist.
- target("my_templ", "foo") {
- print(default_value)
- })");
- ASSERT_FALSE(good_input.has_error());
- Err err;
- good_input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-}
diff --git a/chromium/tools/gn/functions_unittest.cc b/chromium/tools/gn/functions_unittest.cc
deleted file mode 100644
index 1ed509ae019..00000000000
--- a/chromium/tools/gn/functions_unittest.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/functions.h"
-
-#include <memory>
-#include <utility>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/test_with_scope.h"
-#include "tools/gn/value.h"
-
-TEST(Functions, Defined) {
- TestWithScope setup;
-
- FunctionCallNode function_call;
- Err err;
-
- // Test an undefined identifier.
- Token undefined_token(Location(), Token::IDENTIFIER, "undef");
- ListNode args_list_identifier_undefined;
- args_list_identifier_undefined.append_item(
- std::make_unique<IdentifierNode>(undefined_token));
- Value result = functions::RunDefined(setup.scope(), &function_call,
- &args_list_identifier_undefined, &err);
- ASSERT_EQ(Value::BOOLEAN, result.type());
- EXPECT_FALSE(result.boolean_value());
-
- // Define a value that's itself a scope value.
- const char kDef[] = "def"; // Defined variable name.
- setup.scope()->SetValue(
- kDef, Value(nullptr, std::make_unique<Scope>(setup.scope())), nullptr);
-
- // Test the defined identifier.
- Token defined_token(Location(), Token::IDENTIFIER, kDef);
- ListNode args_list_identifier_defined;
- args_list_identifier_defined.append_item(
- std::make_unique<IdentifierNode>(defined_token));
- result = functions::RunDefined(setup.scope(), &function_call,
- &args_list_identifier_defined, &err);
- ASSERT_EQ(Value::BOOLEAN, result.type());
- EXPECT_TRUE(result.boolean_value());
-
- // Should also work by passing an accessor node so you can do
- // "defined(def.foo)" to see if foo is defined on the def scope.
- std::unique_ptr<AccessorNode> undef_accessor =
- std::make_unique<AccessorNode>();
- undef_accessor->set_base(defined_token);
- undef_accessor->set_member(std::make_unique<IdentifierNode>(undefined_token));
- ListNode args_list_accessor_defined;
- args_list_accessor_defined.append_item(std::move(undef_accessor));
- result = functions::RunDefined(setup.scope(), &function_call,
- &args_list_accessor_defined, &err);
- ASSERT_EQ(Value::BOOLEAN, result.type());
- EXPECT_FALSE(result.boolean_value());
-}
-
-// Tests that an error is thrown when a {} is supplied to a function that
-// doesn't take one.
-TEST(Functions, FunctionsWithBlock) {
- TestWithScope setup;
- Err err;
-
- // No scope to print() is OK.
- TestParseInput print_no_scope("print(6)");
- EXPECT_FALSE(print_no_scope.has_error());
- Value result = print_no_scope.parsed()->Execute(setup.scope(), &err);
- EXPECT_FALSE(err.has_error());
-
- // Passing a scope should pass parsing (it doesn't know about what kind of
- // function it is) and then throw an error during execution.
- TestParseInput print_with_scope("print(foo) {}");
- EXPECT_FALSE(print_with_scope.has_error());
- result = print_with_scope.parsed()->Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
- err = Err();
-
- // defined() is a special function so test it separately.
- TestParseInput defined_no_scope("defined(foo)");
- EXPECT_FALSE(defined_no_scope.has_error());
- result = defined_no_scope.parsed()->Execute(setup.scope(), &err);
- EXPECT_FALSE(err.has_error());
-
- // A block to defined should fail.
- TestParseInput defined_with_scope("defined(foo) {}");
- EXPECT_FALSE(defined_with_scope.has_error());
- result = defined_with_scope.parsed()->Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
-}
-
-TEST(Functions, SplitList) {
- TestWithScope setup;
-
- TestParseInput input(
- // Empty input with varying result items.
- "out1 = split_list([], 1)\n"
- "out2 = split_list([], 3)\n"
- "print(\"empty = $out1 $out2\")\n"
-
- // One item input.
- "out3 = split_list([1], 1)\n"
- "out4 = split_list([1], 2)\n"
- "print(\"one = $out3 $out4\")\n"
-
- // Multiple items.
- "out5 = split_list([1, 2, 3, 4, 5, 6, 7, 8, 9], 2)\n"
- "print(\"many = $out5\")\n"
-
- // Rounding.
- "out6 = split_list([1, 2, 3, 4, 5, 6], 4)\n"
- "print(\"rounding = $out6\")\n"
- );
- ASSERT_FALSE(input.has_error());
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- EXPECT_EQ(
- "empty = [[]] [[], [], []]\n"
- "one = [[1]] [[1], []]\n"
- "many = [[1, 2, 3, 4, 5], [6, 7, 8, 9]]\n"
- "rounding = [[1, 2], [3, 4], [5], [6]]\n",
- setup.print_output());
-}
-
-TEST(Functions, DeclareArgs) {
- TestWithScope setup;
- Err err;
-
- // It is not legal to read the value of an argument declared in a
- // declare_args() from inside the call, but outside the call and in
- // a separate call should work.
-
- TestParseInput reading_from_same_call(R"(
- declare_args() {
- foo = true
- bar = foo
- })");
- reading_from_same_call.parsed()->Execute(setup.scope(), &err);
- ASSERT_TRUE(err.has_error());
-
- TestParseInput reading_from_outside_call(R"(
- declare_args() {
- foo = true
- }
-
- bar = foo
- assert(bar)
- )");
- err = Err();
- reading_from_outside_call.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error());
-
- TestParseInput reading_from_different_call(R"(
- declare_args() {
- foo = true
- }
-
- declare_args() {
- bar = foo
- }
-
- assert(bar)
- )");
- err = Err();
- TestWithScope setup2;
- reading_from_different_call.parsed()->Execute(setup2.scope(), &err);
- ASSERT_FALSE(err.has_error());
-}
diff --git a/chromium/tools/gn/gn_main.cc b/chromium/tools/gn/gn_main.cc
deleted file mode 100644
index 4d51158e7d1..00000000000
--- a/chromium/tools/gn/gn_main.cc
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <string>
-
-#include "base/at_exit.h"
-#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/sys_info.h"
-#include "base/task_scheduler/task_scheduler.h"
-#include "build/build_config.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/err.h"
-#include "tools/gn/location.h"
-#include "tools/gn/standard_out.h"
-#include "tools/gn/switches.h"
-
-// Only the GN-generated build makes this header for now.
-// TODO(brettw) consider adding this if we need it in GYP.
-#if defined(GN_BUILD)
-#include "tools/gn/last_commit_position.h"
-#else
-#define LAST_COMMIT_POSITION "UNKNOWN"
-#endif
-
-namespace {
-
-std::vector<std::string> GetArgs(const base::CommandLine& cmdline) {
- base::CommandLine::StringVector in_args = cmdline.GetArgs();
-#if defined(OS_WIN)
- std::vector<std::string> out_args;
- for (const auto& arg : in_args)
- out_args.push_back(base::WideToUTF8(arg));
- return out_args;
-#else
- return in_args;
-#endif
-}
-
-int GetThreadCount() {
- std::string thread_count =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kThreads);
-
- // See if an override was specified on the command line.
- int result;
- if (!thread_count.empty() && base::StringToInt(thread_count, &result) &&
- result >= 1) {
- return result;
- }
-
- // Base the default number of worker threads on number of cores in the
- // system. When building large projects, the speed can be limited by how fast
- // the main thread can dispatch work and connect the dependency graph. If
- // there are too many worker threads, the main thread can be starved and it
- // will run slower overall.
- //
- // One less worker thread than the number of physical CPUs seems to be a
- // good value, both theoretically and experimentally. But always use at
- // least some workers to prevent us from being too sensitive to I/O latency
- // on low-end systems.
- //
- // The minimum thread count is based on measuring the optimal threads for the
- // Chrome build on a several-year-old 4-core MacBook.
- // Almost all CPUs now are hyperthreaded.
- int num_cores = base::SysInfo::NumberOfProcessors() / 2;
- return std::max(num_cores - 1, 8);
-}
-
-void StartTaskScheduler() {
- constexpr base::TimeDelta kSuggestedReclaimTime =
- base::TimeDelta::FromSeconds(30);
-
- constexpr int kBackgroundMaxThreads = 1;
- constexpr int kBackgroundBlockingMaxThreads = 2;
- const int kForegroundMaxThreads =
- std::max(1, base::SysInfo::NumberOfProcessors());
- const int foreground_blocking_max_threads = GetThreadCount();
-
- base::TaskScheduler::Create("gn");
- base::TaskScheduler::GetInstance()->Start(
- {{kBackgroundMaxThreads, kSuggestedReclaimTime},
- {kBackgroundBlockingMaxThreads, kSuggestedReclaimTime},
- {kForegroundMaxThreads, kSuggestedReclaimTime},
- {foreground_blocking_max_threads, kSuggestedReclaimTime}});
-}
-
-} // namespace
-
-int main(int argc, char** argv) {
- base::AtExitManager at_exit;
-#if defined(OS_WIN)
- base::CommandLine::set_slash_is_not_a_switch();
-#endif
- base::CommandLine::Init(argc, argv);
-
- const base::CommandLine& cmdline = *base::CommandLine::ForCurrentProcess();
- std::vector<std::string> args = GetArgs(cmdline);
-
- std::string command;
- if (cmdline.HasSwitch("help") || cmdline.HasSwitch("h")) {
- // Make "-h" and "--help" default to help command.
- command = commands::kHelp;
- } else if (cmdline.HasSwitch(switches::kVersion)) {
- // Make "--version" print the version and exit.
- OutputString(std::string(LAST_COMMIT_POSITION) + "\n");
- exit(0);
- } else if (args.empty()) {
- // No command, print error and exit.
- Err(Location(), "No command specified.",
- "Most commonly you want \"gn gen <out_dir>\" to make a build dir.\n"
- "Or try \"gn help\" for more commands.").PrintToStdout();
- return 1;
- } else {
- command = args[0];
- args.erase(args.begin());
- }
-
- const commands::CommandInfoMap& command_map = commands::GetCommands();
- commands::CommandInfoMap::const_iterator found_command =
- command_map.find(command);
-
- int retval;
- if (found_command != command_map.end()) {
- base::MessageLoop message_loop;
- StartTaskScheduler();
- retval = found_command->second.runner(args);
- base::TaskScheduler::GetInstance()->Shutdown();
- } else {
- Err(Location(), "Command \"" + command + "\" unknown.").PrintToStdout();
- OutputString(
- "Available commands (type \"gn help <command>\" for more details):\n");
- for (const auto& cmd : commands::GetCommands())
- PrintShortHelp(cmd.second.help_short);
-
- retval = 1;
- }
-
- exit(retval); // Don't free memory, it can be really slow!
-}
diff --git a/chromium/tools/gn/group_target_generator.cc b/chromium/tools/gn/group_target_generator.cc
deleted file mode 100644
index e546865fd63..00000000000
--- a/chromium/tools/gn/group_target_generator.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/group_target_generator.h"
-
-#include "tools/gn/target.h"
-#include "tools/gn/variables.h"
-
-GroupTargetGenerator::GroupTargetGenerator(
- Target* target,
- Scope* scope,
- const FunctionCallNode* function_call,
- Err* err)
- : TargetGenerator(target, scope, function_call, err) {
-}
-
-GroupTargetGenerator::~GroupTargetGenerator() = default;
-
-void GroupTargetGenerator::DoRun() {
- target_->set_output_type(Target::GROUP);
- // Groups only have the default types filled in by the target generator
- // base class.
-}
diff --git a/chromium/tools/gn/group_target_generator.h b/chromium/tools/gn/group_target_generator.h
deleted file mode 100644
index 502f40b8db4..00000000000
--- a/chromium/tools/gn/group_target_generator.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_GROUP_TARGET_GENERATOR_H_
-#define TOOLS_GN_GROUP_TARGET_GENERATOR_H_
-
-#include "base/macros.h"
-#include "tools/gn/target_generator.h"
-
-// Populates a Target with the values for a group rule.
-class GroupTargetGenerator : public TargetGenerator {
- public:
- GroupTargetGenerator(Target* target,
- Scope* scope,
- const FunctionCallNode* function_call,
- Err* err);
- ~GroupTargetGenerator() override;
-
- protected:
- void DoRun() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GroupTargetGenerator);
-};
-
-#endif // TOOLS_GN_GROUP_TARGET_GENERATOR_H_
diff --git a/chromium/tools/gn/header_checker.cc b/chromium/tools/gn/header_checker.cc
deleted file mode 100644
index 57d2642665c..00000000000
--- a/chromium/tools/gn/header_checker.cc
+++ /dev/null
@@ -1,600 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/header_checker.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/containers/queue.h"
-#include "base/files/file_util.h"
-#include "base/strings/string_util.h"
-#include "base/task_scheduler/post_task.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/builder.h"
-#include "tools/gn/c_include_iterator.h"
-#include "tools/gn/config.h"
-#include "tools/gn/config_values_extractors.h"
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/source_file_type.h"
-#include "tools/gn/target.h"
-#include "tools/gn/trace.h"
-
-namespace {
-
-struct PublicGeneratedPair {
- PublicGeneratedPair() : is_public(false), is_generated(false) {}
- bool is_public;
- bool is_generated;
-};
-
-// This class makes InputFiles on the stack as it reads files to check. When
-// we throw an error, the Err indicates a locatin which has a pointer to
-// an InputFile that must persist as long as the Err does.
-//
-// To make this work, this function creates a clone of the InputFile managed
-// by the InputFileManager so the error can refer to something that
-// persists. This means that the current file contents will live as long as
-// the program, but this is OK since we're erroring out anyway.
-LocationRange CreatePersistentRange(const InputFile& input_file,
- const LocationRange& range) {
- InputFile* clone_input_file;
- std::vector<Token>* tokens; // Don't care about this.
- std::unique_ptr<ParseNode>* parse_root; // Don't care about this.
-
- g_scheduler->input_file_manager()->AddDynamicInput(
- input_file.name(), &clone_input_file, &tokens, &parse_root);
- clone_input_file->SetContents(input_file.contents());
-
- return LocationRange(Location(clone_input_file,
- range.begin().line_number(),
- range.begin().column_number(),
- -1 /* TODO(scottmg) */),
- Location(clone_input_file,
- range.end().line_number(),
- range.end().column_number(),
- -1 /* TODO(scottmg) */));
-}
-
-// Given a reverse dependency chain where the target chain[0]'s includes are
-// being used by chain[end] and not all deps are public, returns the string
-// describing the error.
-std::string GetDependencyChainPublicError(
- const HeaderChecker::Chain& chain) {
- std::string ret = "The target:\n " +
- chain[chain.size() - 1].target->label().GetUserVisibleName(false) +
- "\nis including a file from the target:\n " +
- chain[0].target->label().GetUserVisibleName(false) +
- "\n";
-
- // Invalid chains should always be 0 (no chain) or more than two
- // (intermediate private dependencies). 1 and 2 are impossible because a
- // target can always include headers from itself and its direct dependents.
- DCHECK(chain.size() != 1 && chain.size() != 2);
- if (chain.empty()) {
- ret += "There is no dependency chain between these targets.";
- } else {
- // Indirect dependency chain, print the chain.
- ret += "\nIt's usually best to depend directly on the destination target.\n"
- "In some cases, the destination target is considered a subcomponent\n"
- "of an intermediate target. In this case, the intermediate target\n"
- "should depend publicly on the destination to forward the ability\n"
- "to include headers.\n"
- "\n"
- "Dependency chain (there may also be others):\n";
-
- for (int i = static_cast<int>(chain.size()) - 1; i >= 0; i--) {
- ret.append(" " + chain[i].target->label().GetUserVisibleName(false));
- if (i != 0) {
- // Identify private dependencies so the user can see where in the
- // dependency chain things went bad. Don't list this for the first link
- // in the chain since direct dependencies are OK, and listing that as
- // "private" may make people feel like they need to fix it.
- if (i == static_cast<int>(chain.size()) - 1 || chain[i - 1].is_public)
- ret.append(" -->");
- else
- ret.append(" --[private]-->");
- }
- ret.append("\n");
- }
- }
- return ret;
-}
-
-// Returns true if the two targets have the same label not counting the
-// toolchain.
-bool TargetLabelsMatchExceptToolchain(const Target* a, const Target* b) {
- return a->label().dir() == b->label().dir() &&
- a->label().name() == b->label().name();
-}
-
-// Returns true if the target |annotation_on| includes a friend annotation
-// that allows |is_marked_friend| as a friend.
-bool FriendMatches(const Target* annotation_on,
- const Target* is_marked_friend) {
- return LabelPattern::VectorMatches(annotation_on->friends(),
- is_marked_friend->label());
-}
-
-} // namespace
-
-HeaderChecker::HeaderChecker(const BuildSettings* build_settings,
- const std::vector<const Target*>& targets)
- : build_settings_(build_settings), task_count_cv_(&lock_) {
- for (auto* target : targets)
- AddTargetToFileMap(target, &file_map_);
-}
-
-HeaderChecker::~HeaderChecker() = default;
-
-bool HeaderChecker::Run(const std::vector<const Target*>& to_check,
- bool force_check,
- std::vector<Err>* errors) {
- FileMap files_to_check;
- for (auto* check : to_check) {
- // This function will get called with all target types, but check only
- // applies to binary targets.
- if (check->IsBinary())
- AddTargetToFileMap(check, &files_to_check);
- }
- RunCheckOverFiles(files_to_check, force_check);
-
- if (errors_.empty())
- return true;
- *errors = errors_;
- return false;
-}
-
-void HeaderChecker::RunCheckOverFiles(const FileMap& files, bool force_check) {
- for (const auto& file : files) {
- // Only check C-like source files (RC files also have includes).
- SourceFileType type = GetSourceFileType(file.first);
- if (type != SOURCE_CPP && type != SOURCE_H && type != SOURCE_C &&
- type != SOURCE_M && type != SOURCE_MM && type != SOURCE_RC)
- continue;
-
- // If any target marks it as generated, don't check it. We have to check
- // file_map_, which includes all known files; files only includes those
- // being checked.
- bool is_generated = false;
- for (const auto& vect_i : file_map_[file.first])
- is_generated |= vect_i.is_generated;
- if (is_generated)
- continue;
-
- for (const auto& vect_i : file.second) {
- if (vect_i.target->check_includes()) {
- task_count_.Increment();
- base::PostTaskWithTraits(FROM_HERE, {base::MayBlock()},
- base::BindOnce(&HeaderChecker::DoWork, this,
- vect_i.target, file.first));
- }
- }
- }
-
- // Wait for all tasks posted by this method to complete.
- base::AutoLock auto_lock(lock_);
- while (!task_count_.IsZero())
- task_count_cv_.Wait();
-}
-
-void HeaderChecker::DoWork(const Target* target, const SourceFile& file) {
- Err err;
- if (!CheckFile(target, file, &err)) {
- base::AutoLock lock(lock_);
- errors_.push_back(err);
- }
-
- if (!task_count_.Decrement()) {
- // Signal |task_count_cv_| when |task_count_| becomes zero.
- base::AutoLock auto_lock(lock_);
- task_count_cv_.Signal();
- }
-}
-
-// static
-void HeaderChecker::AddTargetToFileMap(const Target* target, FileMap* dest) {
- // Files in the sources have this public bit by default.
- bool default_public = target->all_headers_public();
-
- std::map<SourceFile, PublicGeneratedPair> files_to_public;
-
- // First collect the normal files, they get the default visibility. If you
- // depend on the compiled target, it should be enough to be able to include
- // the header.
- for (const auto& source : target->sources()) {
- files_to_public[source].is_public = default_public;
- }
-
- // Add in the public files, forcing them to public. This may overwrite some
- // entries, and it may add new ones.
- if (default_public) // List only used when default is not public.
- DCHECK(target->public_headers().empty());
- for (const auto& source : target->public_headers()) {
- files_to_public[source].is_public = true;
- }
-
- // Add in outputs from actions. These are treated as public (since if other
- // targets can't use them, then there wouldn't be any point in outputting).
- std::vector<SourceFile> outputs;
- target->action_values().GetOutputsAsSourceFiles(target, &outputs);
- for (const auto& output : outputs) {
- PublicGeneratedPair* pair = &files_to_public[output];
- pair->is_public = true;
- pair->is_generated = true;
- }
-
- // Add the merged list to the master list of all files.
- for (const auto& cur : files_to_public) {
- (*dest)[cur.first].push_back(TargetInfo(
- target, cur.second.is_public, cur.second.is_generated));
- }
-}
-
-bool HeaderChecker::IsFileInOuputDir(const SourceFile& file) const {
- const std::string& build_dir = build_settings_->build_dir().value();
- return file.value().compare(0, build_dir.size(), build_dir) == 0;
-}
-
-SourceFile HeaderChecker::SourceFileForInclude(
- const base::StringPiece& relative_file_path,
- const std::vector<SourceDir>& include_dirs,
- const InputFile& source_file,
- const LocationRange& range,
- Err* err) const {
- using base::FilePath;
-
- Value relative_file_value(nullptr, relative_file_path.as_string());
- auto it = std::find_if(
- include_dirs.begin(), include_dirs.end(),
- [relative_file_value, err, this](const SourceDir& dir) -> bool {
- SourceFile include_file =
- dir.ResolveRelativeFile(relative_file_value, err);
- return file_map_.find(include_file) != file_map_.end();
- });
-
- if (it != include_dirs.end())
- return it->ResolveRelativeFile(relative_file_value, err);
-
- return SourceFile();
-}
-
-bool HeaderChecker::CheckFile(const Target* from_target,
- const SourceFile& file,
- Err* err) const {
- ScopedTrace trace(TraceItem::TRACE_CHECK_HEADER, file.value());
-
- // Sometimes you have generated source files included as sources in another
- // target. These won't exist at checking time. Since we require all generated
- // files to be somewhere in the output tree, we can just check the name to
- // see if they should be skipped.
- if (IsFileInOuputDir(file))
- return true;
-
- base::FilePath path = build_settings_->GetFullPath(file);
- std::string contents;
- if (!base::ReadFileToString(path, &contents)) {
- *err = Err(from_target->defined_from(), "Source file not found.",
- "The target:\n " + from_target->label().GetUserVisibleName(false) +
- "\nhas a source file:\n " + file.value() +
- "\nwhich was not found.");
- return false;
- }
-
- InputFile input_file(file);
- input_file.SetContents(contents);
-
- std::vector<SourceDir> include_dirs;
- include_dirs.push_back(file.GetDir());
- for (ConfigValuesIterator iter(from_target); !iter.done(); iter.Next()) {
- const std::vector<SourceDir>& target_include_dirs =
- iter.cur().include_dirs();
- include_dirs.insert(include_dirs.end(), target_include_dirs.begin(),
- target_include_dirs.end());
- }
-
- CIncludeIterator iter(&input_file);
- base::StringPiece current_include;
- LocationRange range;
- while (iter.GetNextIncludeString(&current_include, &range)) {
- SourceFile include = SourceFileForInclude(current_include, include_dirs,
- input_file, range, err);
- if (!include.is_null()) {
- if (!CheckInclude(from_target, input_file, include, range, err))
- return false;
- }
- }
-
- return true;
-}
-
-// If the file exists:
-// - The header must be in the public section of a target, or it must
-// be in the sources with no public list (everything is implicitly public).
-// - The dependency path to the included target must follow only public_deps.
-// - If there are multiple targets with the header in it, only one need be
-// valid for the check to pass.
-bool HeaderChecker::CheckInclude(const Target* from_target,
- const InputFile& source_file,
- const SourceFile& include_file,
- const LocationRange& range,
- Err* err) const {
- // Assume if the file isn't declared in our sources that we don't need to
- // check it. It would be nice if we could give an error if this happens, but
- // our include finder is too primitive and returns all includes, even if
- // they're in a #if not executed in the current build. In that case, it's
- // not unusual for the buildfiles to not specify that header at all.
- FileMap::const_iterator found = file_map_.find(include_file);
- if (found == file_map_.end())
- return true;
-
- const TargetVector& targets = found->second;
- Chain chain; // Prevent reallocating in the loop.
-
- // If the file is unknown in the current toolchain (rather than being private
- // or in a target not visible to the current target), ignore it. This is a
- // bit of a hack to account for the fact that the include finder doesn't
- // understand the preprocessor.
- //
- // When not cross-compiling, if a platform specific header is conditionally
- // included in the build, and preprocessor conditions around #includes of
- // that match the build conditions, everything will be OK because the file
- // won't be known to GN even though the #include finder identified the file.
- //
- // Cross-compiling breaks this. When compiling Android on Linux, for example,
- // we might see both Linux and Android definitions of a target and know
- // about the union of all headers in the build. Since the #include finder
- // ignores preprocessor, we will find the Linux headers in the Android
- // build and note that a dependency from the Android target to the Linux
- // one is missing (these might even be the same target in different
- // toolchains!).
- bool present_in_current_toolchain = false;
- for (const auto& target : targets) {
- if (from_target->label().ToolchainsEqual(target.target->label())) {
- present_in_current_toolchain = true;
- break;
- }
- }
- if (!present_in_current_toolchain)
- return true;
-
- // For all targets containing this file, we require that at least one be
- // a direct or public dependency of the current target, and either (1) the
- // header is public within the target, or (2) there is a friend definition
- // whitelisting the includor.
- //
- // If there is more than one target containing this header, we may encounter
- // some error cases before finding a good one. This error stores the previous
- // one encountered, which we may or may not throw away.
- Err last_error;
-
- bool found_dependency = false;
- for (const auto& target : targets) {
- // We always allow source files in a target to include headers also in that
- // target.
- const Target* to_target = target.target;
- if (to_target == from_target)
- return true;
-
- bool is_permitted_chain = false;
- if (IsDependencyOf(to_target, from_target, &chain, &is_permitted_chain)) {
- DCHECK(chain.size() >= 2);
- DCHECK(chain[0].target == to_target);
- DCHECK(chain[chain.size() - 1].target == from_target);
-
- found_dependency = true;
-
- bool effectively_public =
- target.is_public || FriendMatches(to_target, from_target);
-
- if (effectively_public && is_permitted_chain) {
- // This one is OK, we're done.
- last_error = Err();
- break;
- }
-
- // Diagnose the error.
- if (!effectively_public) {
- // Danger: must call CreatePersistentRange to put in Err.
- last_error = Err(CreatePersistentRange(source_file, range),
- "Including a private header.",
- "This file is private to the target " +
- target.target->label().GetUserVisibleName(false));
- } else if (!is_permitted_chain) {
- last_error = Err(
- CreatePersistentRange(source_file, range),
- "Can't include this header from here.",
- GetDependencyChainPublicError(chain));
- } else {
- NOTREACHED();
- }
- } else if (
- to_target->allow_circular_includes_from().find(from_target->label()) !=
- to_target->allow_circular_includes_from().end()) {
- // Not a dependency, but this include is whitelisted from the destination.
- found_dependency = true;
- last_error = Err();
- break;
- }
- }
-
- if (!found_dependency) {
- DCHECK(!last_error.has_error());
- *err = MakeUnreachableError(source_file, range, from_target, targets);
- return false;
- }
- if (last_error.has_error()) {
- // Found at least one dependency chain above, but it had an error.
- *err = last_error;
- return false;
- }
-
- // One thing we didn't check for is targets that expose their dependents
- // headers in their own public headers.
- //
- // Say we have A -> B -> C. If C has public_configs, everybody getting headers
- // from C should get the configs also or things could be out-of-sync. Above,
- // we check for A including C's headers directly, but A could also include a
- // header from B that in turn includes a header from C.
- //
- // There are two ways to solve this:
- // - If a public header in B includes C, force B to publicly depend on C.
- // This is possible to check, but might be super annoying because most
- // targets (especially large leaf-node targets) don't declare
- // public/private headers and you'll get lots of false positives.
- //
- // - Save the includes found in each file and actually compute the graph of
- // includes to detect when A implicitly includes C's header. This will not
- // have the annoying false positive problem, but is complex to write.
-
- return true;
-}
-
-bool HeaderChecker::IsDependencyOf(const Target* search_for,
- const Target* search_from,
- Chain* chain,
- bool* is_permitted) const {
- if (search_for == search_from) {
- // A target is always visible from itself.
- *is_permitted = true;
- return false;
- }
-
- // Find the shortest public dependency chain.
- if (IsDependencyOf(search_for, search_from, true, chain)) {
- *is_permitted = true;
- return true;
- }
-
- // If not, try to find any dependency chain at all.
- if (IsDependencyOf(search_for, search_from, false, chain)) {
- *is_permitted = false;
- return true;
- }
-
- *is_permitted = false;
- return false;
-}
-
-bool HeaderChecker::IsDependencyOf(const Target* search_for,
- const Target* search_from,
- bool require_permitted,
- Chain* chain) const {
- // This method conducts a breadth-first search through the dependency graph
- // to find a shortest chain from search_from to search_for.
- //
- // work_queue maintains a queue of targets which need to be considered as
- // part of this chain, in the order they were first traversed.
- //
- // Each time a new transitive dependency of search_from is discovered for
- // the first time, it is added to work_queue and a "breadcrumb" is added,
- // indicating which target it was reached from when first discovered.
- //
- // Once this search finds search_for, the breadcrumbs are used to reconstruct
- // a shortest dependency chain (in reverse order) from search_from to
- // search_for.
-
- std::map<const Target*, ChainLink> breadcrumbs;
- base::queue<ChainLink> work_queue;
- work_queue.push(ChainLink(search_from, true));
-
- bool first_time = true;
- while (!work_queue.empty()) {
- ChainLink cur_link = work_queue.front();
- const Target* target = cur_link.target;
- work_queue.pop();
-
- if (target == search_for) {
- // Found it! Reconstruct the chain.
- chain->clear();
- while (target != search_from) {
- chain->push_back(cur_link);
- cur_link = breadcrumbs[target];
- target = cur_link.target;
- }
- chain->push_back(ChainLink(search_from, true));
- return true;
- }
-
- // Always consider public dependencies as possibilities.
- for (const auto& dep : target->public_deps()) {
- if (breadcrumbs.insert(std::make_pair(dep.ptr, cur_link)).second)
- work_queue.push(ChainLink(dep.ptr, true));
- }
-
- if (first_time || !require_permitted) {
- // Consider all dependencies since all target paths are allowed, so add
- // in private ones. Also do this the first time through the loop, since
- // a target can include headers from its direct deps regardless of
- // public/private-ness.
- first_time = false;
- for (const auto& dep : target->private_deps()) {
- if (breadcrumbs.insert(std::make_pair(dep.ptr, cur_link)).second)
- work_queue.push(ChainLink(dep.ptr, false));
- }
- }
- }
-
- return false;
-}
-
-Err HeaderChecker::MakeUnreachableError(
- const InputFile& source_file,
- const LocationRange& range,
- const Target* from_target,
- const TargetVector& targets) {
- // Normally the toolchains will all match, but when cross-compiling, we can
- // get targets with more than one toolchain in the list of possibilities.
- std::vector<const Target*> targets_with_matching_toolchains;
- std::vector<const Target*> targets_with_other_toolchains;
- for (const TargetInfo& candidate : targets) {
- if (candidate.target->toolchain() == from_target->toolchain())
- targets_with_matching_toolchains.push_back(candidate.target);
- else
- targets_with_other_toolchains.push_back(candidate.target);
- }
-
- // It's common when cross-compiling to have a target with the same file in
- // more than one toolchain. We could output all of them, but this is
- // generally confusing to people (most end-users won't understand toolchains
- // well).
- //
- // So delete any candidates in other toolchains that also appear in the same
- // toolchain as the from_target.
- for (int other_index = 0;
- other_index < static_cast<int>(targets_with_other_toolchains.size());
- other_index++) {
- for (const Target* cur_matching : targets_with_matching_toolchains) {
- if (TargetLabelsMatchExceptToolchain(
- cur_matching, targets_with_other_toolchains[other_index])) {
- // Found a duplicate, erase it.
- targets_with_other_toolchains.erase(
- targets_with_other_toolchains.begin() + other_index);
- other_index--;
- break;
- }
- }
- }
-
- // Only display toolchains on labels if they don't all match.
- bool include_toolchain = !targets_with_other_toolchains.empty();
-
- std::string msg = "It is not in any dependency of\n " +
- from_target->label().GetUserVisibleName(include_toolchain);
- msg += "\nThe include file is in the target(s):\n";
- for (auto* target : targets_with_matching_toolchains)
- msg += " " + target->label().GetUserVisibleName(include_toolchain) + "\n";
- for (auto* target : targets_with_other_toolchains)
- msg += " " + target->label().GetUserVisibleName(include_toolchain) + "\n";
- if (targets_with_other_toolchains.size() +
- targets_with_matching_toolchains.size() > 1)
- msg += "at least one of ";
- msg += "which should somehow be reachable.";
-
- // Danger: must call CreatePersistentRange to put in Err.
- return Err(CreatePersistentRange(source_file, range),
- "Include not allowed.", msg);
-}
diff --git a/chromium/tools/gn/header_checker.h b/chromium/tools/gn/header_checker.h
deleted file mode 100644
index b1d0f79fe43..00000000000
--- a/chromium/tools/gn/header_checker.h
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_HEADER_CHECKER_H_
-#define TOOLS_GN_HEADER_CHECKER_H_
-
-#include <map>
-#include <vector>
-
-#include "base/atomic_ref_count.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/strings/string_piece.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "tools/gn/err.h"
-#include "tools/gn/source_dir.h"
-
-class BuildSettings;
-class InputFile;
-class LocationRange;
-class SourceFile;
-class Target;
-
-namespace base {
-class FilePath;
-}
-
-class HeaderChecker : public base::RefCountedThreadSafe<HeaderChecker> {
- public:
- // Represents a dependency chain.
- struct ChainLink {
- ChainLink() : target(nullptr), is_public(false) {}
- ChainLink(const Target* t, bool p) : target(t), is_public(p) {}
-
- const Target* target;
-
- // True when the dependency on this target is public.
- bool is_public;
-
- // Used for testing.
- bool operator==(const ChainLink& other) const {
- return target == other.target && is_public == other.is_public;
- }
- };
- typedef std::vector<ChainLink> Chain;
-
- HeaderChecker(const BuildSettings* build_settings,
- const std::vector<const Target*>& targets);
-
- // Runs the check. The targets in to_check will be checked.
- //
- // This assumes that the current thread already has a message loop. On
- // error, fills the given vector with the errors and returns false. Returns
- // true on success.
- //
- // force_check, if true, will override targets opting out of header checking
- // with "check_includes = false" and will check them anyway.
- bool Run(const std::vector<const Target*>& to_check,
- bool force_check,
- std::vector<Err>* errors);
-
- private:
- friend class base::RefCountedThreadSafe<HeaderChecker>;
- FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, IsDependencyOf);
- FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, CheckInclude);
- FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, PublicFirst);
- FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, CheckIncludeAllowCircular);
- FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, SourceFileForInclude);
- FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest,
- SourceFileForInclude_FileNotFound);
- FRIEND_TEST_ALL_PREFIXES(HeaderCheckerTest, Friend);
-
- ~HeaderChecker();
-
- struct TargetInfo {
- TargetInfo() : target(nullptr), is_public(false), is_generated(false) {}
- TargetInfo(const Target* t, bool is_pub, bool is_gen)
- : target(t),
- is_public(is_pub),
- is_generated(is_gen) {
- }
-
- const Target* target;
-
- // True if the file is public in the given target.
- bool is_public;
-
- // True if this file is generated and won't actually exist on disk.
- bool is_generated;
- };
-
- typedef std::vector<TargetInfo> TargetVector;
- typedef std::map<SourceFile, TargetVector> FileMap;
- typedef base::RepeatingCallback<bool(const base::FilePath& path)>
- PathExistsCallback;
-
- // Backend for Run() that takes the list of files to check. The errors_ list
- // will be populate on failure.
- void RunCheckOverFiles(const FileMap& flies, bool force_check);
-
- void DoWork(const Target* target, const SourceFile& file);
-
- // Adds the sources and public files from the given target to the given map.
- static void AddTargetToFileMap(const Target* target, FileMap* dest);
-
- // Returns true if the given file is in the output directory.
- bool IsFileInOuputDir(const SourceFile& file) const;
-
- // Resolves the contents of an include to a SourceFile.
- SourceFile SourceFileForInclude(const base::StringPiece& relative_file_path,
- const std::vector<SourceDir>& include_dirs,
- const InputFile& source_file,
- const LocationRange& range,
- Err* err) const;
-
- // from_target is the target the file was defined from. It will be used in
- // error messages.
- bool CheckFile(const Target* from_target,
- const SourceFile& file,
- Err* err) const;
-
- // Checks that the given file in the given target can include the given
- // include file. If disallowed, returns false and sets the error. The
- // range indicates the location of the include in the file for error
- // reporting.
- bool CheckInclude(const Target* from_target,
- const InputFile& source_file,
- const SourceFile& include_file,
- const LocationRange& range,
- Err* err) const;
-
- // Returns true if the given search_for target is a dependency of
- // search_from.
- //
- // If found, the vector given in "chain" will be filled with the reverse
- // dependency chain from the dest target (chain[0] = search_for) to the src
- // target (chain[chain.size() - 1] = search_from).
- //
- // Chains with permitted dependencies will be considered first. If a
- // permitted match is found, *is_permitted will be set to true. A chain with
- // indirect, non-public dependencies will only be considered if there are no
- // public or direct chains. In this case, *is_permitted will be false.
- //
- // A permitted dependency is a sequence of public dependencies. The first
- // one may be private, since a direct dependency always allows headers to be
- // included.
- bool IsDependencyOf(const Target* search_for,
- const Target* search_from,
- Chain* chain,
- bool* is_permitted) const;
-
- // For internal use by the previous override of IsDependencyOf. If
- // require_public is true, only public dependency chains are searched.
- bool IsDependencyOf(const Target* search_for,
- const Target* search_from,
- bool require_permitted,
- Chain* chain) const;
-
- // Makes a very descriptive error message for when an include is disallowed
- // from a given from_target, with a missing dependency to one of the given
- // targets.
- static Err MakeUnreachableError(const InputFile& source_file,
- const LocationRange& range,
- const Target* from_target,
- const TargetVector& targets);
-
- // Non-locked variables ------------------------------------------------------
- //
- // These are initialized during construction (which happens on one thread)
- // and are not modified after, so any thread can read these without locking.
-
- const BuildSettings* build_settings_;
-
- // Maps source files to targets it appears in (usually just one target).
- FileMap file_map_;
-
- // Number of tasks posted by RunCheckOverFiles() that haven't completed their
- // execution.
- base::AtomicRefCount task_count_;
-
- // Locked variables ----------------------------------------------------------
- //
- // These are mutable during runtime and require locking.
-
- base::Lock lock_;
-
- std::vector<Err> errors_;
-
- // Signaled when |task_count_| becomes zero.
- base::ConditionVariable task_count_cv_;
-
- DISALLOW_COPY_AND_ASSIGN(HeaderChecker);
-};
-
-#endif // TOOLS_GN_HEADER_CHECKER_H_
diff --git a/chromium/tools/gn/header_checker_unittest.cc b/chromium/tools/gn/header_checker_unittest.cc
deleted file mode 100644
index dcfa7bbb6fe..00000000000
--- a/chromium/tools/gn/header_checker_unittest.cc
+++ /dev/null
@@ -1,382 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <ostream>
-#include <vector>
-
-#include "base/bind.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/config.h"
-#include "tools/gn/header_checker.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scheduler.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-class HeaderCheckerTest : public TestWithScheduler {
- public:
- HeaderCheckerTest()
- : a_(setup_.settings(), Label(SourceDir("//a/"), "a")),
- b_(setup_.settings(), Label(SourceDir("//b/"), "b")),
- c_(setup_.settings(), Label(SourceDir("//c/"), "c")),
- d_(setup_.settings(), Label(SourceDir("//d/"), "d")) {
- a_.set_output_type(Target::SOURCE_SET);
- b_.set_output_type(Target::SOURCE_SET);
- c_.set_output_type(Target::SOURCE_SET);
- d_.set_output_type(Target::SOURCE_SET);
-
- Err err;
- a_.SetToolchain(setup_.toolchain(), &err);
- b_.SetToolchain(setup_.toolchain(), &err);
- c_.SetToolchain(setup_.toolchain(), &err);
- d_.SetToolchain(setup_.toolchain(), &err);
-
- a_.public_deps().push_back(LabelTargetPair(&b_));
- b_.public_deps().push_back(LabelTargetPair(&c_));
-
- // Start with all public visibility.
- a_.visibility().SetPublic();
- b_.visibility().SetPublic();
- c_.visibility().SetPublic();
- d_.visibility().SetPublic();
-
- d_.OnResolved(&err);
- c_.OnResolved(&err);
- b_.OnResolved(&err);
- a_.OnResolved(&err);
-
- targets_.push_back(&a_);
- targets_.push_back(&b_);
- targets_.push_back(&c_);
- targets_.push_back(&d_);
- }
-
- protected:
- TestWithScope setup_;
-
- // Some headers that are automatically set up with a public dependency chain.
- // a -> b -> c. D is unconnected.
- Target a_;
- Target b_;
- Target c_;
- Target d_;
-
- std::vector<const Target*> targets_;
-};
-
-} // namespace
-
-void PrintTo(const SourceFile& source_file, ::std::ostream* os) {
- *os << source_file.value();
-}
-
-TEST_F(HeaderCheckerTest, IsDependencyOf) {
- scoped_refptr<HeaderChecker> checker(
- new HeaderChecker(setup_.build_settings(), targets_));
-
- // Add a target P ("private") that privately depends on C, and hook up the
- // chain so that A -> P -> C. A will depend on C via two different paths.
- Err err;
- Target p(setup_.settings(), Label(SourceDir("//p/"), "p"));
- p.set_output_type(Target::SOURCE_SET);
- p.SetToolchain(setup_.toolchain(), &err);
- EXPECT_FALSE(err.has_error());
- p.private_deps().push_back(LabelTargetPair(&c_));
- p.visibility().SetPublic();
- p.OnResolved(&err);
-
- a_.public_deps().push_back(LabelTargetPair(&p));
-
- // A does not depend on itself.
- bool is_permitted = false;
- HeaderChecker::Chain chain;
- EXPECT_FALSE(checker->IsDependencyOf(&a_, &a_, &chain, &is_permitted));
-
- // A depends publicly on B.
- chain.clear();
- is_permitted = false;
- EXPECT_TRUE(checker->IsDependencyOf(&b_, &a_, &chain, &is_permitted));
- ASSERT_EQ(2u, chain.size());
- EXPECT_EQ(HeaderChecker::ChainLink(&b_, true), chain[0]);
- EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[1]);
- EXPECT_TRUE(is_permitted);
-
- // A indirectly depends on C. The "public" dependency path through B should
- // be identified.
- chain.clear();
- is_permitted = false;
- EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_permitted));
- ASSERT_EQ(3u, chain.size());
- EXPECT_EQ(HeaderChecker::ChainLink(&c_, true), chain[0]);
- EXPECT_EQ(HeaderChecker::ChainLink(&b_, true), chain[1]);
- EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[2]);
- EXPECT_TRUE(is_permitted);
-
- // C does not depend on A.
- chain.clear();
- is_permitted = false;
- EXPECT_FALSE(checker->IsDependencyOf(&a_, &c_, &chain, &is_permitted));
- EXPECT_TRUE(chain.empty());
- EXPECT_FALSE(is_permitted);
-
- // Remove the B -> C public dependency, leaving P's private dep on C the only
- // path from A to C. This should now be found.
- chain.clear();
- EXPECT_EQ(&c_, b_.public_deps()[0].ptr); // Validate it's the right one.
- b_.public_deps().erase(b_.public_deps().begin());
- EXPECT_TRUE(checker->IsDependencyOf(&c_, &a_, &chain, &is_permitted));
- EXPECT_EQ(3u, chain.size());
- EXPECT_EQ(HeaderChecker::ChainLink(&c_, false), chain[0]);
- EXPECT_EQ(HeaderChecker::ChainLink(&p, true), chain[1]);
- EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[2]);
- EXPECT_FALSE(is_permitted);
-
- // P privately depends on C. That dependency should be OK since it's only
- // one hop.
- chain.clear();
- is_permitted = false;
- EXPECT_TRUE(checker->IsDependencyOf(&c_, &p, &chain, &is_permitted));
- ASSERT_EQ(2u, chain.size());
- EXPECT_EQ(HeaderChecker::ChainLink(&c_, false), chain[0]);
- EXPECT_EQ(HeaderChecker::ChainLink(&p, true), chain[1]);
- EXPECT_TRUE(is_permitted);
-}
-
-TEST_F(HeaderCheckerTest, CheckInclude) {
- InputFile input_file(SourceFile("//some_file.cc"));
- input_file.SetContents(std::string());
- LocationRange range; // Dummy value.
-
- // Add a disconnected target d with a header to check that you have to have
- // to depend on a target listing a header.
- SourceFile d_header("//d_header.h");
- d_.sources().push_back(SourceFile(d_header));
-
- // Add a header on B and say everything in B is public.
- SourceFile b_public("//b_public.h");
- b_.sources().push_back(b_public);
- c_.set_all_headers_public(true);
-
- // Add a public and private header on C.
- SourceFile c_public("//c_public.h");
- SourceFile c_private("//c_private.h");
- c_.sources().push_back(c_private);
- c_.public_headers().push_back(c_public);
- c_.set_all_headers_public(false);
-
- // Create another toolchain.
- Settings other_settings(setup_.build_settings(), "other/");
- Toolchain other_toolchain(&other_settings,
- Label(SourceDir("//toolchain/"), "other"));
- TestWithScope::SetupToolchain(&other_toolchain);
- other_settings.set_toolchain_label(other_toolchain.label());
- other_settings.set_default_toolchain_label(setup_.toolchain()->label());
-
- // Add a target in the other toolchain with a header in it that is not
- // connected to any targets in the main toolchain.
- Target otc(&other_settings,
- Label(SourceDir("//p/"), "otc", other_toolchain.label().dir(),
- other_toolchain.label().name()));
- otc.set_output_type(Target::SOURCE_SET);
- Err err;
- EXPECT_TRUE(otc.SetToolchain(&other_toolchain, &err));
- otc.visibility().SetPublic();
- targets_.push_back(&otc);
-
- SourceFile otc_header("//otc_header.h");
- otc.sources().push_back(otc_header);
- EXPECT_TRUE(otc.OnResolved(&err));
-
- scoped_refptr<HeaderChecker> checker(
- new HeaderChecker(setup_.build_settings(), targets_));
-
- // A file in target A can't include a header from D because A has no
- // dependency on D.
- EXPECT_FALSE(checker->CheckInclude(&a_, input_file, d_header, range, &err));
- EXPECT_TRUE(err.has_error());
-
- // A can include the public header in B.
- err = Err();
- EXPECT_TRUE(checker->CheckInclude(&a_, input_file, b_public, range, &err));
- EXPECT_FALSE(err.has_error());
-
- // Check A depending on the public and private headers in C.
- err = Err();
- EXPECT_TRUE(checker->CheckInclude(&a_, input_file, c_public, range, &err));
- EXPECT_FALSE(err.has_error());
- EXPECT_FALSE(checker->CheckInclude(&a_, input_file, c_private, range, &err));
- EXPECT_TRUE(err.has_error());
-
- // A can depend on a random file unknown to the build.
- err = Err();
- EXPECT_TRUE(checker->CheckInclude(&a_, input_file, SourceFile("//random.h"),
- range, &err));
- EXPECT_FALSE(err.has_error());
-
- // A can depend on a file present only in another toolchain even with no
- // dependency path.
- err = Err();
- EXPECT_TRUE(checker->CheckInclude(&a_, input_file, otc_header, range, &err));
- EXPECT_FALSE(err.has_error());
-}
-
-// A public chain of dependencies should always be identified first, even if
-// it is longer than a private one.
-TEST_F(HeaderCheckerTest, PublicFirst) {
- // Now make a A -> Z -> D private dependency chain (one shorter than the
- // public one to get to D).
- Target z(setup_.settings(), Label(SourceDir("//a/"), "a"));
- z.set_output_type(Target::SOURCE_SET);
- Err err;
- EXPECT_TRUE(z.SetToolchain(setup_.toolchain(), &err));
- z.private_deps().push_back(LabelTargetPair(&d_));
- EXPECT_TRUE(z.OnResolved(&err));
- targets_.push_back(&z);
-
- a_.private_deps().push_back(LabelTargetPair(&z));
-
- // Check that D can be found from A, but since it's private, it will be
- // marked as not permitted.
- bool is_permitted = false;
- HeaderChecker::Chain chain;
- scoped_refptr<HeaderChecker> checker(
- new HeaderChecker(setup_.build_settings(), targets_));
- EXPECT_TRUE(checker->IsDependencyOf(&d_, &a_, &chain, &is_permitted));
-
- EXPECT_FALSE(is_permitted);
- ASSERT_EQ(3u, chain.size());
- EXPECT_EQ(HeaderChecker::ChainLink(&d_, false), chain[0]);
- EXPECT_EQ(HeaderChecker::ChainLink(&z, false), chain[1]);
- EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[2]);
-
- // Hook up D to the existing public A -> B -> C chain to make a long one, and
- // search for D again.
- c_.public_deps().push_back(LabelTargetPair(&d_));
- checker = new HeaderChecker(setup_.build_settings(), targets_);
- chain.clear();
- EXPECT_TRUE(checker->IsDependencyOf(&d_, &a_, &chain, &is_permitted));
-
- // This should have found the long public one.
- EXPECT_TRUE(is_permitted);
- ASSERT_EQ(4u, chain.size());
- EXPECT_EQ(HeaderChecker::ChainLink(&d_, true), chain[0]);
- EXPECT_EQ(HeaderChecker::ChainLink(&c_, true), chain[1]);
- EXPECT_EQ(HeaderChecker::ChainLink(&b_, true), chain[2]);
- EXPECT_EQ(HeaderChecker::ChainLink(&a_, true), chain[3]);
-}
-
-// Checks that the allow_circular_includes_from list works.
-TEST_F(HeaderCheckerTest, CheckIncludeAllowCircular) {
- InputFile input_file(SourceFile("//some_file.cc"));
- input_file.SetContents(std::string());
- LocationRange range; // Dummy value.
-
- // Add an include file to A.
- SourceFile a_public("//a_public.h");
- a_.sources().push_back(a_public);
-
- scoped_refptr<HeaderChecker> checker(
- new HeaderChecker(setup_.build_settings(), targets_));
-
- // A depends on B. So B normally can't include headers from A.
- Err err;
- EXPECT_FALSE(checker->CheckInclude(&b_, input_file, a_public, range, &err));
- EXPECT_TRUE(err.has_error());
-
- // Add an allow_circular_includes_from on A that lists B.
- a_.allow_circular_includes_from().insert(b_.label());
-
- // Now the include from B to A should be allowed.
- err = Err();
- EXPECT_TRUE(checker->CheckInclude(&b_, input_file, a_public, range, &err));
- EXPECT_FALSE(err.has_error());
-}
-
-TEST_F(HeaderCheckerTest, SourceFileForInclude) {
- using base::FilePath;
- const std::vector<SourceDir> kIncludeDirs = {
- SourceDir("/c/custom_include/"), SourceDir("//"), SourceDir("//subdir")};
- a_.sources().push_back(SourceFile("//lib/header1.h"));
- b_.sources().push_back(SourceFile("/c/custom_include/header2.h"));
-
- InputFile dummy_input_file(SourceFile("//some_file.cc"));
- dummy_input_file.SetContents(std::string());
- LocationRange dummy_range;
-
- scoped_refptr<HeaderChecker> checker(
- new HeaderChecker(setup_.build_settings(), targets_));
- {
- Err err;
- SourceFile source_file = checker->SourceFileForInclude(
- "lib/header1.h", kIncludeDirs, dummy_input_file, dummy_range, &err);
- EXPECT_FALSE(err.has_error());
- EXPECT_EQ(SourceFile("//lib/header1.h"), source_file);
- }
-
- {
- Err err;
- SourceFile source_file = checker->SourceFileForInclude(
- "header2.h", kIncludeDirs, dummy_input_file, dummy_range, &err);
- EXPECT_FALSE(err.has_error());
- EXPECT_EQ(SourceFile("/c/custom_include/header2.h"), source_file);
- }
-}
-
-TEST_F(HeaderCheckerTest, SourceFileForInclude_FileNotFound) {
- using base::FilePath;
- const char kFileContents[] = "Some dummy contents";
- const std::vector<SourceDir> kIncludeDirs = {SourceDir("//")};
- scoped_refptr<HeaderChecker> checker(
- new HeaderChecker(setup_.build_settings(), targets_));
-
- Err err;
- InputFile input_file(SourceFile("//input.cc"));
- input_file.SetContents(std::string(kFileContents));
- const int kLineNumber = 10;
- const int kColumnNumber = 16;
- const int kLength = 8;
- const int kByteNumber = 100;
- LocationRange range(
- Location(&input_file, kLineNumber, kColumnNumber, kByteNumber),
- Location(&input_file, kLineNumber, kColumnNumber + kLength, kByteNumber));
-
- SourceFile source_file = checker->SourceFileForInclude(
- "header.h", kIncludeDirs, input_file, range, &err);
- EXPECT_TRUE(source_file.is_null());
- EXPECT_FALSE(err.has_error());
-}
-
-TEST_F(HeaderCheckerTest, Friend) {
- // Note: we have a public dependency chain A -> B -> C set up already.
- InputFile input_file(SourceFile("//some_file.cc"));
- input_file.SetContents(std::string());
- LocationRange range; // Dummy value.
-
- // Add a private header on C.
- SourceFile c_private("//c_private.h");
- c_.sources().push_back(c_private);
- c_.set_all_headers_public(false);
-
- // List A as a friend of C.
- Err err;
- c_.friends().push_back(
- LabelPattern::GetPattern(SourceDir("//"), Value(nullptr, "//a:*"), &err));
- ASSERT_FALSE(err.has_error());
-
- // Must be after setting everything up for it to find the files.
- scoped_refptr<HeaderChecker> checker(
- new HeaderChecker(setup_.build_settings(), targets_));
-
- // B should not be allowed to include C's private header.
- err = Err();
- EXPECT_FALSE(checker->CheckInclude(&b_, input_file, c_private, range, &err));
- EXPECT_TRUE(err.has_error());
-
- // A should be able to because of the friend declaration.
- err = Err();
- EXPECT_TRUE(checker->CheckInclude(&a_, input_file, c_private, range, &err));
- EXPECT_FALSE(err.has_error()) << err.message();
-}
diff --git a/chromium/tools/gn/import_manager.cc b/chromium/tools/gn/import_manager.cc
deleted file mode 100644
index 405eb017a0b..00000000000
--- a/chromium/tools/gn/import_manager.cc
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/import_manager.h"
-
-#include <memory>
-
-#include "tools/gn/err.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/scope_per_file_provider.h"
-#include "tools/gn/trace.h"
-
-namespace {
-
-// Returns a newly-allocated scope on success, null on failure.
-std::unique_ptr<Scope> UncachedImport(const Settings* settings,
- const SourceFile& file,
- const ParseNode* node_for_err,
- Err* err) {
- ScopedTrace load_trace(TraceItem::TRACE_IMPORT_LOAD, file.value());
-
- const ParseNode* node = g_scheduler->input_file_manager()->SyncLoadFile(
- node_for_err->GetRange(), settings->build_settings(), file, err);
- if (!node)
- return nullptr;
-
- std::unique_ptr<Scope> scope =
- std::make_unique<Scope>(settings->base_config());
- scope->set_source_dir(file.GetDir());
-
- // Don't allow ScopePerFileProvider to provide target-related variables.
- // These will be relative to the imported file, which is probably not what
- // people mean when they use these.
- ScopePerFileProvider per_file_provider(scope.get(), false);
-
- scope->SetProcessingImport();
- node->Execute(scope.get(), err);
- if (err->has_error()) {
- // If there was an error, append the caller location so the error message
- // displays a why the file was imported (esp. useful for failed asserts).
- err->AppendSubErr(Err(node_for_err, "whence it was imported."));
- return nullptr;
- }
- scope->ClearProcessingImport();
-
- return scope;
-}
-
-} // namespace
-
-struct ImportManager::ImportInfo {
- ImportInfo() = default;
- ~ImportInfo() = default;
-
- // This lock protects the unique_ptr. Once the scope is computed,
- // it is const and can be accessed read-only outside of the lock.
- base::Lock load_lock;
-
- std::unique_ptr<const Scope> scope;
-
- // The result of loading the import. If the load failed, the scope will be
- // null but this will be set to error. In this case the thread should not
- // attempt to load the file, even if the scope is null.
- Err load_result;
-};
-
-ImportManager::ImportManager() = default;
-
-ImportManager::~ImportManager() = default;
-
-bool ImportManager::DoImport(const SourceFile& file,
- const ParseNode* node_for_err,
- Scope* scope,
- Err* err) {
- // Key for the current import on the current thread in imports_in_progress_.
- std::string key =
- std::to_string(base::PlatformThread::CurrentId()) + file.value();
-
- // See if we have a cached import, but be careful to actually do the scope
- // copying outside of the lock.
- ImportInfo* import_info = nullptr;
- {
- base::AutoLock lock(imports_lock_);
- std::unique_ptr<ImportInfo>& info_ptr = imports_[file];
- if (!info_ptr)
- info_ptr = std::make_unique<ImportInfo>();
-
- // Promote the ImportInfo to outside of the imports lock.
- import_info = info_ptr.get();
-
- if (imports_in_progress_.find(key) != imports_in_progress_.end()) {
- *err = Err(Location(), file.value() + " is part of an import loop.");
- return false;
- }
- imports_in_progress_.insert(key);
- }
-
- // Now use the per-import-file lock to block this thread if another thread
- // is already processing the import.
- const Scope* import_scope = nullptr;
- {
- base::TimeTicks import_block_begin = base::TimeTicks::Now();
- base::AutoLock lock(import_info->load_lock);
-
- if (!import_info->scope) {
- // Only load if the import hasn't already failed.
- if (!import_info->load_result.has_error()) {
- import_info->scope = UncachedImport(
- scope->settings(), file, node_for_err, &import_info->load_result);
- }
- if (import_info->load_result.has_error()) {
- *err = import_info->load_result;
- return false;
- }
- } else {
- // Add trace if this thread was blocked for a long period of time and did
- // not load the import itself.
- base::TimeTicks import_block_end = base::TimeTicks::Now();
- constexpr auto kImportBlockTraceThreshold =
- base::TimeDelta::FromMilliseconds(20);
- if (TracingEnabled() &&
- import_block_end - import_block_begin > kImportBlockTraceThreshold) {
- auto* import_block_trace =
- new TraceItem(TraceItem::TRACE_IMPORT_BLOCK, file.value(),
- base::PlatformThread::CurrentId());
- import_block_trace->set_begin(import_block_begin);
- import_block_trace->set_end(import_block_end);
- AddTrace(import_block_trace);
- }
- }
-
- // Promote the now-read-only scope to outside the load lock.
- import_scope = import_info->scope.get();
- }
-
- Scope::MergeOptions options;
- options.skip_private_vars = true;
- options.mark_dest_used = true; // Don't require all imported values be used.
-
- {
- base::AutoLock lock(imports_lock_);
- imports_in_progress_.erase(key);
- }
-
- return import_scope->NonRecursiveMergeTo(scope, options, node_for_err,
- "import", err);
-}
-
-std::vector<SourceFile> ImportManager::GetImportedFiles() const {
- std::vector<SourceFile> imported_files;
- imported_files.resize(imports_.size());
- std::transform(imports_.begin(), imports_.end(), imported_files.begin(),
- [](const ImportMap::value_type& val) { return val.first; });
- return imported_files;
-}
diff --git a/chromium/tools/gn/import_manager.h b/chromium/tools/gn/import_manager.h
deleted file mode 100644
index 01d8af612b0..00000000000
--- a/chromium/tools/gn/import_manager.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_IMPORT_MANAGER_H_
-#define TOOLS_GN_IMPORT_MANAGER_H_
-
-#include <map>
-#include <memory>
-#include <unordered_set>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/synchronization/lock.h"
-
-class Err;
-class ParseNode;
-class Scope;
-class SourceFile;
-
-// Provides a cache of the results of importing scopes so the results can
-// be re-used rather than running the imported files multiple times.
-class ImportManager {
- public:
- ImportManager();
- ~ImportManager();
-
- // Does an import of the given file into the given scope. On error, sets the
- // error and returns false.
- bool DoImport(const SourceFile& file,
- const ParseNode* node_for_err,
- Scope* scope,
- Err* err);
-
- std::vector<SourceFile> GetImportedFiles() const;
-
- private:
- struct ImportInfo;
-
- // Protects access to imports_ and imports_in_progress_. Do not hold when
- // actually executing imports.
- base::Lock imports_lock_;
-
- // Owning pointers to the scopes.
- typedef std::map<SourceFile, std::unique_ptr<ImportInfo>> ImportMap;
- ImportMap imports_;
-
- std::unordered_set<std::string> imports_in_progress_;
-
- DISALLOW_COPY_AND_ASSIGN(ImportManager);
-};
-
-#endif // TOOLS_GN_IMPORT_MANAGER_H_
diff --git a/chromium/tools/gn/inherited_libraries.cc b/chromium/tools/gn/inherited_libraries.cc
deleted file mode 100644
index 62c4150d5fc..00000000000
--- a/chromium/tools/gn/inherited_libraries.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/inherited_libraries.h"
-
-#include "tools/gn/target.h"
-
-InheritedLibraries::InheritedLibraries() = default;
-
-InheritedLibraries::~InheritedLibraries() = default;
-
-std::vector<const Target*> InheritedLibraries::GetOrdered() const {
- std::vector<const Target*> result;
- result.resize(map_.size());
-
- // The indices in the map should be from 0 to the number of items in the
- // map, so insert directly into the result (with some sanity checks).
- for (const auto& pair : map_) {
- size_t index = pair.second.index;
- DCHECK(index < result.size());
- DCHECK(!result[index]);
- result[index] = pair.first;
- }
-
- return result;
-}
-
-std::vector<std::pair<const Target*, bool>>
-InheritedLibraries::GetOrderedAndPublicFlag() const {
- std::vector<std::pair<const Target*, bool>> result;
- result.resize(map_.size());
-
- for (const auto& pair : map_) {
- size_t index = pair.second.index;
- DCHECK(index < result.size());
- DCHECK(!result[index].first);
- result[index] = std::make_pair(pair.first, pair.second.is_public);
- }
-
- return result;
-}
-
-void InheritedLibraries::Append(const Target* target, bool is_public) {
- // Try to insert a new node.
- auto insert_result = map_.insert(
- std::make_pair(target, Node(map_.size(), is_public)));
-
- if (!insert_result.second) {
- // Element already present, insert failed and insert_result indicates the
- // old one. The old one may need to have its public flag updated.
- if (is_public) {
- Node& existing_node = insert_result.first->second;
- existing_node.is_public = true;
- }
- }
-}
-
-void InheritedLibraries::AppendInherited(const InheritedLibraries& other,
- bool is_public) {
- // Append all items in order, mark them public only if the're already public
- // and we're adding them publically.
- for (const auto& cur : other.GetOrderedAndPublicFlag())
- Append(cur.first, is_public && cur.second);
-}
-
-void InheritedLibraries::AppendPublicSharedLibraries(
- const InheritedLibraries& other,
- bool is_public) {
- for (const auto& cur : other.GetOrderedAndPublicFlag()) {
- if (cur.first->output_type() == Target::SHARED_LIBRARY && cur.second)
- Append(cur.first, is_public);
- }
-}
diff --git a/chromium/tools/gn/inherited_libraries.h b/chromium/tools/gn/inherited_libraries.h
deleted file mode 100644
index e8568b26766..00000000000
--- a/chromium/tools/gn/inherited_libraries.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_INHERITED_LIBRARIES_H_
-#define TOOLS_GN_INHERITED_LIBRARIES_H_
-
-#include <stddef.h>
-
-#include <map>
-#include <utility>
-#include <vector>
-
-#include "base/macros.h"
-
-class Target;
-
-// Represents an ordered uniquified set of all shared/static libraries for
-// a given target. These are pushed up the dependency tree.
-//
-// Maintaining the order is important so GN links all libraries in the same
-// order specified in the build files.
-//
-// Since this list is uniquified, appending to the list will not actually
-// append a new item if the target already exists. However, the existing one
-// may have its is_public flag updated. "Public" always wins, so is_public will
-// be true if any dependency with that name has been set to public.
-class InheritedLibraries {
- public:
- InheritedLibraries();
- ~InheritedLibraries();
-
- // Returns the list of dependencies in order, optionally with the flag
- // indicating whether the dependency is public.
- std::vector<const Target*> GetOrdered() const;
- std::vector<std::pair<const Target*, bool>> GetOrderedAndPublicFlag() const;
-
- // Adds a single dependency to the end of the list. See note on adding above.
- void Append(const Target* target, bool is_public);
-
- // Appends all items from the "other" list to the current one. The is_public
- // parameter indicates how the current target depends on the items in
- // "other". If is_public is true, the existing public flags of the appended
- // items will be preserved (propogating the public-ness up the dependency
- // chain). If is_public is false, all deps will be added as private since
- // the current target isn't forwarding them.
- void AppendInherited(const InheritedLibraries& other, bool is_public);
-
- // Like AppendInherited but only appends the items in "other" that are of
- // type SHARED_LIBRARY and only when they're marked public. This is used
- // to push shared libraries up the dependency chain, following only public
- // deps, to dependent targets that need to use them.
- void AppendPublicSharedLibraries(const InheritedLibraries& other,
- bool is_public);
-
- private:
- struct Node {
- Node() : index(static_cast<size_t>(-1)), is_public(false) {}
- Node(size_t i, bool p) : index(i), is_public(p) {}
-
- size_t index;
- bool is_public;
- };
-
- typedef std::map<const Target*, Node> LibraryMap;
- LibraryMap map_;
-
- DISALLOW_COPY_AND_ASSIGN(InheritedLibraries);
-};
-
-#endif // TOOLS_GN_INHERITED_LIBRARIES_H_
diff --git a/chromium/tools/gn/inherited_libraries_unittest.cc b/chromium/tools/gn/inherited_libraries_unittest.cc
deleted file mode 100644
index 51152095352..00000000000
--- a/chromium/tools/gn/inherited_libraries_unittest.cc
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/inherited_libraries.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-// In these tests, Pair can't be used conveniently because the
-// "const" won't be inferred and the types won't match. This helper makes the
-// right type of pair with the const Target.
-std::pair<const Target*, bool> Pair(const Target* t, bool b) {
- return std::pair<const Target*, bool>(t, b);
-}
-
-} // namespace
-
-TEST(InheritedLibraries, Unique) {
- TestWithScope setup;
-
- Target a(setup.settings(), Label(SourceDir("//foo/"), "a"));
- Target b(setup.settings(), Label(SourceDir("//foo/"), "b"));
-
- // Setup, add the two targets as private.
- InheritedLibraries libs;
- libs.Append(&a, false);
- libs.Append(&b, false);
- auto result = libs.GetOrderedAndPublicFlag();
- ASSERT_EQ(2u, result.size());
- EXPECT_EQ(Pair(&a, false), result[0]);
- EXPECT_EQ(Pair(&b, false), result[1]);
-
- // Add again as private, this should be a NOP.
- libs.Append(&a, false);
- libs.Append(&b, false);
- result = libs.GetOrderedAndPublicFlag();
- ASSERT_EQ(2u, result.size());
- EXPECT_EQ(Pair(&a, false), result[0]);
- EXPECT_EQ(Pair(&b, false), result[1]);
-
- // Add as public, this should make both public.
- libs.Append(&a, true);
- libs.Append(&b, true);
- result = libs.GetOrderedAndPublicFlag();
- ASSERT_EQ(2u, result.size());
- EXPECT_EQ(Pair(&a, true), result[0]);
- EXPECT_EQ(Pair(&b, true), result[1]);
-
- // Add again private, they should stay public.
- libs.Append(&a, false);
- libs.Append(&b, false);
- result = libs.GetOrderedAndPublicFlag();
- ASSERT_EQ(2u, result.size());
- EXPECT_EQ(Pair(&a, true), result[0]);
- EXPECT_EQ(Pair(&b, true), result[1]);
-}
-
-TEST(InheritedLibraries, AppendInherited) {
- TestWithScope setup;
-
- Target a(setup.settings(), Label(SourceDir("//foo/"), "a"));
- Target b(setup.settings(), Label(SourceDir("//foo/"), "b"));
- Target w(setup.settings(), Label(SourceDir("//foo/"), "w"));
- Target x(setup.settings(), Label(SourceDir("//foo/"), "x"));
- Target y(setup.settings(), Label(SourceDir("//foo/"), "y"));
- Target z(setup.settings(), Label(SourceDir("//foo/"), "z"));
-
- InheritedLibraries libs;
- libs.Append(&a, false);
- libs.Append(&b, false);
-
- // Appending these things with private inheritance should make them private,
- // no matter how they're listed in the appended class.
- InheritedLibraries append_private;
- append_private.Append(&a, true);
- append_private.Append(&b, false);
- append_private.Append(&w, true);
- append_private.Append(&x, false);
- libs.AppendInherited(append_private, false);
-
- auto result = libs.GetOrderedAndPublicFlag();
- ASSERT_EQ(4u, result.size());
- EXPECT_EQ(Pair(&a, false), result[0]);
- EXPECT_EQ(Pair(&b, false), result[1]);
- EXPECT_EQ(Pair(&w, false), result[2]);
- EXPECT_EQ(Pair(&x, false), result[3]);
-
- // Appending these things with public inheritance should convert them.
- InheritedLibraries append_public;
- append_public.Append(&a, true);
- append_public.Append(&b, false);
- append_public.Append(&y, true);
- append_public.Append(&z, false);
- libs.AppendInherited(append_public, true);
-
- result = libs.GetOrderedAndPublicFlag();
- ASSERT_EQ(6u, result.size());
- EXPECT_EQ(Pair(&a, true), result[0]); // Converted to public.
- EXPECT_EQ(Pair(&b, false), result[1]);
- EXPECT_EQ(Pair(&w, false), result[2]);
- EXPECT_EQ(Pair(&x, false), result[3]);
- EXPECT_EQ(Pair(&y, true), result[4]); // Appended as public.
- EXPECT_EQ(Pair(&z, false), result[5]);
-}
-
-TEST(InheritedLibraries, AppendPublicSharedLibraries) {
- TestWithScope setup;
- InheritedLibraries append;
-
- // Two source sets.
- Target set_pub(setup.settings(), Label(SourceDir("//foo/"), "set_pub"));
- set_pub.set_output_type(Target::SOURCE_SET);
- append.Append(&set_pub, true);
- Target set_priv(setup.settings(), Label(SourceDir("//foo/"), "set_priv"));
- set_priv.set_output_type(Target::SOURCE_SET);
- append.Append(&set_priv, false);
-
- // Two shared libraries.
- Target sh_pub(setup.settings(), Label(SourceDir("//foo/"), "sh_pub"));
- sh_pub.set_output_type(Target::SHARED_LIBRARY);
- append.Append(&sh_pub, true);
- Target sh_priv(setup.settings(), Label(SourceDir("//foo/"), "sh_priv"));
- sh_priv.set_output_type(Target::SHARED_LIBRARY);
- append.Append(&sh_priv, false);
-
- InheritedLibraries libs;
- libs.AppendPublicSharedLibraries(append, true);
-
- auto result = libs.GetOrderedAndPublicFlag();
- ASSERT_EQ(1u, result.size());
- EXPECT_EQ(Pair(&sh_pub, true), result[0]);
-}
diff --git a/chromium/tools/gn/input_conversion.cc b/chromium/tools/gn/input_conversion.cc
deleted file mode 100644
index a7abcf4c078..00000000000
--- a/chromium/tools/gn/input_conversion.cc
+++ /dev/null
@@ -1,324 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/input_conversion.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/json/json_reader.h"
-#include "base/macros.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/values.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/err.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/label.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/parser.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/tokenizer.h"
-#include "tools/gn/value.h"
-
-namespace {
-
-enum ValueOrScope {
- PARSE_VALUE, // Treat the input as an expression.
- PARSE_SCOPE, // Treat the input as code and return the resulting scope.
-};
-
-// Sets the origin of the value and any nested values with the given node.
-Value ParseValueOrScope(const Settings* settings,
- const std::string& input,
- ValueOrScope what,
- const ParseNode* origin,
- Err* err) {
- // The memory for these will be kept around by the input file manager
- // so the origin parse nodes for the values will be preserved.
- InputFile* input_file;
- std::vector<Token>* tokens;
- std::unique_ptr<ParseNode>* parse_root_ptr;
- g_scheduler->input_file_manager()->AddDynamicInput(
- SourceFile(), &input_file, &tokens, &parse_root_ptr);
-
- input_file->SetContents(input);
- if (origin) {
- // This description will be the blame for any error messages caused by
- // script parsing or if a value is blamed. It will say
- // "Error at <...>:line:char" so here we try to make a string for <...>
- // that reads well in this context.
- input_file->set_friendly_name(
- "dynamically parsed input that " +
- origin->GetRange().begin().Describe(true) +
- " loaded ");
- } else {
- input_file->set_friendly_name("dynamic input");
- }
-
- *tokens = Tokenizer::Tokenize(input_file, err);
- if (err->has_error())
- return Value();
-
- // Parse the file according to what we're looking for.
- if (what == PARSE_VALUE)
- *parse_root_ptr = Parser::ParseValue(*tokens, err);
- else
- *parse_root_ptr = Parser::Parse(*tokens, err); // Will return a Block.
- if (err->has_error())
- return Value();
- ParseNode* parse_root = parse_root_ptr->get(); // For nicer syntax below.
-
- // It's valid for the result to be a null pointer, this just means that the
- // script returned nothing.
- if (!parse_root)
- return Value();
-
- std::unique_ptr<Scope> scope = std::make_unique<Scope>(settings);
- Value result = parse_root->Execute(scope.get(), err);
- if (err->has_error())
- return Value();
-
- // When we want the result as a scope, the result is actually the scope
- // we made, rather than the result of running the block (which will be empty).
- if (what == PARSE_SCOPE) {
- DCHECK(result.type() == Value::NONE);
- result = Value(origin, std::move(scope));
- }
- return result;
-}
-
-Value ParseList(const std::string& input, const ParseNode* origin, Err* err) {
- Value ret(origin, Value::LIST);
- std::vector<std::string> as_lines = base::SplitString(
- input, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-
- // Trim one empty line from the end since the last line might end in a
- // newline. If the user wants more trimming, they'll specify "trim" in the
- // input conversion options.
- if (!as_lines.empty() && as_lines[as_lines.size() - 1].empty())
- as_lines.resize(as_lines.size() - 1);
-
- ret.list_value().reserve(as_lines.size());
- for (const auto& line : as_lines)
- ret.list_value().push_back(Value(origin, line));
- return ret;
-}
-
-bool IsIdentifier(const base::StringPiece& buffer) {
- DCHECK(buffer.size() > 0);
- if (!Tokenizer::IsIdentifierFirstChar(buffer[0]))
- return false;
- for (size_t i = 1; i < buffer.size(); i++)
- if (!Tokenizer::IsIdentifierContinuingChar(buffer[i]))
- return false;
- return true;
-}
-
-Value ParseJSONValue(const Settings* settings,
- const base::Value& value,
- const ParseNode* origin,
- InputFile* input_file,
- Err* err) {
- switch (value.type()) {
- case base::Value::Type::NONE:
- *err = Err(origin, "Null values are not supported.");
- return Value();
- case base::Value::Type::BOOLEAN:
- return Value(origin, value.GetBool());
- case base::Value::Type::INTEGER:
- return Value(origin, static_cast<int64_t>(value.GetInt()));
- case base::Value::Type::DOUBLE:
- *err = Err(origin, "Floating point values are not supported.");
- return Value();
- case base::Value::Type::STRING:
- return Value(origin, value.GetString());
- case base::Value::Type::BINARY:
- *err = Err(origin, "Binary values are not supported.");
- return Value();
- case base::Value::Type::DICTIONARY: {
- std::unique_ptr<Scope> scope = std::make_unique<Scope>(settings);
- for (const auto& it : value.DictItems()) {
- Value value =
- ParseJSONValue(settings, it.second, origin, input_file, err);
- if (!IsIdentifier(it.first)) {
- *err = Err(origin, "Invalid identifier \"" + it.first + "\".");
- return Value();
- }
- // Search for the key in the input file. We know it's present because
- // it was parsed by the JSON reader, but we need its location to
- // construct a StringPiece that can be used as key in the Scope.
- size_t off = input_file->contents().find("\"" + it.first + "\"");
- if (off == std::string::npos) {
- *err = Err(origin, "Invalid encoding \"" + it.first + "\".");
- return Value();
- }
- base::StringPiece key(&input_file->contents()[off + 1],
- it.first.size());
- scope->SetValue(key, std::move(value), origin);
- }
- return Value(origin, std::move(scope));
- }
- case base::Value::Type::LIST: {
- Value result(origin, Value::LIST);
- result.list_value().reserve(value.GetList().size());
- for (const auto& val : value.GetList()) {
- Value value = ParseJSONValue(settings, val, origin, input_file, err);
- result.list_value().push_back(value);
- }
- return result;
- }
- }
- return Value();
-}
-
-// Parses the JSON string and converts it to GN value.
-Value ParseJSON(const Settings* settings,
- const std::string& input,
- const ParseNode* origin,
- Err* err) {
- InputFile* input_file;
- std::vector<Token>* tokens;
- std::unique_ptr<ParseNode>* parse_root_ptr;
- g_scheduler->input_file_manager()->AddDynamicInput(SourceFile(), &input_file,
- &tokens, &parse_root_ptr);
- input_file->SetContents(input);
-
- int error_code_out;
- std::string error_msg_out;
- std::unique_ptr<base::Value> value = base::JSONReader::ReadAndReturnError(
- input, base::JSONParserOptions::JSON_PARSE_RFC, &error_code_out,
- &error_msg_out);
- if (!value) {
- *err = Err(origin, "Input is not a valid JSON: " + error_msg_out);
- return Value();
- }
-
- return ParseJSONValue(settings, *value, origin, input_file, err);
-}
-
-// Backend for ConvertInputToValue, this takes the extracted string for the
-// input conversion so we can recursively call ourselves to handle the optional
-// "trim" prefix. This original value is also kept for the purposes of throwing
-// errors.
-Value DoConvertInputToValue(const Settings* settings,
- const std::string& input,
- const ParseNode* origin,
- const Value& original_input_conversion,
- const std::string& input_conversion,
- Err* err) {
- if (input_conversion.empty())
- return Value(); // Empty string means discard the result.
-
- const char kTrimPrefix[] = "trim ";
- if (base::StartsWith(input_conversion, kTrimPrefix,
- base::CompareCase::SENSITIVE)) {
- std::string trimmed;
- base::TrimWhitespaceASCII(input, base::TRIM_ALL, &trimmed);
-
- // Remove "trim" prefix from the input conversion and re-run.
- return DoConvertInputToValue(
- settings, trimmed, origin, original_input_conversion,
- input_conversion.substr(arraysize(kTrimPrefix) - 1), err);
- }
-
- if (input_conversion == "value")
- return ParseValueOrScope(settings, input, PARSE_VALUE, origin, err);
- if (input_conversion == "string")
- return Value(origin, input);
- if (input_conversion == "list lines")
- return ParseList(input, origin, err);
- if (input_conversion == "scope")
- return ParseValueOrScope(settings, input, PARSE_SCOPE, origin, err);
- if (input_conversion == "json")
- return ParseJSON(settings, input, origin, err);
-
- *err = Err(original_input_conversion, "Not a valid input_conversion.",
- "Run gn help input_conversion to see your options.");
- return Value();
-}
-
-} // namespace
-
-const char kInputConversion_Help[] =
- R"(input_conversion: Specifies how to transform input to a variable.
-
- input_conversion is an argument to read_file and exec_script that specifies
- how the result of the read operation should be converted into a variable.
-
- "" (the default)
- Discard the result and return None.
-
- "list lines"
- Return the file contents as a list, with a string for each line. The
- newlines will not be present in the result. The last line may or may not
- end in a newline.
-
- After splitting, each individual line will be trimmed of whitespace on
- both ends.
-
- "scope"
- Execute the block as GN code and return a scope with the resulting values
- in it. If the input was:
- a = [ "hello.cc", "world.cc" ]
- b = 26
- and you read the result into a variable named "val", then you could
- access contents the "." operator on "val":
- sources = val.a
- some_count = val.b
-
- "string"
- Return the file contents into a single string.
-
- "value"
- Parse the input as if it was a literal rvalue in a buildfile. Examples of
- typical program output using this mode:
- [ "foo", "bar" ] (result will be a list)
- or
- "foo bar" (result will be a string)
- or
- 5 (result will be an integer)
-
- Note that if the input is empty, the result will be a null value which
- will produce an error if assigned to a variable.
-
- "json"
- Parse the input as a JSON and convert it to equivalent GN rvalue. The data
- type mapping is:
- a string in JSON maps to string in GN
- an integer in JSON maps to integer in GN
- a float in JSON is unsupported and will result in an error
- an object in JSON maps to scope in GN
- an array in JSON maps to list in GN
- a boolean in JSON maps to boolean in GN
- a null in JSON is unsupported and will result in an error
-
- Nota that the dictionary keys have to be valid GN identifiers otherwise
- they will produce an error.
-
- "trim ..."
- Prefixing any of the other transformations with the word "trim" will
- result in whitespace being trimmed from the beginning and end of the
- result before processing.
-
- Examples: "trim string" or "trim list lines"
-
- Note that "trim value" is useless because the value parser skips
- whitespace anyway.
-)";
-
-Value ConvertInputToValue(const Settings* settings,
- const std::string& input,
- const ParseNode* origin,
- const Value& input_conversion_value,
- Err* err) {
- if (input_conversion_value.type() == Value::NONE)
- return Value(); // Allow null inputs to mean discard the result.
- if (!input_conversion_value.VerifyTypeIs(Value::STRING, err))
- return Value();
- return DoConvertInputToValue(settings, input, origin, input_conversion_value,
- input_conversion_value.string_value(), err);
-}
diff --git a/chromium/tools/gn/input_conversion.h b/chromium/tools/gn/input_conversion.h
deleted file mode 100644
index e6d5f6eab32..00000000000
--- a/chromium/tools/gn/input_conversion.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_INPUT_CONVERSION_H_
-#define TOOLS_GN_INPUT_CONVERSION_H_
-
-#include <string>
-
-class Err;
-class ParseNode;
-class Settings;
-class Value;
-
-extern const char kInputConversion_Help[];
-
-// Converts the given input string (is read from a file or output from a
-// script) to a Value. Conversions as specified in the input_conversion string
-// will be performed. The given origin will be used for constructing the
-// resulting Value.
-//
-// If the conversion string is invalid, the error will be set and an empty
-// value will be returned.
-Value ConvertInputToValue(const Settings* settings,
- const std::string& input,
- const ParseNode* origin,
- const Value& input_conversion_value,
- Err* err);
-
-#endif // TOOLS_GN_INPUT_CONVERSION_H_
diff --git a/chromium/tools/gn/input_conversion_unittest.cc b/chromium/tools/gn/input_conversion_unittest.cc
deleted file mode 100644
index dfc82c90e33..00000000000
--- a/chromium/tools/gn/input_conversion_unittest.cc
+++ /dev/null
@@ -1,274 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/input_conversion.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/err.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/test_with_scheduler.h"
-#include "tools/gn/test_with_scope.h"
-#include "tools/gn/value.h"
-
-namespace {
-
-// InputConversion needs a global scheduler object.
-class InputConversionTest : public TestWithScheduler {
- public:
- InputConversionTest() = default;
-
- const Settings* settings() { return setup_.settings(); }
-
- private:
- TestWithScope setup_;
-};
-
-} // namespace
-
-TEST_F(InputConversionTest, String) {
- Err err;
- std::string input("\nfoo bar \n");
- Value result = ConvertInputToValue(settings(), input, nullptr,
- Value(nullptr, "string"), &err);
- EXPECT_FALSE(err.has_error());
- EXPECT_EQ(Value::STRING, result.type());
- EXPECT_EQ(input, result.string_value());
-
- // Test with trimming.
- result = ConvertInputToValue(settings(), input, nullptr,
- Value(nullptr, "trim string"), &err);
- EXPECT_FALSE(err.has_error());
- EXPECT_EQ(Value::STRING, result.type());
- EXPECT_EQ("foo bar", result.string_value());
-}
-
-TEST_F(InputConversionTest, ListLines) {
- Err err;
- std::string input("\nfoo\nbar \n\n");
- Value result = ConvertInputToValue(settings(), input, nullptr,
- Value(nullptr, "list lines"), &err);
- EXPECT_FALSE(err.has_error());
- EXPECT_EQ(Value::LIST, result.type());
- ASSERT_EQ(4u, result.list_value().size());
- EXPECT_EQ("", result.list_value()[0].string_value());
- EXPECT_EQ("foo", result.list_value()[1].string_value());
- EXPECT_EQ("bar", result.list_value()[2].string_value());
- EXPECT_EQ("", result.list_value()[3].string_value());
-
- // Test with trimming.
- result = ConvertInputToValue(settings(), input, nullptr,
- Value(nullptr, "trim list lines"), &err);
- EXPECT_FALSE(err.has_error());
- EXPECT_EQ(Value::LIST, result.type());
- ASSERT_EQ(2u, result.list_value().size());
- EXPECT_EQ("foo", result.list_value()[0].string_value());
- EXPECT_EQ("bar", result.list_value()[1].string_value());
-}
-
-TEST_F(InputConversionTest, ValueString) {
- Err err;
- std::string input("\"str\"");
- Value result = ConvertInputToValue(settings(), input, nullptr,
- Value(nullptr, "value"), &err);
- EXPECT_FALSE(err.has_error());
- EXPECT_EQ(Value::STRING, result.type());
- EXPECT_EQ("str", result.string_value());
-}
-
-TEST_F(InputConversionTest, ValueInt) {
- Err err;
- std::string input("\n\n 6 \n ");
- Value result = ConvertInputToValue(settings(), input, nullptr,
- Value(nullptr, "value"), &err);
- EXPECT_FALSE(err.has_error());
- EXPECT_EQ(Value::INTEGER, result.type());
- EXPECT_EQ(6, result.int_value());
-}
-
-TEST_F(InputConversionTest, ValueList) {
- Err err;
- std::string input("\n [ \"a\", 5]");
- Value result = ConvertInputToValue(settings(), input, nullptr,
- Value(nullptr, "value"), &err);
- EXPECT_FALSE(err.has_error());
- ASSERT_EQ(Value::LIST, result.type());
- ASSERT_EQ(2u, result.list_value().size());
- EXPECT_EQ("a", result.list_value()[0].string_value());
- EXPECT_EQ(5, result.list_value()[1].int_value());
-}
-
-TEST_F(InputConversionTest, ValueDict) {
- Err err;
- std::string input("\n a = 5 b = \"foo\" c = a + 2");
- Value result = ConvertInputToValue(settings(), input, nullptr,
- Value(nullptr, "scope"), &err);
- EXPECT_FALSE(err.has_error());
- ASSERT_EQ(Value::SCOPE, result.type());
-
- const Value* a_value = result.scope_value()->GetValue("a");
- ASSERT_TRUE(a_value);
- EXPECT_EQ(5, a_value->int_value());
-
- const Value* b_value = result.scope_value()->GetValue("b");
- ASSERT_TRUE(b_value);
- EXPECT_EQ("foo", b_value->string_value());
-
- const Value* c_value = result.scope_value()->GetValue("c");
- ASSERT_TRUE(c_value);
- EXPECT_EQ(7, c_value->int_value());
-
- // Tests that when we get Values out of the input conversion, the resulting
- // values have an origin set to something corresponding to the input.
- const ParseNode* a_origin = a_value->origin();
- ASSERT_TRUE(a_origin);
- LocationRange a_range = a_origin->GetRange();
- EXPECT_EQ(2, a_range.begin().line_number());
- EXPECT_EQ(6, a_range.begin().column_number());
-
- const InputFile* a_file = a_range.begin().file();
- EXPECT_EQ(input, a_file->contents());
-}
-
-TEST_F(InputConversionTest, ValueJSON) {
- Err err;
- std::string input(R"*({
- "a": 5,
- "b": "foo",
- "c": {
- "d": true,
- "e": [
- {
- "f": "bar"
- }
- ]
- }
-})*");
- Value result = ConvertInputToValue(settings(), input, nullptr,
- Value(nullptr, "json"), &err);
- EXPECT_FALSE(err.has_error());
- ASSERT_EQ(Value::SCOPE, result.type());
-
- const Value* a_value = result.scope_value()->GetValue("a");
- ASSERT_TRUE(a_value);
- EXPECT_EQ(5, a_value->int_value());
-
- const Value* b_value = result.scope_value()->GetValue("b");
- ASSERT_TRUE(b_value);
- EXPECT_EQ("foo", b_value->string_value());
-
- const Value* c_value = result.scope_value()->GetValue("c");
- ASSERT_TRUE(c_value);
- ASSERT_EQ(Value::SCOPE, c_value->type());
-
- const Value* d_value = c_value->scope_value()->GetValue("d");
- ASSERT_TRUE(d_value);
- EXPECT_EQ(true, d_value->boolean_value());
-
- const Value* e_value = c_value->scope_value()->GetValue("e");
- ASSERT_TRUE(e_value);
- ASSERT_EQ(Value::LIST, e_value->type());
-
- EXPECT_EQ(1u, e_value->list_value().size());
- ASSERT_EQ(Value::SCOPE, e_value->list_value()[0].type());
- const Value* f_value = e_value->list_value()[0].scope_value()->GetValue("f");
- ASSERT_TRUE(f_value);
- EXPECT_EQ("bar", f_value->string_value());
-}
-
-TEST_F(InputConversionTest, ValueJSONInvalidInput) {
- Err err;
- std::string input(R"*({
- "a": 5,
- "b":
-})*");
- Value result = ConvertInputToValue(settings(), input, nullptr,
- Value(nullptr, "json"), &err);
- EXPECT_TRUE(err.has_error());
- EXPECT_EQ("Input is not a valid JSON: Line: 4, column: 2, Unexpected token.",
- err.message());
-}
-
-TEST_F(InputConversionTest, ValueJSONUnsupportedValue) {
- Err err;
- std::string input(R"*({
- "a": null
-})*");
- Value result = ConvertInputToValue(settings(), input, nullptr,
- Value(nullptr, "json"), &err);
- EXPECT_TRUE(err.has_error());
- EXPECT_EQ("Null values are not supported.", err.message());
-}
-
-TEST_F(InputConversionTest, ValueJSONInvalidVariable) {
- Err err;
- std::string input(R"*({
- "a\\x0001b": 5
-})*");
- Value result = ConvertInputToValue(settings(), input, nullptr,
- Value(nullptr, "json"), &err);
- EXPECT_TRUE(err.has_error());
- EXPECT_EQ("Invalid identifier \"a\\x0001b\".", err.message());
-}
-
-TEST_F(InputConversionTest, ValueJSONUnsupported) {
- Err err;
- std::string input(R"*({
- "d": 0.0
-})*");
- Value result = ConvertInputToValue(settings(), input, nullptr,
- Value(nullptr, "json"), &err);
- EXPECT_TRUE(err.has_error());
- EXPECT_EQ("Floating point values are not supported.", err.message());
-}
-
-TEST_F(InputConversionTest, ValueEmpty) {
- Err err;
- Value result = ConvertInputToValue(settings(), "", nullptr,
- Value(nullptr, "value"), &err);
- EXPECT_FALSE(err.has_error());
- EXPECT_EQ(Value::NONE, result.type());
-}
-
-TEST_F(InputConversionTest, ValueError) {
- static const char* const kTests[] = {
- "\n [ \"a\", 5\nfoo bar",
-
- // Blocks not allowed.
- "{ foo = 5 }",
-
- // Function calls not allowed.
- "print(5)",
-
- // Trailing junk not allowed.
- "233105-1",
-
- // Non-literals hidden in arrays are not allowed.
- "[233105 - 1]",
- "[rebase_path(\"//\")]",
- };
-
- for (auto* test : kTests) {
- Err err;
- std::string input(test);
- Value result = ConvertInputToValue(settings(), input, nullptr,
- Value(nullptr, "value"), &err);
- EXPECT_TRUE(err.has_error()) << test;
- }
-}
-
-// Passing none or the empty string for input conversion should ignore the
-// result.
-TEST_F(InputConversionTest, Ignore) {
- Err err;
- Value result = ConvertInputToValue(settings(), "foo", nullptr, Value(), &err);
- EXPECT_FALSE(err.has_error());
- EXPECT_EQ(Value::NONE, result.type());
-
- result =
- ConvertInputToValue(settings(), "foo", nullptr, Value(nullptr, ""), &err);
- EXPECT_FALSE(err.has_error());
- EXPECT_EQ(Value::NONE, result.type());
-}
diff --git a/chromium/tools/gn/input_file.cc b/chromium/tools/gn/input_file.cc
deleted file mode 100644
index 4d310e83435..00000000000
--- a/chromium/tools/gn/input_file.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/input_file.h"
-
-#include "base/files/file_util.h"
-
-InputFile::InputFile(const SourceFile& name)
- : name_(name),
- dir_(name_.GetDir()),
- contents_loaded_(false) {
-}
-
-InputFile::~InputFile() = default;
-
-void InputFile::SetContents(const std::string& c) {
- contents_loaded_ = true;
- contents_ = c;
-}
-
-bool InputFile::Load(const base::FilePath& system_path) {
- if (base::ReadFileToString(system_path, &contents_)) {
- contents_loaded_ = true;
- physical_name_ = system_path;
- return true;
- }
- return false;
-}
-
diff --git a/chromium/tools/gn/input_file.h b/chromium/tools/gn/input_file.h
deleted file mode 100644
index 49e5f855741..00000000000
--- a/chromium/tools/gn/input_file.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_INPUT_FILE_H_
-#define TOOLS_GN_INPUT_FILE_H_
-
-#include <string>
-
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "tools/gn/source_dir.h"
-#include "tools/gn/source_file.h"
-
-class InputFile {
- public:
- explicit InputFile(const SourceFile& name);
-
- ~InputFile();
-
- // The virtual name passed into the constructor. This does not take into
- // account whether the file was loaded from the secondary source tree (see
- // BuildSettings secondary_source_path).
- const SourceFile& name() const { return name_; }
-
- // The directory is just a cached version of name()->GetDir() but we get this
- // a lot so computing it once up front saves a bunch of work.
- const SourceDir& dir() const { return dir_; }
-
- // The physical name tells the actual name on disk, if there is one.
- const base::FilePath& physical_name() const { return physical_name_; }
-
- // The friendly name can be set to override the name() in cases where there
- // is no name (like SetContents is used instead) or if the name doesn't
- // make sense. This will be displayed in error messages.
- const std::string& friendly_name() const { return friendly_name_; }
- void set_friendly_name(const std::string& f) { friendly_name_ = f; }
-
- const std::string& contents() const {
- DCHECK(contents_loaded_);
- return contents_;
- }
-
- // For testing and in cases where this input doesn't actually refer to
- // "a file".
- void SetContents(const std::string& c);
-
- // Loads the given file synchronously, returning true on success. This
- bool Load(const base::FilePath& system_path);
-
- private:
- SourceFile name_;
- SourceDir dir_;
-
- base::FilePath physical_name_;
- std::string friendly_name_;
-
- bool contents_loaded_;
- std::string contents_;
-
- DISALLOW_COPY_AND_ASSIGN(InputFile);
-};
-
-#endif // TOOLS_GN_INPUT_FILE_H_
diff --git a/chromium/tools/gn/input_file_manager.cc b/chromium/tools/gn/input_file_manager.cc
deleted file mode 100644
index 6fe3cae8d84..00000000000
--- a/chromium/tools/gn/input_file_manager.cc
+++ /dev/null
@@ -1,323 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/input_file_manager.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/stl_util.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/parser.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/scope_per_file_provider.h"
-#include "tools/gn/tokenizer.h"
-#include "tools/gn/trace.h"
-
-namespace {
-
-void InvokeFileLoadCallback(const InputFileManager::FileLoadCallback& cb,
- const ParseNode* node) {
- cb.Run(node);
-}
-
-bool DoLoadFile(const LocationRange& origin,
- const BuildSettings* build_settings,
- const SourceFile& name,
- InputFile* file,
- std::vector<Token>* tokens,
- std::unique_ptr<ParseNode>* root,
- Err* err) {
- // Do all of this stuff outside the lock. We should not give out file
- // pointers until the read is complete.
- if (g_scheduler->verbose_logging()) {
- std::string logmsg = name.value();
- if (origin.begin().file())
- logmsg += " (referenced from " + origin.begin().Describe(false) + ")";
- g_scheduler->Log("Loading", logmsg);
- }
-
- // Read.
- base::FilePath primary_path = build_settings->GetFullPath(name);
- ScopedTrace load_trace(TraceItem::TRACE_FILE_LOAD, name.value());
- if (!file->Load(primary_path)) {
- if (!build_settings->secondary_source_path().empty()) {
- // Fall back to secondary source tree.
- base::FilePath secondary_path =
- build_settings->GetFullPathSecondary(name);
- if (!file->Load(secondary_path)) {
- *err = Err(origin, "Can't load input file.",
- "Unable to load:\n " +
- FilePathToUTF8(primary_path) + "\n"
- "I also checked in the secondary tree for:\n " +
- FilePathToUTF8(secondary_path));
- return false;
- }
- } else {
- *err = Err(origin,
- "Unable to load \"" + FilePathToUTF8(primary_path) + "\".");
- return false;
- }
- }
- load_trace.Done();
-
- ScopedTrace exec_trace(TraceItem::TRACE_FILE_PARSE, name.value());
-
- // Tokenize.
- *tokens = Tokenizer::Tokenize(file, err);
- if (err->has_error())
- return false;
-
- // Parse.
- *root = Parser::Parse(*tokens, err);
- if (err->has_error())
- return false;
-
- exec_trace.Done();
- return true;
-}
-
-} // namespace
-
-InputFileManager::InputFileData::InputFileData(const SourceFile& file_name)
- : file(file_name),
- loaded(false),
- sync_invocation(false) {
-}
-
-InputFileManager::InputFileData::~InputFileData() = default;
-
-InputFileManager::InputFileManager() = default;
-
-InputFileManager::~InputFileManager() {
- // Should be single-threaded by now.
-}
-
-bool InputFileManager::AsyncLoadFile(const LocationRange& origin,
- const BuildSettings* build_settings,
- const SourceFile& file_name,
- const FileLoadCallback& callback,
- Err* err) {
- // Try not to schedule callbacks while holding the lock. All cases that don't
- // want to schedule should return early. Otherwise, this will be scheduled
- // after we leave the lock.
- base::Closure schedule_this;
- {
- base::AutoLock lock(lock_);
-
- InputFileMap::const_iterator found = input_files_.find(file_name);
- if (found == input_files_.end()) {
- // New file, schedule load.
- std::unique_ptr<InputFileData> data =
- std::make_unique<InputFileData>(file_name);
- data->scheduled_callbacks.push_back(callback);
- schedule_this = base::Bind(&InputFileManager::BackgroundLoadFile,
- this,
- origin,
- build_settings,
- file_name,
- &data->file);
- input_files_[file_name] = std::move(data);
-
- } else {
- InputFileData* data = found->second.get();
-
- // Prevent mixing async and sync loads. See SyncLoadFile for discussion.
- if (data->sync_invocation) {
- g_scheduler->FailWithError(Err(
- origin, "Load type mismatch.",
- "The file \"" + file_name.value() + "\" was previously loaded\n"
- "synchronously (via an import) and now you're trying to load it "
- "asynchronously\n(via a deps rule). This is a class 2 misdemeanor: "
- "a single input file must\nbe loaded the same way each time to "
- "avoid blowing my tiny, tiny mind."));
- return false;
- }
-
- if (data->loaded) {
- // Can just directly issue the callback on the background thread.
- schedule_this = base::Bind(&InvokeFileLoadCallback, callback,
- data->parsed_root.get());
- } else {
- // Load is pending on this file, schedule the invoke.
- data->scheduled_callbacks.push_back(callback);
- return true;
- }
- }
- }
- g_scheduler->ScheduleWork(schedule_this);
- return true;
-}
-
-const ParseNode* InputFileManager::SyncLoadFile(
- const LocationRange& origin,
- const BuildSettings* build_settings,
- const SourceFile& file_name,
- Err* err) {
- base::AutoLock lock(lock_);
-
- InputFileData* data = nullptr;
- InputFileMap::iterator found = input_files_.find(file_name);
- if (found == input_files_.end()) {
- // Haven't seen this file yet, start loading right now.
- std::unique_ptr<InputFileData> new_data =
- std::make_unique<InputFileData>(file_name);
- data = new_data.get();
- data->sync_invocation = true;
- input_files_[file_name] = std::move(new_data);
-
- base::AutoUnlock unlock(lock_);
- if (!LoadFile(origin, build_settings, file_name, &data->file, err))
- return nullptr;
- } else {
- // This file has either been loaded or is pending loading.
- data = found->second.get();
-
- if (!data->sync_invocation) {
- // Don't allow mixing of sync and async loads. If an async load is
- // scheduled and then a bunch of threads need to load it synchronously
- // and block on it loading, it could deadlock or at least cause a lot
- // of wasted CPU while those threads wait for the load to complete (which
- // may be far back in the input queue).
- //
- // We could work around this by promoting the load to a sync load. This
- // requires a bunch of extra code to either check flags and likely do
- // extra locking (bad) or to just do both types of load on the file and
- // deal with the race condition.
- //
- // I have no practical way to test this, and generally we should have
- // all include files processed synchronously and all build files
- // processed asynchronously, so it doesn't happen in practice.
- *err = Err(
- origin, "Load type mismatch.",
- "The file \"" + file_name.value() + "\" was previously loaded\n"
- "asynchronously (via a deps rule) and now you're trying to load it "
- "synchronously.\nThis is a class 2 misdemeanor: a single input file "
- "must be loaded the same way\neach time to avoid blowing my tiny, "
- "tiny mind.");
- return nullptr;
- }
-
- if (!data->loaded) {
- // Wait for the already-pending sync load to complete.
- if (!data->completion_event) {
- data->completion_event = std::make_unique<base::WaitableEvent>(
- base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- }
- {
- base::AutoUnlock unlock(lock_);
- data->completion_event->Wait();
- }
- // If there were multiple waiters on the same event, we now need to wake
- // up the next one.
- data->completion_event->Signal();
- }
- }
-
- // The other load could have failed. It is possible that this thread's error
- // will be reported to the scheduler before the other thread's (and the first
- // error reported "wins"). Forward the parse error from the other load for
- // this thread so that the error message is useful.
- if (!data->parsed_root)
- *err = data->parse_error;
- return data->parsed_root.get();
-}
-
-void InputFileManager::AddDynamicInput(
- const SourceFile& name,
- InputFile** file,
- std::vector<Token>** tokens,
- std::unique_ptr<ParseNode>** parse_root) {
- std::unique_ptr<InputFileData> data = std::make_unique<InputFileData>(name);
- *file = &data->file;
- *tokens = &data->tokens;
- *parse_root = &data->parsed_root;
- {
- base::AutoLock lock(lock_);
- dynamic_inputs_.push_back(std::move(data));
- }
-}
-
-int InputFileManager::GetInputFileCount() const {
- base::AutoLock lock(lock_);
- return static_cast<int>(input_files_.size());
-}
-
-void InputFileManager::GetAllPhysicalInputFileNames(
- std::vector<base::FilePath>* result) const {
- base::AutoLock lock(lock_);
- result->reserve(input_files_.size());
- for (const auto& file : input_files_) {
- if (!file.second->file.physical_name().empty())
- result->push_back(file.second->file.physical_name());
- }
-}
-
-void InputFileManager::BackgroundLoadFile(const LocationRange& origin,
- const BuildSettings* build_settings,
- const SourceFile& name,
- InputFile* file) {
- Err err;
- if (!LoadFile(origin, build_settings, name, file, &err))
- g_scheduler->FailWithError(err);
-}
-
-bool InputFileManager::LoadFile(const LocationRange& origin,
- const BuildSettings* build_settings,
- const SourceFile& name,
- InputFile* file,
- Err* err) {
- std::vector<Token> tokens;
- std::unique_ptr<ParseNode> root;
- bool success = DoLoadFile(origin, build_settings, name, file,
- &tokens, &root, err);
- // Can't return early. We have to ensure that the completion event is
- // signaled in all cases bacause another thread could be blocked on this one.
-
- // Save this pointer for running the callbacks below, which happens after the
- // scoped ptr ownership is taken away inside the lock.
- ParseNode* unowned_root = root.get();
-
- std::vector<FileLoadCallback> callbacks;
- {
- base::AutoLock lock(lock_);
- DCHECK(input_files_.find(name) != input_files_.end());
-
- InputFileData* data = input_files_[name].get();
- data->loaded = true;
- if (success) {
- data->tokens.swap(tokens);
- data->parsed_root = std::move(root);
- } else {
- data->parse_error = *err;
- }
-
- // Unblock waiters on this event.
- //
- // It's somewhat bad to signal this inside the lock. When it's used, it's
- // lazily created inside the lock. So we need to do the check and signal
- // inside the lock to avoid race conditions on the lazy creation of the
- // lock.
- //
- // We could avoid this by creating the lock every time, but the lock is
- // very seldom used and will generally be NULL, so my current theory is that
- // several signals of a completion event inside a lock is better than
- // creating about 1000 extra locks (one for each file).
- if (data->completion_event)
- data->completion_event->Signal();
-
- callbacks.swap(data->scheduled_callbacks);
- }
-
- // Run pending invocations. Theoretically we could schedule each of these
- // separately to get some parallelism. But normally there will only be one
- // item in the list, so that's extra overhead and complexity for no gain.
- if (success) {
- for (const auto& cb : callbacks)
- cb.Run(unowned_root);
- }
- return success;
-}
diff --git a/chromium/tools/gn/input_file_manager.h b/chromium/tools/gn/input_file_manager.h
deleted file mode 100644
index dd166048e9b..00000000000
--- a/chromium/tools/gn/input_file_manager.h
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_INPUT_FILE_MANAGER_H_
-#define TOOLS_GN_INPUT_FILE_MANAGER_H_
-
-#include <set>
-#include <utility>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/containers/hash_tables.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/settings.h"
-
-class Err;
-class LocationRange;
-class ParseNode;
-class Token;
-
-// Manages loading and parsing files from disk. This doesn't actually have
-// any context for executing the results, so potentially multiple configs
-// could use the same input file (saving parsing).
-//
-// This class is threadsafe.
-//
-// InputFile objects must never be deleted while the program is running since
-// various state points into them.
-class InputFileManager : public base::RefCountedThreadSafe<InputFileManager> {
- public:
- // Callback issued when a file is laoded. On auccess, the parse node will
- // refer to the root block of the file. On failure, this will be NULL.
- typedef base::Callback<void(const ParseNode*)> FileLoadCallback;
-
- InputFileManager();
-
- // Loads the given file and executes the callback on the worker pool.
- //
- // There are two types of errors. For errors known synchronously, the error
- // will be set, it will return false, and no work will be scheduled.
- //
- // For parse errors and such that happen in the future, the error will be
- // logged to the scheduler and the callback will be invoked with a null
- // ParseNode pointer. The given |origin| will be blamed for the invocation.
- bool AsyncLoadFile(const LocationRange& origin,
- const BuildSettings* build_settings,
- const SourceFile& file_name,
- const FileLoadCallback& callback,
- Err* err);
-
- // Loads and parses the given file synchronously, returning the root block
- // corresponding to the parsed result. On error, return NULL and the given
- // Err is set.
- const ParseNode* SyncLoadFile(const LocationRange& origin,
- const BuildSettings* build_settings,
- const SourceFile& file_name,
- Err* err);
-
- // Creates an entry to manage the memory associated with keeping a parsed
- // set of code in memory.
- //
- // The values pointed to by the parameters will be filled with pointers to
- // the file, tokens, and parse node that this class created. The calling
- // code is responsible for populating these values and maintaining
- // threadsafety. This class' only job is to hold onto the memory and delete
- // it when the program exits.
- //
- // This solves the problem that sometimes we need to execute something
- // dynamic and save the result, but the values all have references to the
- // nodes and file that created it. Either we need to reset the origin of
- // the values and lose context for error reporting, or somehow keep the
- // associated parse nodes, tokens, and file data in memory. This function
- // allows the latter.
- void AddDynamicInput(const SourceFile& name,
- InputFile** file,
- std::vector<Token>** tokens,
- std::unique_ptr<ParseNode>** parse_root);
-
- // Does not count dynamic input.
- int GetInputFileCount() const;
-
- // Fills the vector with all input files.
- void GetAllPhysicalInputFileNames(std::vector<base::FilePath>* result) const;
-
- private:
- friend class base::RefCountedThreadSafe<InputFileManager>;
-
- struct InputFileData {
- explicit InputFileData(const SourceFile& file_name);
- ~InputFileData();
-
- // Don't touch this outside the lock until it's marked loaded.
- InputFile file;
-
- bool loaded;
-
- bool sync_invocation;
-
- // Lists all invocations that need to be executed when the file completes
- // loading.
- std::vector<FileLoadCallback> scheduled_callbacks;
-
- // Event to signal when the load is complete (or fails). This is lazily
- // created only when a thread is synchronously waiting for this load (which
- // only happens for imports).
- std::unique_ptr<base::WaitableEvent> completion_event;
-
- std::vector<Token> tokens;
-
- // Null before the file is loaded or if loading failed.
- std::unique_ptr<ParseNode> parsed_root;
- Err parse_error;
- };
-
- virtual ~InputFileManager();
-
- void BackgroundLoadFile(const LocationRange& origin,
- const BuildSettings* build_settings,
- const SourceFile& name,
- InputFile* file);
-
- // Loads the given file. On error, sets the Err and return false.
- bool LoadFile(const LocationRange& origin,
- const BuildSettings* build_settings,
- const SourceFile& name,
- InputFile* file,
- Err* err);
-
- mutable base::Lock lock_;
-
- // Maps repo-relative filenames to the corresponding owned pointer.
- typedef base::hash_map<SourceFile, std::unique_ptr<InputFileData>>
- InputFileMap;
- InputFileMap input_files_;
-
- // Tracks all dynamic inputs. The data are holders for memory management
- // purposes and should not be read or modified by this class. The values
- // will be vended out to the code creating the dynamic input, who is in
- // charge of the threadsafety requirements.
- //
- // See AddDynamicInput().
- std::vector<std::unique_ptr<InputFileData>> dynamic_inputs_;
-
- DISALLOW_COPY_AND_ASSIGN(InputFileManager);
-};
-
-#endif // TOOLS_GN_INPUT_FILE_MANAGER_H_
diff --git a/chromium/tools/gn/item.cc b/chromium/tools/gn/item.cc
deleted file mode 100644
index f36ff023b36..00000000000
--- a/chromium/tools/gn/item.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/item.h"
-
-#include "base/logging.h"
-#include "tools/gn/settings.h"
-
-Item::Item(const Settings* settings,
- const Label& label,
- const std::set<SourceFile>& build_dependency_files)
- : settings_(settings),
- label_(label),
- build_dependency_files_(build_dependency_files),
- defined_from_(nullptr) {}
-
-Item::~Item() = default;
-
-Config* Item::AsConfig() {
- return nullptr;
-}
-const Config* Item::AsConfig() const {
- return nullptr;
-}
-Pool* Item::AsPool() {
- return nullptr;
-}
-const Pool* Item::AsPool() const {
- return nullptr;
-}
-Target* Item::AsTarget() {
- return nullptr;
-}
-const Target* Item::AsTarget() const {
- return nullptr;
-}
-Toolchain* Item::AsToolchain() {
- return nullptr;
-}
-const Toolchain* Item::AsToolchain() const {
- return nullptr;
-}
-
-std::string Item::GetItemTypeName() const {
- if (AsConfig())
- return "config";
- if (AsTarget())
- return "target";
- if (AsToolchain())
- return "toolchain";
- if (AsPool())
- return "pool";
- NOTREACHED();
- return "this thing that I have no idea what it is";
-}
-
-bool Item::OnResolved(Err* err) {
- return true;
-}
diff --git a/chromium/tools/gn/item.h b/chromium/tools/gn/item.h
deleted file mode 100644
index f2e7c0658b8..00000000000
--- a/chromium/tools/gn/item.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_ITEM_H_
-#define TOOLS_GN_ITEM_H_
-
-#include <set>
-#include <string>
-
-#include "tools/gn/label.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/visibility.h"
-
-class Config;
-class ParseNode;
-class Pool;
-class Settings;
-class SourceFile;
-class Target;
-class Toolchain;
-
-// A named item (target, config, etc.) that participates in the dependency
-// graph.
-class Item {
- public:
- Item(const Settings* settings,
- const Label& label,
- const std::set<SourceFile>& build_dependency_files = {});
- virtual ~Item();
-
- const Settings* settings() const { return settings_; }
-
- // This is guaranteed to never change after construction so this can be
- // accessed from any thread with no locking once the item is constructed.
- const Label& label() const { return label_; }
-
- const ParseNode* defined_from() const { return defined_from_; }
- void set_defined_from(const ParseNode* df) { defined_from_ = df; }
-
- Visibility& visibility() { return visibility_; }
- const Visibility& visibility() const { return visibility_; }
-
- // Manual RTTI.
- virtual Config* AsConfig();
- virtual const Config* AsConfig() const;
- virtual Pool* AsPool();
- virtual const Pool* AsPool() const;
- virtual Target* AsTarget();
- virtual const Target* AsTarget() const;
- virtual Toolchain* AsToolchain();
- virtual const Toolchain* AsToolchain() const;
-
- // Returns a name like "target" or "config" for the type of item this is, to
- // be used in logging and error messages.
- std::string GetItemTypeName() const;
-
- // Returns the set of build files that may affect this item, please refer to
- // Scope for how this is determined.
- const std::set<SourceFile>& build_dependency_files() const {
- return build_dependency_files_;
- }
-
- std::set<SourceFile>& build_dependency_files() {
- return build_dependency_files_;
- }
-
- // Called when this item is resolved, meaning it and all of its dependents
- // have no unresolved deps. Returns true on success. Sets the error and
- // returns false on failure.
- virtual bool OnResolved(Err* err);
-
- private:
- const Settings* settings_;
- Label label_;
- std::set<SourceFile> build_dependency_files_;
- const ParseNode* defined_from_;
-
- Visibility visibility_;
-};
-
-#endif // TOOLS_GN_ITEM_H_
diff --git a/chromium/tools/gn/json_project_writer.cc b/chromium/tools/gn/json_project_writer.cc
deleted file mode 100644
index 4f4b0e7c41d..00000000000
--- a/chromium/tools/gn/json_project_writer.cc
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/json_project_writer.h"
-
-#include <iostream>
-#include <memory>
-
-#include "base/command_line.h"
-#include "base/json/json_writer.h"
-#include "base/strings/string_number_conversions.h"
-#include "tools/gn/builder.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/desc_builder.h"
-#include "tools/gn/exec_process.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/settings.h"
-
-// Structure of JSON output file
-// {
-// "build_settings" = {
-// "root_path" : "absolute path of project root",
-// "build_dir" : "build directory (project relative)",
-// "default_toolchain" : "name of default toolchain"
-// }
-// "targets" = {
-// "target x name" : { target x properties },
-// "target y name" : { target y properties },
-// ...
-// }
-// }
-// See desc_builder.cc for overview of target properties
-
-namespace {
-
-void AddTargetDependencies(const Target* target,
- std::set<const Target*>* deps) {
- for (const auto& pair : target->GetDeps(Target::DEPS_LINKED)) {
- if (deps->find(pair.ptr) == deps->end()) {
- deps->insert(pair.ptr);
- AddTargetDependencies(pair.ptr, deps);
- }
- }
-}
-
-// Filters targets according to filter string; Will also recursively
-// add dependent targets.
-bool FilterTargets(const BuildSettings* build_settings,
- std::vector<const Target*>& all_targets,
- std::vector<const Target*>* targets,
- const std::string& dir_filter_string,
- Err* err) {
- if (dir_filter_string.empty()) {
- *targets = all_targets;
- } else {
- targets->reserve(all_targets.size());
- std::vector<LabelPattern> filters;
- if (!commands::FilterPatternsFromString(build_settings, dir_filter_string,
- &filters, err)) {
- return false;
- }
- commands::FilterTargetsByPatterns(all_targets, filters, targets);
-
- std::set<const Target*> target_set(targets->begin(), targets->end());
- for (const auto* target : *targets)
- AddTargetDependencies(target, &target_set);
-
- targets->clear();
- targets->insert(targets->end(), target_set.begin(), target_set.end());
- }
-
- // Sort the list of targets per-label to get a consistent ordering of them
- // in the generated project (and thus stability of the file generated).
- std::sort(targets->begin(), targets->end(),
- [](const Target* a, const Target* b) {
- return a->label().name() < b->label().name();
- });
-
- return true;
-}
-
-std::string RenderJSON(const BuildSettings* build_settings,
- const Builder& builder,
- std::vector<const Target*>& all_targets) {
- Label default_toolchain_label;
-
- auto targets = std::make_unique<base::DictionaryValue>();
- for (const auto* target : all_targets) {
- if (default_toolchain_label.is_null())
- default_toolchain_label = target->settings()->default_toolchain_label();
- auto description =
- DescBuilder::DescriptionForTarget(target, "", false, false, false);
- // Outputs need to be asked for separately.
- auto outputs = DescBuilder::DescriptionForTarget(target, "source_outputs",
- false, false, false);
- base::DictionaryValue* outputs_value = nullptr;
- if (outputs->GetDictionary("source_outputs", &outputs_value) &&
- !outputs_value->empty()) {
- description->MergeDictionary(outputs.get());
- }
- targets->SetWithoutPathExpansion(
- target->label().GetUserVisibleName(default_toolchain_label),
- std::move(description));
- }
-
- auto settings = std::make_unique<base::DictionaryValue>();
- settings->SetKey("root_path", base::Value(build_settings->root_path_utf8()));
- settings->SetKey("build_dir",
- base::Value(build_settings->build_dir().value()));
- settings->SetKey(
- "default_toolchain",
- base::Value(default_toolchain_label.GetUserVisibleName(false)));
-
- auto output = std::make_unique<base::DictionaryValue>();
- output->SetWithoutPathExpansion("targets", std::move(targets));
- output->SetWithoutPathExpansion("build_settings", std::move(settings));
-
- std::string s;
- base::JSONWriter::WriteWithOptions(
- *output.get(), base::JSONWriter::OPTIONS_PRETTY_PRINT, &s);
- return s;
-}
-
-bool InvokePython(const BuildSettings* build_settings,
- const base::FilePath& python_script_path,
- const std::string& python_script_extra_args,
- const base::FilePath& output_path,
- bool quiet,
- Err* err) {
- const base::FilePath& python_path = build_settings->python_path();
- base::CommandLine cmdline(python_path);
- cmdline.AppendArg("--");
- cmdline.AppendArgPath(python_script_path);
- cmdline.AppendArgPath(output_path);
- if (!python_script_extra_args.empty()) {
- cmdline.AppendArg(python_script_extra_args);
- }
- base::FilePath startup_dir =
- build_settings->GetFullPath(build_settings->build_dir());
-
- std::string output;
- std::string stderr_output;
-
- int exit_code = 0;
- if (!internal::ExecProcess(cmdline, startup_dir, &output, &stderr_output,
- &exit_code)) {
- *err =
- Err(Location(), "Could not execute python.",
- "I was trying to execute \"" + FilePathToUTF8(python_path) + "\".");
- return false;
- }
-
- if (!quiet) {
- std::cout << output;
- std::cerr << stderr_output;
- }
-
- if (exit_code != 0) {
- *err = Err(Location(), "Python has quit with exit code " +
- base::IntToString(exit_code) + ".");
- return false;
- }
-
- return true;
-}
-
-} // namespace
-
-bool JSONProjectWriter::RunAndWriteFiles(
- const BuildSettings* build_settings,
- const Builder& builder,
- const std::string& file_name,
- const std::string& exec_script,
- const std::string& exec_script_extra_args,
- const std::string& dir_filter_string,
- bool quiet,
- Err* err) {
- SourceFile output_file = build_settings->build_dir().ResolveRelativeFile(
- Value(nullptr, file_name), err);
- if (output_file.is_null()) {
- return false;
- }
-
- base::FilePath output_path = build_settings->GetFullPath(output_file);
-
- std::vector<const Target*> all_targets = builder.GetAllResolvedTargets();
- std::vector<const Target*> targets;
- if (!FilterTargets(build_settings, all_targets, &targets, dir_filter_string,
- err)) {
- return false;
- }
-
- std::string json = RenderJSON(build_settings, builder, targets);
- if (!ContentsEqual(output_path, json)) {
- if (!WriteFileIfChanged(output_path, json, err)) {
- return false;
- }
-
- if (!exec_script.empty()) {
- SourceFile script_file;
- if (exec_script[0] != '/') {
- // Relative path, assume the base is in build_dir.
- script_file = build_settings->build_dir().ResolveRelativeFile(
- Value(nullptr, exec_script), err);
- if (script_file.is_null()) {
- return false;
- }
- } else {
- script_file = SourceFile(exec_script);
- }
- base::FilePath script_path = build_settings->GetFullPath(script_file);
- return InvokePython(build_settings, script_path, exec_script_extra_args,
- output_path, quiet, err);
- }
- }
-
- return true;
-}
diff --git a/chromium/tools/gn/json_project_writer.h b/chromium/tools/gn/json_project_writer.h
deleted file mode 100644
index 8c293bfd93d..00000000000
--- a/chromium/tools/gn/json_project_writer.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_JSON_WRITER_H_
-#define TOOLS_GN_JSON_WRITER_H_
-
-#include "tools/gn/err.h"
-#include "tools/gn/target.h"
-
-class Builder;
-class BuildSettings;
-
-class JSONProjectWriter {
- public:
- static bool RunAndWriteFiles(const BuildSettings* build_setting,
- const Builder& builder,
- const std::string& file_name,
- const std::string& exec_script,
- const std::string& exec_script_extra_args,
- const std::string& dir_filter_string,
- bool quiet,
- Err* err);
-};
-
-#endif
diff --git a/chromium/tools/gn/label.cc b/chromium/tools/gn/label.cc
deleted file mode 100644
index 26e452f7791..00000000000
--- a/chromium/tools/gn/label.cc
+++ /dev/null
@@ -1,332 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/label.h"
-
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "build/build_config.h"
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/value.h"
-
-namespace {
-
-// We print user visible label names with no trailing slash after the
-// directory name.
-std::string DirWithNoTrailingSlash(const SourceDir& dir) {
- // Be careful not to trim if the input is just "/" or "//".
- if (dir.value().size() > 2)
- return dir.value().substr(0, dir.value().size() - 1);
- return dir.value();
-}
-
-// Given the separate-out input (everything before the colon) in the dep rule,
-// computes the final build rule. Sets err on failure. On success,
-// |*used_implicit| will be set to whether the implicit current directory was
-// used. The value is used only for generating error messages.
-bool ComputeBuildLocationFromDep(const Value& input_value,
- const SourceDir& current_dir,
- const base::StringPiece& input,
- SourceDir* result,
- Err* err) {
- // No rule, use the current location.
- if (input.empty()) {
- *result = current_dir;
- return true;
- }
-
- *result = current_dir.ResolveRelativeDir(input_value, input, err);
- return true;
-}
-
-// Given the separated-out target name (after the colon) computes the final
-// name, using the implicit name from the previously-generated
-// computed_location if necessary. The input_value is used only for generating
-// error messages.
-bool ComputeTargetNameFromDep(const Value& input_value,
- const SourceDir& computed_location,
- const base::StringPiece& input,
- std::string* result,
- Err* err) {
- if (!input.empty()) {
- // Easy case: input is specified, just use it.
- result->assign(input.data(), input.size());
- return true;
- }
-
- const std::string& loc = computed_location.value();
-
- // Use implicit name. The path will be "//", "//base/", "//base/i18n/", etc.
- if (loc.size() <= 2) {
- *err = Err(input_value, "This dependency name is empty");
- return false;
- }
-
- size_t next_to_last_slash = loc.rfind('/', loc.size() - 2);
- DCHECK(next_to_last_slash != std::string::npos);
- result->assign(&loc[next_to_last_slash + 1],
- loc.size() - next_to_last_slash - 2);
- return true;
-}
-
-// The original value is used only for error reporting, use the |input| as the
-// input to this function (which may be a substring of the original value when
-// we're parsing toolchains.
-//
-// If the output toolchain vars are NULL, then we'll report an error if we
-// find a toolchain specified (this is used when recursively parsing toolchain
-// labels which themselves can't have toolchain specs).
-//
-// We assume that the output variables are initialized to empty so we don't
-// write them unless we need them to contain something.
-//
-// Returns true on success. On failure, the out* variables might be written to
-// but shouldn't be used.
-bool Resolve(const SourceDir& current_dir,
- const Label& current_toolchain,
- const Value& original_value,
- const base::StringPiece& input,
- SourceDir* out_dir,
- std::string* out_name,
- SourceDir* out_toolchain_dir,
- std::string* out_toolchain_name,
- Err* err) {
- // To workaround the problem that StringPiece operator[] doesn't return a ref.
- const char* input_str = input.data();
- size_t offset = 0;
-#if defined(OS_WIN)
- if (IsPathAbsolute(input)) {
- size_t drive_letter_pos = input[0] == '/' ? 1 : 0;
- if (input.size() > drive_letter_pos + 2 &&
- input[drive_letter_pos + 1] == ':' &&
- IsSlash(input[drive_letter_pos + 2]) &&
- base::IsAsciiAlpha(input[drive_letter_pos])) {
- // Skip over the drive letter colon.
- offset = drive_letter_pos + 2;
- }
- }
-#endif
- size_t path_separator = input.find_first_of(":(", offset);
- base::StringPiece location_piece;
- base::StringPiece name_piece;
- base::StringPiece toolchain_piece;
- if (path_separator == std::string::npos) {
- location_piece = input;
- // Leave name & toolchain piece null.
- } else {
- location_piece = base::StringPiece(&input_str[0], path_separator);
-
- size_t toolchain_separator = input.find('(', path_separator);
- if (toolchain_separator == std::string::npos) {
- name_piece = base::StringPiece(&input_str[path_separator + 1],
- input.size() - path_separator - 1);
- // Leave location piece null.
- } else if (!out_toolchain_dir) {
- // Toolchain specified but not allows in this context.
- *err = Err(original_value, "Toolchain has a toolchain.",
- "Your toolchain definition (inside the parens) seems to itself "
- "have a\ntoolchain. Don't do this.");
- return false;
- } else {
- // Name piece is everything between the two separators. Note that the
- // separators may be the same (e.g. "//foo(bar)" which means empty name.
- if (toolchain_separator > path_separator) {
- name_piece = base::StringPiece(
- &input_str[path_separator + 1],
- toolchain_separator - path_separator - 1);
- }
-
- // Toolchain name should end in a ) and this should be the end of the
- // string.
- if (input[input.size() - 1] != ')') {
- *err = Err(original_value, "Bad toolchain name.",
- "Toolchain name must end in a \")\" at the end of the label.");
- return false;
- }
-
- // Subtract off the two parens to just get the toolchain name.
- toolchain_piece = base::StringPiece(
- &input_str[toolchain_separator + 1],
- input.size() - toolchain_separator - 2);
- }
- }
-
- // Everything before the separator is the filename.
- // We allow three cases:
- // Absolute: "//foo:bar" -> /foo:bar
- // Target in current file: ":foo" -> <currentdir>:foo
- // Path with implicit name: "/foo" -> /foo:foo
- if (location_piece.empty() && name_piece.empty()) {
- // Can't use both implicit filename and name (":").
- *err = Err(original_value, "This doesn't specify a dependency.");
- return false;
- }
-
- if (!ComputeBuildLocationFromDep(original_value, current_dir, location_piece,
- out_dir, err))
- return false;
-
- if (!ComputeTargetNameFromDep(original_value, *out_dir, name_piece,
- out_name, err))
- return false;
-
- // Last, do the toolchains.
- if (out_toolchain_dir) {
- // Handle empty toolchain strings. We don't allow normal labels to be
- // empty so we can't allow the recursive call of this function to do this
- // check.
- if (toolchain_piece.empty()) {
- *out_toolchain_dir = current_toolchain.dir();
- *out_toolchain_name = current_toolchain.name();
- return true;
- } else {
- return Resolve(current_dir, current_toolchain, original_value,
- toolchain_piece, out_toolchain_dir, out_toolchain_name,
- nullptr, nullptr, err);
- }
- }
- return true;
-}
-
-} // namespace
-
-const char kLabels_Help[] =
- R"*(About labels
-
- Everything that can participate in the dependency graph (targets, configs,
- and toolchains) are identified by labels. A common label looks like:
-
- //base/test:test_support
-
- This consists of a source-root-absolute path, a colon, and a name. This means
- to look for the thing named "test_support" in "base/test/BUILD.gn".
-
- You can also specify system absolute paths if necessary. Typically such
- paths would be specified via a build arg so the developer can specify where
- the component is on their system.
-
- /usr/local/foo:bar (Posix)
- /C:/Program Files/MyLibs:bar (Windows)
-
-Toolchains
-
- A canonical label includes the label of the toolchain being used. Normally,
- the toolchain label is implicitly inherited from the current execution
- context, but you can override this to specify cross-toolchain dependencies:
-
- //base/test:test_support(//build/toolchain/win:msvc)
-
- Here GN will look for the toolchain definition called "msvc" in the file
- "//build/toolchain/win" to know how to compile this target.
-
-Relative labels
-
- If you want to refer to something in the same buildfile, you can omit
- the path name and just start with a colon. This format is recommended for
- all same-file references.
-
- :base
-
- Labels can be specified as being relative to the current directory.
- Stylistically, we prefer to use absolute paths for all non-file-local
- references unless a build file needs to be run in different contexts (like a
- project needs to be both standalone and pulled into other projects in
- difference places in the directory hierarchy).
-
- source/plugin:myplugin
- ../net:url_request
-
-Implicit names
-
- If a name is unspecified, it will inherit the directory name. Stylistically,
- we prefer to omit the colon and name when possible:
-
- //net -> //net:net
- //tools/gn -> //tools/gn:gn
-)*";
-
-Label::Label() = default;
-
-Label::Label(const SourceDir& dir,
- const base::StringPiece& name,
- const SourceDir& toolchain_dir,
- const base::StringPiece& toolchain_name)
- : dir_(dir),
- toolchain_dir_(toolchain_dir) {
- name_.assign(name.data(), name.size());
- toolchain_name_.assign(toolchain_name.data(), toolchain_name.size());
-}
-
-Label::Label(const SourceDir& dir, const base::StringPiece& name)
- : dir_(dir) {
- name_.assign(name.data(), name.size());
-}
-
-Label::Label(const Label& other) = default;
-
-Label::~Label() = default;
-
-// static
-Label Label::Resolve(const SourceDir& current_dir,
- const Label& current_toolchain,
- const Value& input,
- Err* err) {
- Label ret;
- if (input.type() != Value::STRING) {
- *err = Err(input, "Dependency is not a string.");
- return ret;
- }
- const std::string& input_string = input.string_value();
- if (input_string.empty()) {
- *err = Err(input, "Dependency string is empty.");
- return ret;
- }
-
- if (!::Resolve(current_dir, current_toolchain, input, input_string,
- &ret.dir_, &ret.name_,
- &ret.toolchain_dir_, &ret.toolchain_name_,
- err))
- return Label();
- return ret;
-}
-
-Label Label::GetToolchainLabel() const {
- return Label(toolchain_dir_, toolchain_name_);
-}
-
-Label Label::GetWithNoToolchain() const {
- return Label(dir_, name_);
-}
-
-std::string Label::GetUserVisibleName(bool include_toolchain) const {
- std::string ret;
- ret.reserve(dir_.value().size() + name_.size() + 1);
-
- if (dir_.is_null())
- return ret;
-
- ret = DirWithNoTrailingSlash(dir_);
- ret.push_back(':');
- ret.append(name_);
-
- if (include_toolchain) {
- ret.push_back('(');
- if (!toolchain_dir_.is_null() && !toolchain_name_.empty()) {
- ret.append(DirWithNoTrailingSlash(toolchain_dir_));
- ret.push_back(':');
- ret.append(toolchain_name_);
- }
- ret.push_back(')');
- }
- return ret;
-}
-
-std::string Label::GetUserVisibleName(const Label& default_toolchain) const {
- bool include_toolchain =
- default_toolchain.dir() != toolchain_dir_ ||
- default_toolchain.name() != toolchain_name_;
- return GetUserVisibleName(include_toolchain);
-}
diff --git a/chromium/tools/gn/label.h b/chromium/tools/gn/label.h
deleted file mode 100644
index 88fe430a649..00000000000
--- a/chromium/tools/gn/label.h
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_LABEL_H_
-#define TOOLS_GN_LABEL_H_
-
-#include <stddef.h>
-
-#include "base/containers/hash_tables.h"
-#include "tools/gn/source_dir.h"
-
-class Err;
-class Value;
-
-// A label represents the name of a target or some other named thing in
-// the source path. The label is always absolute and always includes a name
-// part, so it starts with a slash, and has one colon.
-class Label {
- public:
- Label();
-
- // Makes a label given an already-separated out path and name.
- // See also Resolve().
- Label(const SourceDir& dir,
- const base::StringPiece& name,
- const SourceDir& toolchain_dir,
- const base::StringPiece& toolchain_name);
-
- // Makes a label with an empty toolchain.
- Label(const SourceDir& dir, const base::StringPiece& name);
- Label(const Label& other);
- ~Label();
-
- // Resolves a string from a build file that may be relative to the
- // current directory into a fully qualified label. On failure returns an
- // is_null() label and sets the error.
- static Label Resolve(const SourceDir& current_dir,
- const Label& current_toolchain,
- const Value& input,
- Err* err);
-
- bool is_null() const { return dir_.is_null(); }
-
- const SourceDir& dir() const { return dir_; }
- const std::string& name() const { return name_; }
-
- const SourceDir& toolchain_dir() const { return toolchain_dir_; }
- const std::string& toolchain_name() const { return toolchain_name_; }
-
- // Returns the current label's toolchain as its own Label.
- Label GetToolchainLabel() const;
-
- // Returns a copy of this label but with an empty toolchain.
- Label GetWithNoToolchain() const;
-
- // Formats this label in a way that we can present to the user or expose to
- // other parts of the system. SourceDirs end in slashes, but the user
- // expects names like "//chrome/renderer:renderer_config" when printed. The
- // toolchain is optionally included.
- std::string GetUserVisibleName(bool include_toolchain) const;
-
- // Like the above version, but automatically includes the toolchain if it's
- // not the default one. Normally the user only cares about the toolchain for
- // non-default ones, so this can make certain output more clear.
- std::string GetUserVisibleName(const Label& default_toolchain) const;
-
- bool operator==(const Label& other) const {
- return name_ == other.name_ && dir_ == other.dir_ &&
- toolchain_dir_ == other.toolchain_dir_ &&
- toolchain_name_ == other.toolchain_name_;
- }
- bool operator!=(const Label& other) const {
- return !operator==(other);
- }
- bool operator<(const Label& other) const {
- if (int c = dir_.value().compare(other.dir_.value()))
- return c < 0;
- if (int c = name_.compare(other.name_))
- return c < 0;
- if (int c = toolchain_dir_.value().compare(other.toolchain_dir_.value()))
- return c < 0;
- return toolchain_name_ < other.toolchain_name_;
- }
-
- void swap(Label& other) {
- dir_.swap(other.dir_);
- name_.swap(other.name_);
- toolchain_dir_.swap(other.toolchain_dir_);
- toolchain_name_.swap(other.toolchain_name_);
- }
-
- // Returns true if the toolchain dir/name of this object matches some
- // other object.
- bool ToolchainsEqual(const Label& other) const {
- return toolchain_dir_ == other.toolchain_dir_ &&
- toolchain_name_ == other.toolchain_name_;
- }
-
- private:
- SourceDir dir_;
- std::string name_;
-
- SourceDir toolchain_dir_;
- std::string toolchain_name_;
-};
-
-namespace BASE_HASH_NAMESPACE {
-
-template<> struct hash<Label> {
- std::size_t operator()(const Label& v) const {
- hash<std::string> stringhash;
- return ((stringhash(v.dir().value()) * 131 +
- stringhash(v.name())) * 131 +
- stringhash(v.toolchain_dir().value())) * 131 +
- stringhash(v.toolchain_name());
- }
-};
-
-} // namespace BASE_HASH_NAMESPACE
-
-inline void swap(Label& lhs, Label& rhs) {
- lhs.swap(rhs);
-}
-
-extern const char kLabels_Help[];
-
-#endif // TOOLS_GN_LABEL_H_
diff --git a/chromium/tools/gn/label_pattern.cc b/chromium/tools/gn/label_pattern.cc
deleted file mode 100644
index b2568e7d315..00000000000
--- a/chromium/tools/gn/label_pattern.cc
+++ /dev/null
@@ -1,276 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/label_pattern.h"
-
-#include <stddef.h>
-
-#include "base/strings/string_util.h"
-#include "build/build_config.h"
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/value.h"
-
-const char kLabelPattern_Help[] =
- R"*(Label patterns
-
- A label pattern is a way of expressing one or more labels in a portion of the
- source tree. They are not general regular expressions.
-
- They can take the following forms only:
-
- - Explicit (no wildcard):
- "//foo/bar:baz"
- ":baz"
-
- - Wildcard target names:
- "//foo/bar:*" (all targets in the //foo/bar/BUILD.gn file)
- ":*" (all targets in the current build file)
-
- - Wildcard directory names ("*" is only supported at the end)
- "*" (all targets)
- "//foo/bar/*" (all targets in any subdir of //foo/bar)
- "./*" (all targets in the current build file or sub dirs)
-
- Any of the above forms can additionally take an explicit toolchain. In this
- case, the toolchain must be fully qualified (no wildcards are supported in
- the toolchain name).
-
- "//foo:bar(//build/toochain:mac)"
- An explicit target in an explicit toolchain.
-
- ":*(//build/toolchain/linux:32bit)"
- All targets in the current build file using the 32-bit Linux toolchain.
-
- "//foo/*(//build/toolchain:win)"
- All targets in //foo and any subdirectory using the Windows
- toolchain.
-)*";
-
-LabelPattern::LabelPattern() : type_(MATCH) {
-}
-
-LabelPattern::LabelPattern(Type type,
- const SourceDir& dir,
- const base::StringPiece& name,
- const Label& toolchain_label)
- : toolchain_(toolchain_label),
- type_(type),
- dir_(dir) {
- name.CopyToString(&name_);
-}
-
-LabelPattern::LabelPattern(const LabelPattern& other) = default;
-
-LabelPattern::~LabelPattern() = default;
-
-// static
-LabelPattern LabelPattern::GetPattern(const SourceDir& current_dir,
- const Value& value,
- Err* err) {
- if (!value.VerifyTypeIs(Value::STRING, err))
- return LabelPattern();
-
- base::StringPiece str(value.string_value());
- if (str.empty()) {
- *err = Err(value, "Label pattern must not be empty.");
- return LabelPattern();
- }
-
- // If there's no wildcard, this is specifying an exact label, use the
- // label resolution code to get all the implicit name stuff.
- size_t star = str.find('*');
- if (star == std::string::npos) {
- Label label = Label::Resolve(current_dir, Label(), value, err);
- if (err->has_error())
- return LabelPattern();
-
- // Toolchain.
- Label toolchain_label;
- if (!label.toolchain_dir().is_null() || !label.toolchain_name().empty())
- toolchain_label = label.GetToolchainLabel();
-
- return LabelPattern(MATCH, label.dir(), label.name(), toolchain_label);
- }
-
- // Wildcard case, need to split apart the label to see what it specifies.
- Label toolchain_label;
- size_t open_paren = str.find('(');
- if (open_paren != std::string::npos) {
- // Has a toolchain definition, extract inside the parens.
- size_t close_paren = str.find(')', open_paren);
- if (close_paren == std::string::npos) {
- *err = Err(value, "No close paren when looking for toolchain name.");
- return LabelPattern();
- }
-
- std::string toolchain_string =
- str.substr(open_paren + 1, close_paren - open_paren - 1).as_string();
- if (toolchain_string.find('*') != std::string::npos) {
- *err = Err(value, "Can't have a wildcard in the toolchain.");
- return LabelPattern();
- }
-
- // Parse the inside of the parens as a label for a toolchain.
- Value value_for_toolchain(value.origin(), toolchain_string);
- toolchain_label =
- Label::Resolve(current_dir, Label(), value_for_toolchain, err);
- if (err->has_error())
- return LabelPattern();
-
- // Trim off the toolchain for the processing below.
- str = str.substr(0, open_paren);
- }
-
- // Extract path and name.
- base::StringPiece path;
- base::StringPiece name;
- size_t offset = 0;
-#if defined(OS_WIN)
- if (IsPathAbsolute(str)) {
- size_t drive_letter_pos = str[0] == '/' ? 1 : 0;
- if (str.size() > drive_letter_pos + 2 && str[drive_letter_pos + 1] == ':' &&
- IsSlash(str[drive_letter_pos + 2]) &&
- base::IsAsciiAlpha(str[drive_letter_pos])) {
- // Skip over the drive letter colon.
- offset = drive_letter_pos + 2;
- }
- }
-#endif
- size_t colon = str.find(':', offset);
- if (colon == std::string::npos) {
- path = base::StringPiece(str);
- } else {
- path = str.substr(0, colon);
- name = str.substr(colon + 1);
- }
-
- // The path can have these forms:
- // 1. <empty> (use current dir)
- // 2. <non wildcard stuff> (send through directory resolution)
- // 3. <non wildcard stuff>* (send stuff through dir resolution, note star)
- // 4. * (matches anything)
- SourceDir dir;
- bool has_path_star = false;
- if (path.empty()) {
- // Looks like ":foo".
- dir = current_dir;
- } else if (path[path.size() - 1] == '*') {
- // Case 3 or 4 above.
- has_path_star = true;
-
- // Adjust path to contain everything but the star.
- path = path.substr(0, path.size() - 1);
-
- if (!path.empty() && path[path.size() - 1] != '/') {
- // The input was "foo*" which is invalid.
- *err = Err(value, "'*' must match full directories in a label pattern.",
- "You did \"foo*\" but this thing doesn't do general pattern\n"
- "matching. Instead, you have to add a slash: \"foo/*\" to match\n"
- "all targets in a directory hierarchy.");
- return LabelPattern();
- }
- }
-
- // Resolve the part of the path that's not the wildcard.
- if (!path.empty()) {
- // The non-wildcard stuff better not have a wildcard.
- if (path.find('*') != base::StringPiece::npos) {
- *err = Err(value, "Label patterns only support wildcard suffixes.",
- "The pattern contained a '*' that wasn't at the end.");
- return LabelPattern();
- }
-
- // Resolve the non-wildcard stuff.
- dir = current_dir.ResolveRelativeDir(value, path, err);
- if (err->has_error())
- return LabelPattern();
- }
-
- // Resolve the name. At this point, we're doing wildcard matches so the
- // name should either be empty ("foo/*") or a wildcard ("foo:*");
- if (colon != std::string::npos && name != "*") {
- *err = Err(value, "Invalid label pattern.",
- "You seem to be using the wildcard more generally that is supported.\n"
- "Did you mean \"foo:*\" to match everything in the file, or\n"
- "\"./*\" to recursively match everything in the currend subtree.");
- return LabelPattern();
- }
-
- Type type;
- if (has_path_star) {
- // We know there's a wildcard, so if the name is empty it looks like
- // "foo/*".
- type = RECURSIVE_DIRECTORY;
- } else {
- // Everything else should be of the form "foo:*".
- type = DIRECTORY;
- }
-
- // When we're doing wildcard matching, the name is always empty.
- return LabelPattern(type, dir, base::StringPiece(), toolchain_label);
-}
-
-bool LabelPattern::HasWildcard(const std::string& str) {
- // Just look for a star. In the future, we may want to handle escaping or
- // other types of patterns.
- return str.find('*') != std::string::npos;
-}
-
-bool LabelPattern::Matches(const Label& label) const {
- if (!toolchain_.is_null()) {
- // Toolchain must match exactly.
- if (toolchain_.dir() != label.toolchain_dir() ||
- toolchain_.name() != label.toolchain_name())
- return false;
- }
-
- switch (type_) {
- case MATCH:
- return label.name() == name_ && label.dir() == dir_;
- case DIRECTORY:
- // The directories must match exactly.
- return label.dir() == dir_;
- case RECURSIVE_DIRECTORY:
- // Our directory must be a prefix of the input label for recursive.
- return label.dir().value().compare(0, dir_.value().size(), dir_.value())
- == 0;
- default:
- NOTREACHED();
- return false;
- }
-}
-
-// static
-bool LabelPattern::VectorMatches(const std::vector<LabelPattern>& patterns,
- const Label& label) {
- for (const auto& pattern : patterns) {
- if (pattern.Matches(label))
- return true;
- }
- return false;
-}
-
-std::string LabelPattern::Describe() const {
- std::string result;
-
- switch (type()) {
- case MATCH:
- result = DirectoryWithNoLastSlash(dir()) + ":" + name();
- break;
- case DIRECTORY:
- result = DirectoryWithNoLastSlash(dir()) + ":*";
- break;
- case RECURSIVE_DIRECTORY:
- result = dir().value() + "*";
- break;
- }
-
- if (!toolchain_.is_null()) {
- result.push_back('(');
- result.append(toolchain_.GetUserVisibleName(false));
- result.push_back(')');
- }
- return result;
-}
diff --git a/chromium/tools/gn/label_pattern.h b/chromium/tools/gn/label_pattern.h
deleted file mode 100644
index 774b81a62fc..00000000000
--- a/chromium/tools/gn/label_pattern.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_LABEL_PATTERN_H_
-#define TOOLS_GN_LABEL_PATTERN_H_
-
-#include "base/strings/string_piece.h"
-#include "tools/gn/label.h"
-#include "tools/gn/source_dir.h"
-
-class Err;
-class Value;
-
-extern const char kLabelPattern_Help[];
-
-// A label pattern is a simple pattern that matches labels. It is used for
-// specifying visibility and other times when multiple targets need to be
-// referenced.
-class LabelPattern {
- public:
- enum Type {
- MATCH = 1, // Exact match for a given target.
- DIRECTORY, // Only targets in the file in the given directory.
- RECURSIVE_DIRECTORY // The given directory and any subdir.
- // (also indicates "public" when dir is empty).
- };
-
- LabelPattern();
- LabelPattern(Type type,
- const SourceDir& dir,
- const base::StringPiece& name,
- const Label& toolchain_label);
- LabelPattern(const LabelPattern& other);
- ~LabelPattern();
-
- // Converts the given input string to a pattern. This does special stuff
- // to treat the pattern as a label. Sets the error on failure.
- static LabelPattern GetPattern(const SourceDir& current_dir,
- const Value& value,
- Err* err);
-
- // Returns true if the given input string might match more than one thing.
- static bool HasWildcard(const std::string& str);
-
- // Returns true if this pattern matches the given label.
- bool Matches(const Label& label) const;
-
- // Returns true if any of the patterns in the vector match the label.
- static bool VectorMatches(const std::vector<LabelPattern>& patterns,
- const Label& label);
-
- // Returns a string representation of this pattern.
- std::string Describe() const;
-
- Type type() const { return type_; }
-
- const SourceDir& dir() const { return dir_; }
- const std::string& name() const { return name_; }
-
- const Label& toolchain() const { return toolchain_; }
- void set_toolchain(const Label& tc) { toolchain_ = tc; }
-
- private:
- // If nonempty, specifies the toolchain to use. If empty, this will match
- // all toolchains. This is independent of the match type.
- Label toolchain_;
-
- Type type_;
-
- // Used when type_ == PRIVATE and PRIVATE_RECURSIVE. This specifies the
- // directory that to which the pattern is private to.
- SourceDir dir_;
-
- // Empty name means match everything. Otherwise the name must match
- // exactly.
- std::string name_;
-};
-
-#endif // TOOLS_GN_LABEL_PATTERN_H_
diff --git a/chromium/tools/gn/label_pattern_unittest.cc b/chromium/tools/gn/label_pattern_unittest.cc
deleted file mode 100644
index 2154af1b88a..00000000000
--- a/chromium/tools/gn/label_pattern_unittest.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/err.h"
-#include "tools/gn/label_pattern.h"
-#include "tools/gn/value.h"
-
-namespace {
-
-struct PatternCase {
- const char* input;
- bool success;
-
- LabelPattern::Type type;
- const char* dir;
- const char* name;
- const char* toolchain;
-};
-
-} // namespace
-
-TEST(LabelPattern, PatternParse) {
- SourceDir current_dir("//foo/");
- PatternCase cases[] = {
- // Missing stuff.
- {"", false, LabelPattern::MATCH, "", "", ""},
- {":", false, LabelPattern::MATCH, "", "", ""},
- // Normal things.
- {":bar", true, LabelPattern::MATCH, "//foo/", "bar", ""},
- {"//la:bar", true, LabelPattern::MATCH, "//la/", "bar", ""},
- {"*", true, LabelPattern::RECURSIVE_DIRECTORY, "", "", ""},
- {":*", true, LabelPattern::DIRECTORY, "//foo/", "", ""},
- {"la:*", true, LabelPattern::DIRECTORY, "//foo/la/", "", ""},
- {"la/*:*", true, LabelPattern::RECURSIVE_DIRECTORY, "//foo/la/", "", ""},
- {"//la:*", true, LabelPattern::DIRECTORY, "//la/", "", ""},
- {"./*", true, LabelPattern::RECURSIVE_DIRECTORY, "//foo/", "", ""},
- {"foo/*", true, LabelPattern::RECURSIVE_DIRECTORY, "//foo/foo/", "", ""},
- {"//l/*", true, LabelPattern::RECURSIVE_DIRECTORY, "//l/", "", ""},
- // Toolchains.
- {"//foo()", true, LabelPattern::MATCH, "//foo/", "foo", ""},
- {"//foo(//bar)", true, LabelPattern::MATCH, "//foo/", "foo", "//bar:bar"},
- {"//foo:*(//bar)", true, LabelPattern::DIRECTORY, "//foo/", "",
- "//bar:bar"},
- {"//foo/*(//bar)", true, LabelPattern::RECURSIVE_DIRECTORY, "//foo/", "",
- "//bar:bar"},
- // Wildcards in invalid places.
- {"*foo*:bar", false, LabelPattern::MATCH, "", "", ""},
- {"foo*:*bar", false, LabelPattern::MATCH, "", "", ""},
- {"*foo:bar", false, LabelPattern::MATCH, "", "", ""},
- {"foo:bar*", false, LabelPattern::MATCH, "", "", ""},
- {"*:*", true, LabelPattern::RECURSIVE_DIRECTORY, "", "", ""},
- // Invalid toolchain stuff.
- {"//foo(//foo/bar:*)", false, LabelPattern::MATCH, "", "", ""},
- {"//foo/*(*)", false, LabelPattern::MATCH, "", "", ""},
- {"//foo(//bar", false, LabelPattern::MATCH, "", "", ""},
- // Absolute paths.
- {"/la/*", true, LabelPattern::RECURSIVE_DIRECTORY, "/la/", "", ""},
- {"/la:bar", true, LabelPattern::MATCH, "/la/", "bar", ""},
-#if defined(OS_WIN)
- {"/C:/la/*", true, LabelPattern::RECURSIVE_DIRECTORY, "/C:/la/", "", ""},
- {"C:/la/*", true, LabelPattern::RECURSIVE_DIRECTORY, "/C:/la/", "", ""},
- {"/C:/la:bar", true, LabelPattern::MATCH, "/C:/la/", "bar", ""},
- {"C:/la:bar", true, LabelPattern::MATCH, "/C:/la/", "bar", ""},
- {"C:foo", true, LabelPattern::MATCH, "//foo/C/", "foo", ""},
-#endif
- };
-
- for (size_t i = 0; i < arraysize(cases); i++) {
- const PatternCase& cur = cases[i];
- Err err;
- LabelPattern result =
- LabelPattern::GetPattern(current_dir, Value(nullptr, cur.input), &err);
-
- EXPECT_EQ(cur.success, !err.has_error()) << i << " " << cur.input;
- EXPECT_EQ(cur.type, result.type()) << i << " " << cur.input;
- EXPECT_EQ(cur.dir, result.dir().value()) << i << " " << cur.input;
- EXPECT_EQ(cur.name, result.name()) << i << " " << cur.input;
- EXPECT_EQ(cur.toolchain, result.toolchain().GetUserVisibleName(false))
- << i << " " << cur.input;
- }
-}
diff --git a/chromium/tools/gn/label_ptr.h b/chromium/tools/gn/label_ptr.h
deleted file mode 100644
index c0b2d636f17..00000000000
--- a/chromium/tools/gn/label_ptr.h
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_LABEL_PTR_H_
-#define TOOLS_GN_LABEL_PTR_H_
-
-#include <stddef.h>
-
-#include <functional>
-
-#include "tools/gn/label.h"
-
-class Config;
-class ParseNode;
-class Target;
-
-// Structure that holds a labeled "thing". This is used for various places
-// where we need to store lists of targets or configs. We sometimes populate
-// the pointers on another thread from where we compute the labels, so this
-// structure lets us save them separately. This also allows us to store the
-// location of the thing that added this dependency.
-template<typename T>
-struct LabelPtrPair {
- typedef T DestType;
-
- LabelPtrPair() : label(), ptr(nullptr), origin(nullptr) {}
-
- explicit LabelPtrPair(const Label& l)
- : label(l), ptr(nullptr), origin(nullptr) {}
-
- // This contructor is typically used in unit tests, it extracts the label
- // automatically from a given pointer.
- explicit LabelPtrPair(const T* p)
- : label(p->label()), ptr(p), origin(nullptr) {}
-
- ~LabelPtrPair() {}
-
- Label label;
- const T* ptr; // May be NULL.
-
- // The origin of this dependency. This will be null for internally generated
- // dependencies. This happens when a group is automatically expanded and that
- // group's members are added to the target that depends on that group.
- const ParseNode* origin;
-};
-
-typedef LabelPtrPair<Config> LabelConfigPair;
-typedef LabelPtrPair<Target> LabelTargetPair;
-
-typedef std::vector<LabelConfigPair> LabelConfigVector;
-typedef std::vector<LabelTargetPair> LabelTargetVector;
-
-// Comparison and search functions ---------------------------------------------
-
-// To do a brute-force search by label:
-// std::find_if(vect.begin(), vect.end(), LabelPtrLabelEquals<Config>(label));
-template<typename T>
-struct LabelPtrLabelEquals {
- explicit LabelPtrLabelEquals(const Label& l) : label(l) {}
-
- bool operator()(const LabelPtrPair<T>& arg) const {
- return arg.label == label;
- }
-
- const Label& label;
-};
-
-// To do a brute-force search by object pointer:
-// std::find_if(vect.begin(), vect.end(), LabelPtrPtrEquals<Config>(config));
-template<typename T>
-struct LabelPtrPtrEquals {
- explicit LabelPtrPtrEquals(const T* p) : ptr(p) {}
-
- bool operator()(const LabelPtrPair<T>& arg) const {
- return arg.ptr == ptr;
- }
-
- const T* ptr;
-};
-
-// To sort by label:
-// std::sort(vect.begin(), vect.end(), LabelPtrLabelLess<Config>());
-template<typename T>
-struct LabelPtrLabelLess {
- bool operator()(const LabelPtrPair<T>& a, const LabelPtrPair<T>& b) const {
- return a.label < b.label;
- }
-};
-
-// Default comparison operators -----------------------------------------------
-//
-// The default hash and comparison operators operate on the label, which should
-// always be valid, whereas the pointer is sometimes null.
-
-template<typename T> inline bool operator==(const LabelPtrPair<T>& a,
- const LabelPtrPair<T>& b) {
- return a.label == b.label;
-}
-
-template<typename T> inline bool operator<(const LabelPtrPair<T>& a,
- const LabelPtrPair<T>& b) {
- return a.label < b.label;
-}
-
-namespace BASE_HASH_NAMESPACE {
-
-template<typename T> struct hash< LabelPtrPair<T> > {
- std::size_t operator()(const LabelPtrPair<T>& v) const {
- BASE_HASH_NAMESPACE::hash<Label> h;
- return h(v.label);
- }
-};
-
-} // namespace BASE_HASH_NAMESPACE
-
-#endif // TOOLS_GN_LABEL_PTR_H_
diff --git a/chromium/tools/gn/label_unittest.cc b/chromium/tools/gn/label_unittest.cc
deleted file mode 100644
index 986aa9b50d6..00000000000
--- a/chromium/tools/gn/label_unittest.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/err.h"
-#include "tools/gn/label.h"
-#include "tools/gn/value.h"
-
-namespace {
-
-struct ParseDepStringCase {
- const char* cur_dir;
- const char* str;
- bool success;
- const char* expected_dir;
- const char* expected_name;
- const char* expected_toolchain_dir;
- const char* expected_toolchain_name;
-};
-
-} // namespace
-
-TEST(Label, Resolve) {
- ParseDepStringCase cases[] = {
- {"//chrome/", "", false, "", "", "", ""},
- {"//chrome/", "/", false, "", "", "", ""},
- {"//chrome/", ":", false, "", "", "", ""},
- {"//chrome/", "/:", false, "", "", "", ""},
- {"//chrome/", "blah", true, "//chrome/blah/", "blah", "//t/", "d"},
- {"//chrome/", "blah:bar", true, "//chrome/blah/", "bar", "//t/", "d"},
- // Absolute paths.
- {"//chrome/", "/chrome:bar", true, "/chrome/", "bar", "//t/", "d"},
- {"//chrome/", "/chrome/:bar", true, "/chrome/", "bar", "//t/", "d"},
-#if defined(OS_WIN)
- {"//chrome/", "/C:/chrome:bar", true, "/C:/chrome/", "bar", "//t/", "d"},
- {"//chrome/", "/C:/chrome/:bar", true, "/C:/chrome/", "bar", "//t/", "d"},
- {"//chrome/", "C:/chrome:bar", true, "/C:/chrome/", "bar", "//t/", "d"},
-#endif
- // Refers to root dir.
- {"//chrome/", "//:bar", true, "//", "bar", "//t/", "d"},
- // Implicit directory
- {"//chrome/", ":bar", true, "//chrome/", "bar", "//t/", "d"},
- {"//chrome/renderer/", ":bar", true, "//chrome/renderer/", "bar", "//t/",
- "d"},
- // Implicit names.
- {"//chrome/", "//base", true, "//base/", "base", "//t/", "d"},
- {"//chrome/", "//base/i18n", true, "//base/i18n/", "i18n", "//t/", "d"},
- {"//chrome/", "//base/i18n:foo", true, "//base/i18n/", "foo", "//t/", "d"},
- {"//chrome/", "//", false, "", "", "", ""},
- // Toolchain parsing.
- {"//chrome/", "//chrome:bar(//t:n)", true, "//chrome/", "bar", "//t/", "n"},
- {"//chrome/", "//chrome:bar(//t)", true, "//chrome/", "bar", "//t/", "t"},
- {"//chrome/", "//chrome:bar(//t:)", true, "//chrome/", "bar", "//t/", "t"},
- {"//chrome/", "//chrome:bar()", true, "//chrome/", "bar", "//t/", "d"},
- {"//chrome/", "//chrome:bar(foo)", true, "//chrome/", "bar",
- "//chrome/foo/", "foo"},
- {"//chrome/", "//chrome:bar(:foo)", true, "//chrome/", "bar", "//chrome/",
- "foo"},
- // TODO(brettw) it might be nice to make this an error:
- //{"//chrome/", "//chrome:bar())", false, "", "", "", "" },
- {"//chrome/", "//chrome:bar(//t:bar(tc))", false, "", "", "", ""},
- {"//chrome/", "//chrome:bar(()", false, "", "", "", ""},
- {"//chrome/", "(t:b)", false, "", "", "", ""},
- {"//chrome/", ":bar(//t/b)", true, "//chrome/", "bar", "//t/b/", "b"},
- {"//chrome/", ":bar(/t/b)", true, "//chrome/", "bar", "/t/b/", "b"},
- {"//chrome/", ":bar(t/b)", true, "//chrome/", "bar", "//chrome/t/b/", "b"},
- };
-
- Label default_toolchain(SourceDir("//t/"), "d");
-
- for (size_t i = 0; i < arraysize(cases); i++) {
- const ParseDepStringCase& cur = cases[i];
-
- std::string location, name;
- Err err;
- Value v(nullptr, Value::STRING);
- v.string_value() = cur.str;
- Label result =
- Label::Resolve(SourceDir(cur.cur_dir), default_toolchain, v, &err);
- EXPECT_EQ(cur.success, !err.has_error()) << i << " " << cur.str;
- if (!err.has_error() && cur.success) {
- EXPECT_EQ(cur.expected_dir, result.dir().value()) << i << " " << cur.str;
- EXPECT_EQ(cur.expected_name, result.name()) << i << " " << cur.str;
- EXPECT_EQ(cur.expected_toolchain_dir, result.toolchain_dir().value())
- << i << " " << cur.str;
- EXPECT_EQ(cur.expected_toolchain_name, result.toolchain_name())
- << i << " " << cur.str;
- }
- }
-}
diff --git a/chromium/tools/gn/last_commit_position.py b/chromium/tools/gn/last_commit_position.py
deleted file mode 100644
index a91f7226e17..00000000000
--- a/chromium/tools/gn/last_commit_position.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Writes the most recent "Cr-Commit-Position" value on the master branch
-to a C header file.
-
-Usage: last_commit_position.py <dir> <outfile> <headerguard>
-
- <dir>
- Some directory inside the repo to check. This will be used as the current
- directory when running git. It's best to pass the repo toplevel directory.
-
- <outfile>
- C header file to write.
-
- <headerguard>
- String to use as the header guard for the written file.
-"""
-
-import os
-import re
-import subprocess
-import sys
-
-def RunGitCommand(directory, command):
- """
- Launches git subcommand.
-
- Errors are swallowed.
-
- Returns:
- A process object or None.
- """
- command = ['git'] + command
- # Force shell usage under cygwin. This is a workaround for
- # mysterious loss of cwd while invoking cygwin's git.
- # We can't just pass shell=True to Popen, as under win32 this will
- # cause CMD to be used, while we explicitly want a cygwin shell.
- if sys.platform == 'cygwin':
- command = ['sh', '-c', ' '.join(command)]
- try:
- proc = subprocess.Popen(command,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- cwd=directory,
- shell=(sys.platform=='win32'))
- return proc
- except OSError:
- return None
-
-
-def FetchCommitPosition(directory):
- regex = re.compile(r'\s*Cr-Commit-Position: refs/heads/master@\{#(\d+)\}\s*')
-
- # Search this far backward in the git log. The commit position should be
- # close to the top. We allow some slop for long commit messages, and maybe
- # there were some local commits after the last "official" one. Having this
- # max prevents us from searching all history in the case of an error.
- max_lines = 2048
-
- proc = RunGitCommand(directory, ['log'])
- for i in range(max_lines):
- line = proc.stdout.readline()
- if not line:
- return None
-
- match = regex.match(line)
- if match:
- return match.group(1)
-
- return None
-
-
-def WriteHeader(header_file, header_guard, value):
- with open(header_file, 'w') as f:
- f.write('''/* Generated by last_commit_position.py. */
-
-#ifndef %(guard)s
-#define %(guard)s
-
-#define LAST_COMMIT_POSITION "%(value)s"
-
-#endif
-''' % {'guard': header_guard, 'value': value})
-
-
-if len(sys.argv) != 4:
- print "Wrong number of arguments"
- sys.exit(1)
-
-git_directory = sys.argv[1]
-output_file = sys.argv[2]
-header_guard = sys.argv[3]
-
-value = FetchCommitPosition(git_directory)
-if not value:
- value = 'UNKNOWN'
-
-WriteHeader(output_file, header_guard, value)
diff --git a/chromium/tools/gn/lib_file.cc b/chromium/tools/gn/lib_file.cc
deleted file mode 100644
index 9c55aaa8747..00000000000
--- a/chromium/tools/gn/lib_file.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/lib_file.h"
-
-#include "base/logging.h"
-
-LibFile::LibFile() = default;
-
-LibFile::LibFile(const SourceFile& source_file) : source_file_(source_file) {}
-
-LibFile::LibFile(const base::StringPiece& lib_name)
- : name_(lib_name.data(), lib_name.size()) {
- DCHECK(!lib_name.empty());
-}
-
-void LibFile::Swap(LibFile* other) {
- name_.swap(other->name_);
- source_file_.swap(other->source_file_);
-}
-
-const std::string& LibFile::value() const {
- return is_source_file() ? source_file_.value() : name_;
-}
-
-const SourceFile& LibFile::source_file() const {
- DCHECK(is_source_file());
- return source_file_;
-}
diff --git a/chromium/tools/gn/lib_file.h b/chromium/tools/gn/lib_file.h
deleted file mode 100644
index 675a48c4ce3..00000000000
--- a/chromium/tools/gn/lib_file.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_LIB_FILE_H_
-#define TOOLS_GN_LIB_FILE_H_
-
-#include <stddef.h>
-
-#include <algorithm>
-#include <string>
-
-#include "base/strings/string_piece.h"
-#include "tools/gn/source_file.h"
-
-// Represents an entry in "libs" list. Can be either a path (a SourceFile) or
-// a library name (a string).
-class LibFile {
- public:
- LibFile();
- explicit LibFile(const base::StringPiece& lib_name);
- explicit LibFile(const SourceFile& source_file);
-
- void Swap(LibFile* other);
- bool is_source_file() const { return name_.empty(); }
-
- // Returns name, or source_file().value() (whichever is set).
- const std::string& value() const;
- const SourceFile& source_file() const;
-
- bool operator==(const LibFile& other) const {
- return value() == other.value();
- }
- bool operator!=(const LibFile& other) const { return !operator==(other); }
- bool operator<(const LibFile& other) const { return value() < other.value(); }
-
- private:
- std::string name_;
- SourceFile source_file_;
-};
-
-namespace BASE_HASH_NAMESPACE {
-
-template <>
-struct hash<LibFile> {
- std::size_t operator()(const LibFile& v) const {
- hash<std::string> h;
- return h(v.value());
- }
-};
-
-} // namespace BASE_HASH_NAMESPACE
-
-inline void swap(LibFile& lhs, LibFile& rhs) {
- lhs.Swap(&rhs);
-}
-
-#endif // TOOLS_GN_LIB_FILE_H_
diff --git a/chromium/tools/gn/loader.cc b/chromium/tools/gn/loader.cc
deleted file mode 100644
index 2e10c9a78cd..00000000000
--- a/chromium/tools/gn/loader.cc
+++ /dev/null
@@ -1,429 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/loader.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/input_file_manager.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/scope_per_file_provider.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/source_dir.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/trace.h"
-
-namespace {
-
-struct SourceFileAndOrigin {
- SourceFileAndOrigin(const SourceFile& f, const LocationRange& o)
- : file(f), origin(o) {}
-
- SourceFile file;
- LocationRange origin;
-};
-
-} // namespace
-
-// Identifies one time a file is loaded in a given toolchain so we don't load
-// it more than once.
-struct LoaderImpl::LoadID {
- LoadID() = default;
- LoadID(const SourceFile& f, const Label& tc_name)
- : file(f), toolchain_name(tc_name) {}
-
- bool operator<(const LoadID& other) const {
- if (file.value() == other.file.value())
- return toolchain_name < other.toolchain_name;
- return file < other.file;
- }
-
- SourceFile file;
- Label toolchain_name;
-};
-
-// Our tracking information for a toolchain.
-struct LoaderImpl::ToolchainRecord {
- // The default toolchain label can be empty for the first time the default
- // toolchain is loaded, since we don't know it yet. This will be fixed up
- // later. It should be valid in all other cases.
- ToolchainRecord(const BuildSettings* build_settings,
- const Label& toolchain_label,
- const Label& default_toolchain_label)
- : settings(
- build_settings,
- GetOutputSubdirName(toolchain_label,
- toolchain_label == default_toolchain_label)),
- is_toolchain_loaded(false),
- is_config_loaded(false) {
- settings.set_default_toolchain_label(default_toolchain_label);
- settings.set_toolchain_label(toolchain_label);
- }
-
- Settings settings;
-
- bool is_toolchain_loaded;
- bool is_config_loaded;
-
- std::vector<SourceFileAndOrigin> waiting_on_me;
-};
-
-// -----------------------------------------------------------------------------
-
-const void* const Loader::kDefaultToolchainKey = &kDefaultToolchainKey;
-
-Loader::Loader() = default;
-
-Loader::~Loader() = default;
-
-void Loader::Load(const Label& label, const LocationRange& origin) {
- Load(BuildFileForLabel(label), origin, label.GetToolchainLabel());
-}
-
-// static
-SourceFile Loader::BuildFileForLabel(const Label& label) {
- return SourceFile(label.dir().value() + "BUILD.gn");
-}
-
-// -----------------------------------------------------------------------------
-
-LoaderImpl::LoaderImpl(const BuildSettings* build_settings)
- : pending_loads_(0), build_settings_(build_settings) {
- // There may not be an active TaskRunner at this point. When that's the case,
- // the calling code is expected to call set_task_runner().
- if (base::ThreadTaskRunnerHandle::IsSet())
- task_runner_ = base::ThreadTaskRunnerHandle::Get();
-}
-
-LoaderImpl::~LoaderImpl() = default;
-
-void LoaderImpl::Load(const SourceFile& file,
- const LocationRange& origin,
- const Label& in_toolchain_name) {
- const Label& toolchain_name = in_toolchain_name.is_null()
- ? default_toolchain_label_
- : in_toolchain_name;
- LoadID load_id(file, toolchain_name);
- if (!invocations_.insert(load_id).second)
- return; // Already in set, so this file was already loaded or schedulerd.
-
- if (toolchain_records_.empty()) {
- // Nothing loaded, need to load the default build config. The initial load
- // should not specify a toolchain.
- DCHECK(toolchain_name.is_null());
-
- std::unique_ptr<ToolchainRecord> new_record =
- std::make_unique<ToolchainRecord>(build_settings_, Label(), Label());
- ToolchainRecord* record = new_record.get();
- toolchain_records_[Label()] = std::move(new_record);
-
- // The default build config is no dependent on the toolchain definition,
- // since we need to load the build config before we know what the default
- // toolchain name is.
- record->is_toolchain_loaded = true;
-
- record->waiting_on_me.push_back(SourceFileAndOrigin(file, origin));
- ScheduleLoadBuildConfig(&record->settings, Scope::KeyValueMap());
-
- return;
- }
-
- ToolchainRecord* record;
- if (toolchain_name.is_null())
- record = toolchain_records_[default_toolchain_label_].get();
- else
- record = toolchain_records_[toolchain_name].get();
-
- if (!record) {
- DCHECK(!default_toolchain_label_.is_null());
-
- // No reference to this toolchain found yet, make one.
- std::unique_ptr<ToolchainRecord> new_record =
- std::make_unique<ToolchainRecord>(build_settings_, toolchain_name,
- default_toolchain_label_);
- record = new_record.get();
- toolchain_records_[toolchain_name] = std::move(new_record);
-
- // Schedule a load of the toolchain using the default one.
- Load(BuildFileForLabel(toolchain_name), origin, default_toolchain_label_);
- }
-
- if (record->is_config_loaded)
- ScheduleLoadFile(&record->settings, origin, file);
- else
- record->waiting_on_me.push_back(SourceFileAndOrigin(file, origin));
-}
-
-void LoaderImpl::ToolchainLoaded(const Toolchain* toolchain) {
- ToolchainRecord* record = toolchain_records_[toolchain->label()].get();
- if (!record) {
- DCHECK(!default_toolchain_label_.is_null());
- std::unique_ptr<ToolchainRecord> new_record =
- std::make_unique<ToolchainRecord>(build_settings_, toolchain->label(),
- default_toolchain_label_);
- record = new_record.get();
- toolchain_records_[toolchain->label()] = std::move(new_record);
- }
- record->is_toolchain_loaded = true;
-
- // The default build config is loaded first, then its toolchain. Secondary
- // ones are loaded in the opposite order so we can pass toolchain parameters
- // to the build config. So we may or may not have a config at this point.
- if (!record->is_config_loaded) {
- ScheduleLoadBuildConfig(&record->settings, toolchain->args());
- } else {
- // There should be nobody waiting on this if the build config is already
- // loaded.
- DCHECK(record->waiting_on_me.empty());
- }
-}
-
-Label LoaderImpl::GetDefaultToolchain() const {
- return default_toolchain_label_;
-}
-
-const Settings* LoaderImpl::GetToolchainSettings(const Label& label) const {
- ToolchainRecordMap::const_iterator found_toolchain;
- if (label.is_null()) {
- if (default_toolchain_label_.is_null())
- return nullptr;
- found_toolchain = toolchain_records_.find(default_toolchain_label_);
- } else {
- found_toolchain = toolchain_records_.find(label);
- }
-
- if (found_toolchain == toolchain_records_.end())
- return nullptr;
- return &found_toolchain->second->settings;
-}
-
-void LoaderImpl::ScheduleLoadFile(const Settings* settings,
- const LocationRange& origin,
- const SourceFile& file) {
- Err err;
- pending_loads_++;
- if (!AsyncLoadFile(origin, settings->build_settings(), file,
- base::Bind(&LoaderImpl::BackgroundLoadFile, this,
- settings, file, origin),
- &err)) {
- g_scheduler->FailWithError(err);
- DecrementPendingLoads();
- }
-}
-
-void LoaderImpl::ScheduleLoadBuildConfig(
- Settings* settings,
- const Scope::KeyValueMap& toolchain_overrides) {
- Err err;
- pending_loads_++;
- if (!AsyncLoadFile(LocationRange(), settings->build_settings(),
- settings->build_settings()->build_config_file(),
- base::Bind(&LoaderImpl::BackgroundLoadBuildConfig,
- this, settings, toolchain_overrides),
- &err)) {
- g_scheduler->FailWithError(err);
- DecrementPendingLoads();
- }
-}
-
-void LoaderImpl::BackgroundLoadFile(const Settings* settings,
- const SourceFile& file_name,
- const LocationRange& origin,
- const ParseNode* root) {
- if (!root) {
- task_runner_->PostTask(
- FROM_HERE, base::Bind(&LoaderImpl::DecrementPendingLoads, this));
- return;
- }
-
- if (g_scheduler->verbose_logging()) {
- g_scheduler->Log("Running", file_name.value() + " with toolchain " +
- settings->toolchain_label().GetUserVisibleName(false));
- }
-
- Scope our_scope(settings->base_config());
- ScopePerFileProvider per_file_provider(&our_scope, true);
- our_scope.set_source_dir(file_name.GetDir());
- our_scope.AddBuildDependencyFile(file_name);
-
- // Targets, etc. generated as part of running this file will end up here.
- Scope::ItemVector collected_items;
- our_scope.set_item_collector(&collected_items);
-
- ScopedTrace trace(TraceItem::TRACE_FILE_EXECUTE, file_name.value());
- trace.SetToolchain(settings->toolchain_label());
-
- Err err;
- root->Execute(&our_scope, &err);
- if (!err.has_error())
- our_scope.CheckForUnusedVars(&err);
-
- if (err.has_error()) {
- if (!origin.is_null())
- err.AppendSubErr(Err(origin, "which caused the file to be included."));
- g_scheduler->FailWithError(err);
- }
-
-
- // Pass all of the items that were defined off to the builder.
- for (auto& item : collected_items)
- settings->build_settings()->ItemDefined(std::move(item));
-
- trace.Done();
-
- task_runner_->PostTask(FROM_HERE, base::Bind(&LoaderImpl::DidLoadFile, this));
-}
-
-void LoaderImpl::BackgroundLoadBuildConfig(
- Settings* settings,
- const Scope::KeyValueMap& toolchain_overrides,
- const ParseNode* root) {
- if (!root) {
- task_runner_->PostTask(
- FROM_HERE, base::Bind(&LoaderImpl::DecrementPendingLoads, this));
- return;
- }
-
- Scope* base_config = settings->base_config();
- base_config->set_source_dir(SourceDir("//"));
- base_config->AddBuildDependencyFile(
- settings->build_settings()->build_config_file());
-
- settings->build_settings()->build_args().SetupRootScope(base_config,
- toolchain_overrides);
-
- base_config->SetProcessingBuildConfig();
-
- // See kDefaultToolchainKey in the header.
- Label default_toolchain_label;
- if (settings->is_default())
- base_config->SetProperty(kDefaultToolchainKey, &default_toolchain_label);
-
- ScopedTrace trace(TraceItem::TRACE_FILE_EXECUTE,
- settings->build_settings()->build_config_file().value());
- trace.SetToolchain(settings->toolchain_label());
-
- Err err;
- root->Execute(base_config, &err);
-
- // Clear all private variables left in the scope. We want the root build
- // config to be like a .gni file in that variables beginning with an
- // underscore aren't exported.
- base_config->RemovePrivateIdentifiers();
-
- trace.Done();
-
- if (err.has_error())
- g_scheduler->FailWithError(err);
-
- base_config->ClearProcessingBuildConfig();
- if (settings->is_default()) {
- // The default toolchain must have been set in the default build config
- // file.
- if (default_toolchain_label.is_null()) {
- g_scheduler->FailWithError(Err(
- Location(),
- "The default build config file did not call set_default_toolchain()",
- "If you don't call this, I can't figure out what toolchain to use\n"
- "for all of this code."));
- } else {
- DCHECK(settings->toolchain_label().is_null());
- settings->set_toolchain_label(default_toolchain_label);
- }
- }
-
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&LoaderImpl::DidLoadBuildConfig, this,
- settings->toolchain_label()));
-}
-
-void LoaderImpl::DidLoadFile() {
- DecrementPendingLoads();
-}
-
-void LoaderImpl::DidLoadBuildConfig(const Label& label) {
- // Do not return early, we must call DecrementPendingLoads() at the bottom.
-
- ToolchainRecordMap::iterator found_toolchain = toolchain_records_.find(label);
- ToolchainRecord* record = nullptr;
- if (found_toolchain == toolchain_records_.end()) {
- // When loading the default build config, we'll insert it into the record
- // map with an empty label since we don't yet know what to call it.
- //
- // In this case, we should have exactly one entry in the map with an empty
- // label. We now need to fix up the naming so it refers to the "real" one.
- CHECK_EQ(1U, toolchain_records_.size());
- ToolchainRecordMap::iterator empty_label = toolchain_records_.find(Label());
- CHECK(empty_label != toolchain_records_.end());
-
- // Fix up the toolchain record.
- std::unique_ptr<ToolchainRecord> moved_record =
- std::move(empty_label->second);
- record = moved_record.get();
- toolchain_records_[label] = std::move(moved_record);
- toolchain_records_.erase(empty_label);
-
- // Save the default toolchain label.
- default_toolchain_label_ = label;
- DCHECK(record->settings.default_toolchain_label().is_null());
- record->settings.set_default_toolchain_label(label);
-
- // The settings object should have the toolchain label already set.
- DCHECK(!record->settings.toolchain_label().is_null());
-
- // Update any stored invocations that refer to the empty toolchain label.
- // This will normally only be one, for the root build file, so brute-force
- // is OK.
- LoadIDSet old_loads;
- invocations_.swap(old_loads);
- for (const auto& load : old_loads) {
- if (load.toolchain_name.is_null()) {
- // Fix up toolchain label
- invocations_.insert(LoadID(load.file, label));
- } else {
- // Can keep the old one.
- invocations_.insert(load);
- }
- }
- } else {
- record = found_toolchain->second.get();
- }
-
- DCHECK(!record->is_config_loaded);
- DCHECK(record->is_toolchain_loaded);
- record->is_config_loaded = true;
-
- // Schedule all waiting file loads.
- for (const auto& waiting : record->waiting_on_me)
- ScheduleLoadFile(&record->settings, waiting.origin, waiting.file);
- record->waiting_on_me.clear();
-
- DecrementPendingLoads();
-}
-
-void LoaderImpl::DecrementPendingLoads() {
- DCHECK_GT(pending_loads_, 0);
- pending_loads_--;
- if (pending_loads_ == 0 && !complete_callback_.is_null())
- complete_callback_.Run();
-}
-
-bool LoaderImpl::AsyncLoadFile(
- const LocationRange& origin,
- const BuildSettings* build_settings,
- const SourceFile& file_name,
- const base::Callback<void(const ParseNode*)>& callback,
- Err* err) {
- if (async_load_file_.is_null()) {
- return g_scheduler->input_file_manager()->AsyncLoadFile(
- origin, build_settings, file_name, callback, err);
- }
- return async_load_file_.Run(origin, build_settings, file_name, callback, err);
-}
diff --git a/chromium/tools/gn/loader.h b/chromium/tools/gn/loader.h
deleted file mode 100644
index 17f7110ed76..00000000000
--- a/chromium/tools/gn/loader.h
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_LOADER_H_
-#define TOOLS_GN_LOADER_H_
-
-#include <map>
-#include <memory>
-#include <set>
-
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "tools/gn/label.h"
-#include "tools/gn/scope.h"
-
-class BuildSettings;
-class LocationRange;
-class Settings;
-class SourceFile;
-class Toolchain;
-
-// The loader manages execution of the different build files. It receives
-// requests (normally from the Builder) when new references are found, and also
-// manages loading the build config files.
-//
-// This loader class is abstract so it can be mocked out for testing the
-// Builder.
-class Loader : public base::RefCountedThreadSafe<Loader> {
- public:
- Loader();
-
- // Loads the given file in the conext of the given toolchain. The initial
- // call to this (the one that actually starts the generation) should have an
- // empty toolchain name, which will trigger the load of the default build
- // config.
- virtual void Load(const SourceFile& file,
- const LocationRange& origin,
- const Label& toolchain_name) = 0;
-
- // Notification that the given toolchain has loaded. This will unblock files
- // waiting on this definition.
- virtual void ToolchainLoaded(const Toolchain* toolchain) = 0;
-
- // Returns the label of the default toolchain.
- virtual Label GetDefaultToolchain() const = 0;
-
- // Returns information about the toolchain with the given label. Will return
- // false if we haven't processed this toolchain yet.
- virtual const Settings* GetToolchainSettings(const Label& label) const = 0;
-
- // Helper function that extracts the file and toolchain name from the given
- // label, and calls Load().
- void Load(const Label& label, const LocationRange& origin);
-
- // Returns the build file that the given label references.
- static SourceFile BuildFileForLabel(const Label& label);
-
- // When processing the default build config, we want to capture the argument
- // of set_default_build_config. The implementation of that function uses this
- // constant as a property key to get the Label* out of the scope where the
- // label should be stored.
- static const void* const kDefaultToolchainKey;
-
- protected:
- friend class base::RefCountedThreadSafe<Loader>;
- virtual ~Loader();
-};
-
-class LoaderImpl : public Loader {
- public:
- // Callback to emulate InputFileManager::AsyncLoadFile.
- typedef base::Callback<bool(const LocationRange&,
- const BuildSettings*,
- const SourceFile&,
- const base::Callback<void(const ParseNode*)>&,
- Err*)> AsyncLoadFileCallback;
-
- explicit LoaderImpl(const BuildSettings* build_settings);
-
- // Loader implementation.
- void Load(const SourceFile& file,
- const LocationRange& origin,
- const Label& toolchain_name) override;
- void ToolchainLoaded(const Toolchain* toolchain) override;
- Label GetDefaultToolchain() const override;
- const Settings* GetToolchainSettings(const Label& label) const override;
-
- // Sets the task runner corresponding to the main thread. By default this
- // class will use the thread active during construction, but there is not
- // a task runner active during construction all the time.
- void set_task_runner(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- task_runner_ = task_runner;
- }
-
- // The complete callback is called whenever there are no more pending loads.
- // Called on the main thread only. This may be called more than once if the
- // queue is drained, but then more stuff gets added.
- void set_complete_callback(const base::Closure& cb) {
- complete_callback_ = cb;
- }
-
- // This callback is used when the loader finds it wants to load a file.
- void set_async_load_file(const AsyncLoadFileCallback& cb) {
- async_load_file_ = cb;
- }
-
- const Label& default_toolchain_label() const {
- return default_toolchain_label_;
- }
-
- private:
- struct LoadID;
- struct ToolchainRecord;
-
- ~LoaderImpl() override;
-
- // Schedules the input file manager to load the given file.
- void ScheduleLoadFile(const Settings* settings,
- const LocationRange& origin,
- const SourceFile& file);
- void ScheduleLoadBuildConfig(
- Settings* settings,
- const Scope::KeyValueMap& toolchain_overrides);
-
- // Runs the given file on the background thread. These are called by the
- // input file manager.
- void BackgroundLoadFile(const Settings* settings,
- const SourceFile& file_name,
- const LocationRange& origin,
- const ParseNode* root);
- void BackgroundLoadBuildConfig(
- Settings* settings,
- const Scope::KeyValueMap& toolchain_overrides,
- const ParseNode* root);
-
- // Posted to the main thread when any file other than a build config file
- // file has completed running.
- void DidLoadFile();
-
- // Posted to the main thread when any build config file has completed
- // running. The label should be the name of the toolchain.
- //
- // If there is no defauled toolchain loaded yet, we'll assume that the first
- // call to this indicates to the default toolchain, and this function will
- // set the default toolchain name to the given label.
- void DidLoadBuildConfig(const Label& label);
-
- // Decrements the pending_loads_ variable and issues the complete callback if
- // necessary.
- void DecrementPendingLoads();
-
- // Forwards to the appropriate location to load the file.
- bool AsyncLoadFile(const LocationRange& origin,
- const BuildSettings* build_settings,
- const SourceFile& file_name,
- const base::Callback<void(const ParseNode*)>& callback,
- Err* err);
-
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- int pending_loads_;
- base::Closure complete_callback_;
-
- // When non-null, use this callback instead of the InputFileManager for
- // mocking purposes.
- AsyncLoadFileCallback async_load_file_;
-
- typedef std::set<LoadID> LoadIDSet;
- LoadIDSet invocations_;
-
- const BuildSettings* build_settings_;
- Label default_toolchain_label_;
-
- // Records for the build config file loads.
- typedef std::map<Label, std::unique_ptr<ToolchainRecord>> ToolchainRecordMap;
- ToolchainRecordMap toolchain_records_;
-};
-
-#endif // TOOLS_GN_LOADER_H_
diff --git a/chromium/tools/gn/loader_unittest.cc b/chromium/tools/gn/loader_unittest.cc
deleted file mode 100644
index e42ee5b7844..00000000000
--- a/chromium/tools/gn/loader_unittest.cc
+++ /dev/null
@@ -1,264 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <map>
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/err.h"
-#include "tools/gn/loader.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/parser.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/test_with_scheduler.h"
-#include "tools/gn/tokenizer.h"
-
-namespace {
-
-bool ItemContainsBuildDependencyFile(const Item* item,
- const SourceFile& source_file) {
- const auto& build_dependency_files = item->build_dependency_files();
- return build_dependency_files.end() !=
- build_dependency_files.find(source_file);
-}
-
-class MockBuilder {
- public:
- void OnItemDefined(std::unique_ptr<Item> item);
- std::vector<const Item*> GetAllItems() const;
-
- private:
- std::vector<std::unique_ptr<Item>> items_;
-};
-
-void MockBuilder::OnItemDefined(std::unique_ptr<Item> item) {
- items_.push_back(std::move(item));
-}
-
-std::vector<const Item*> MockBuilder::GetAllItems() const {
- std::vector<const Item*> result;
- for (const auto& item : items_) {
- result.push_back(item.get());
- }
-
- return result;
-}
-
-class MockInputFileManager {
- public:
- typedef base::Callback<void(const ParseNode*)> Callback;
-
- MockInputFileManager() = default;
-
- LoaderImpl::AsyncLoadFileCallback GetCallback();
-
- // Sets a given response for a given source file.
- void AddCannedResponse(const SourceFile& source_file,
- const std::string& source);
-
- // Returns true if there is/are pending load(s) matching the given file(s).
- bool HasOnePending(const SourceFile& f) const;
- bool HasTwoPending(const SourceFile& f1, const SourceFile& f2) const;
-
- void IssueAllPending();
-
- private:
- struct CannedResult {
- std::unique_ptr<InputFile> input_file;
- std::vector<Token> tokens;
- std::unique_ptr<ParseNode> root;
- };
-
- bool AsyncLoadFile(const LocationRange& origin,
- const BuildSettings* build_settings,
- const SourceFile& file_name,
- const Callback& callback,
- Err* err) {
- pending_.push_back(std::make_pair(file_name, callback));
- return true;
- }
-
- typedef std::map<SourceFile, std::unique_ptr<CannedResult>> CannedResponseMap;
- CannedResponseMap canned_responses_;
-
- std::vector< std::pair<SourceFile, Callback> > pending_;
-};
-
-LoaderImpl::AsyncLoadFileCallback MockInputFileManager::GetCallback() {
- return base::Bind(&MockInputFileManager::AsyncLoadFile,
- base::Unretained(this));
-}
-
-// Sets a given response for a given source file.
-void MockInputFileManager::AddCannedResponse(const SourceFile& source_file,
- const std::string& source) {
- std::unique_ptr<CannedResult> canned = std::make_unique<CannedResult>();
- canned->input_file = std::make_unique<InputFile>(source_file);
- canned->input_file->SetContents(source);
-
- // Tokenize.
- Err err;
- canned->tokens = Tokenizer::Tokenize(canned->input_file.get(), &err);
- EXPECT_FALSE(err.has_error());
-
- // Parse.
- canned->root = Parser::Parse(canned->tokens, &err);
- EXPECT_FALSE(err.has_error());
-
- canned_responses_[source_file] = std::move(canned);
-}
-
-bool MockInputFileManager::HasOnePending(const SourceFile& f) const {
- return pending_.size() == 1u && pending_[0].first == f;
-}
-
-bool MockInputFileManager::HasTwoPending(const SourceFile& f1,
- const SourceFile& f2) const {
- if (pending_.size() != 2u)
- return false;
- return pending_[0].first == f1 && pending_[1].first == f2;
-}
-
-void MockInputFileManager::IssueAllPending() {
- BlockNode block(BlockNode::DISCARDS_RESULT); // Default response.
-
- for (const auto& cur : pending_) {
- CannedResponseMap::const_iterator found = canned_responses_.find(cur.first);
- if (found == canned_responses_.end())
- cur.second.Run(&block);
- else
- cur.second.Run(found->second->root.get());
- }
- pending_.clear();
-}
-
-// LoaderTest ------------------------------------------------------------------
-
-class LoaderTest : public TestWithScheduler {
- public:
- LoaderTest() {
- build_settings_.SetBuildDir(SourceDir("//out/Debug/"));
- }
-
- protected:
- BuildSettings build_settings_;
- MockBuilder mock_builder_;
- MockInputFileManager mock_ifm_;
-};
-
-} // namespace
-
-// -----------------------------------------------------------------------------
-
-TEST_F(LoaderTest, Foo) {
- SourceFile build_config("//build/config/BUILDCONFIG.gn");
- build_settings_.set_build_config_file(build_config);
-
- scoped_refptr<LoaderImpl> loader(new LoaderImpl(&build_settings_));
-
- // The default toolchain needs to be set by the build config file.
- mock_ifm_.AddCannedResponse(build_config,
- "set_default_toolchain(\"//tc:tc\")");
-
- loader->set_async_load_file(mock_ifm_.GetCallback());
-
- // Request the root build file be loaded. This should kick off the default
- // build config loading.
- SourceFile root_build("//BUILD.gn");
- loader->Load(root_build, LocationRange(), Label());
- EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));
-
- // Completing the build config load should kick off the root build file load.
- mock_ifm_.IssueAllPending();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(mock_ifm_.HasOnePending(root_build));
-
- // Load the root build file.
- mock_ifm_.IssueAllPending();
- base::RunLoop().RunUntilIdle();
-
- // Schedule some other file to load in another toolchain.
- Label second_tc(SourceDir("//tc2/"), "tc2");
- SourceFile second_file("//foo/BUILD.gn");
- loader->Load(second_file, LocationRange(), second_tc);
- EXPECT_TRUE(mock_ifm_.HasOnePending(SourceFile("//tc2/BUILD.gn")));
-
- // Running the toolchain file should schedule the build config file to load
- // for that toolchain.
- mock_ifm_.IssueAllPending();
- base::RunLoop().RunUntilIdle();
-
- // We have to tell it we have a toolchain definition now (normally the
- // builder would do this).
- const Settings* default_settings = loader->GetToolchainSettings(Label());
- Toolchain second_tc_object(default_settings, second_tc);
- loader->ToolchainLoaded(&second_tc_object);
- EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));
-
- // Scheduling a second file to load in that toolchain should not make it
- // pending yet (it's waiting for the build config).
- SourceFile third_file("//bar/BUILD.gn");
- loader->Load(third_file, LocationRange(), second_tc);
- EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));
-
- // Running the build config file should make our third file pending.
- mock_ifm_.IssueAllPending();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(mock_ifm_.HasTwoPending(second_file, third_file));
-
- EXPECT_FALSE(scheduler().is_failed());
-}
-
-TEST_F(LoaderTest, BuildDependencyFilesAreCollected) {
- SourceFile build_config("//build/config/BUILDCONFIG.gn");
- SourceFile root_build("//BUILD.gn");
- build_settings_.set_build_config_file(build_config);
- build_settings_.set_item_defined_callback(base::Bind(
- &MockBuilder::OnItemDefined, base::Unretained(&mock_builder_)));
-
- scoped_refptr<LoaderImpl> loader(new LoaderImpl(&build_settings_));
- mock_ifm_.AddCannedResponse(build_config,
- "set_default_toolchain(\"//tc:tc\")");
- mock_ifm_.AddCannedResponse(SourceFile("//test.gni"), "concurrent_jobs = 1");
- std::string root_build_content =
- "executable(\"a\") { sources = [ \"a.cc\" ] }\n"
- "config(\"b\") { configs = [\"//t:t\"] }\n"
- "toolchain(\"c\") {}\n"
- "pool(\"d\") { depth = 1 }";
- mock_ifm_.AddCannedResponse(root_build, root_build_content);
-
- loader->set_async_load_file(mock_ifm_.GetCallback());
-
- // Request the root build file be loaded. This should kick off the default
- // build config loading.
- loader->Load(root_build, LocationRange(), Label());
- EXPECT_TRUE(mock_ifm_.HasOnePending(build_config));
-
- // Completing the build config load should kick off the root build file load.
- mock_ifm_.IssueAllPending();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(mock_ifm_.HasOnePending(root_build));
-
- // Completing the root build file should define a target which must have
- // set of source files hashes.
- mock_ifm_.IssueAllPending();
- base::RunLoop().RunUntilIdle();
-
- std::vector<const Item*> items = mock_builder_.GetAllItems();
- EXPECT_TRUE(items[0]->AsTarget());
- EXPECT_TRUE(ItemContainsBuildDependencyFile(items[0], root_build));
- EXPECT_TRUE(items[1]->AsConfig());
- EXPECT_TRUE(ItemContainsBuildDependencyFile(items[1], root_build));
- EXPECT_TRUE(items[2]->AsToolchain());
- EXPECT_TRUE(ItemContainsBuildDependencyFile(items[2], root_build));
- EXPECT_TRUE(items[3]->AsPool());
- EXPECT_TRUE(ItemContainsBuildDependencyFile(items[3], root_build));
-
- EXPECT_FALSE(scheduler().is_failed());
-}
diff --git a/chromium/tools/gn/location.cc b/chromium/tools/gn/location.cc
deleted file mode 100644
index f3c2d91861e..00000000000
--- a/chromium/tools/gn/location.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/location.h"
-
-#include <tuple>
-
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "tools/gn/input_file.h"
-
-Location::Location()
- : file_(nullptr),
- line_number_(-1),
- column_number_(-1) {
-}
-
-Location::Location(const InputFile* file,
- int line_number,
- int column_number,
- int byte)
- : file_(file),
- line_number_(line_number),
- column_number_(column_number),
- byte_(byte) {
-}
-
-bool Location::operator==(const Location& other) const {
- return other.file_ == file_ &&
- other.line_number_ == line_number_ &&
- other.column_number_ == column_number_;
-}
-
-bool Location::operator!=(const Location& other) const {
- return !operator==(other);
-}
-
-bool Location::operator<(const Location& other) const {
- DCHECK(file_ == other.file_);
- return std::tie(line_number_, column_number_) <
- std::tie(other.line_number_, other.column_number_);
-}
-
-std::string Location::Describe(bool include_column_number) const {
- if (!file_)
- return std::string();
-
- std::string ret;
- if (file_->friendly_name().empty())
- ret = file_->name().value();
- else
- ret = file_->friendly_name();
-
- ret += ":";
- ret += base::IntToString(line_number_);
- if (include_column_number) {
- ret += ":";
- ret += base::IntToString(column_number_);
- }
- return ret;
-}
-
-LocationRange::LocationRange() = default;
-
-LocationRange::LocationRange(const Location& begin, const Location& end)
- : begin_(begin),
- end_(end) {
- DCHECK(begin_.file() == end_.file());
-}
-
-LocationRange LocationRange::Union(const LocationRange& other) const {
- DCHECK(begin_.file() == other.begin_.file());
- return LocationRange(
- begin_ < other.begin_ ? begin_ : other.begin_,
- end_ < other.end_ ? other.end_ : end_);
-}
diff --git a/chromium/tools/gn/location.h b/chromium/tools/gn/location.h
deleted file mode 100644
index 647c6f71227..00000000000
--- a/chromium/tools/gn/location.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_LOCATION_H_
-#define TOOLS_GN_LOCATION_H_
-
-#include <string>
-
-class InputFile;
-
-// Represents a place in a source file. Used for error reporting.
-class Location {
- public:
- Location();
- Location(const InputFile* file, int line_number, int column_number, int byte);
-
- const InputFile* file() const { return file_; }
- int line_number() const { return line_number_; }
- int column_number() const { return column_number_; }
- int byte() const { return byte_; }
- bool is_null() const { return *this == Location(); }
-
- bool operator==(const Location& other) const;
- bool operator!=(const Location& other) const;
- bool operator<(const Location& other) const;
-
- // Returns a string with the file, line, and (optionally) the character
- // offset for this location. If this location is null, returns an empty
- // string.
- std::string Describe(bool include_column_number) const;
-
- private:
- const InputFile* file_; // Null when unset.
- int line_number_; // -1 when unset. 1-based.
- int column_number_; // -1 when unset. 1-based.
- int byte_; // Index into the buffer, 0-based.
-};
-
-// Represents a range in a source file. Used for error reporting.
-// The end is exclusive i.e. [begin, end)
-class LocationRange {
- public:
- LocationRange();
- LocationRange(const Location& begin, const Location& end);
-
- const Location& begin() const { return begin_; }
- const Location& end() const { return end_; }
- bool is_null() const {
- return begin_.is_null(); // No need to check both for the null case.
- }
-
-
- LocationRange Union(const LocationRange& other) const;
-
- private:
- Location begin_;
- Location end_;
-};
-
-#endif // TOOLS_GN_LOCATION_H_
diff --git a/chromium/tools/gn/misc/OWNERS b/chromium/tools/gn/misc/OWNERS
deleted file mode 100644
index 4d2bd881f6b..00000000000
--- a/chromium/tools/gn/misc/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-scottmg@chromium.org
-erg@chromium.org
diff --git a/chromium/tools/gn/misc/emacs/gn-mode.el b/chromium/tools/gn/misc/emacs/gn-mode.el
deleted file mode 100644
index 4474bde3044..00000000000
--- a/chromium/tools/gn/misc/emacs/gn-mode.el
+++ /dev/null
@@ -1,191 +0,0 @@
-;;; gn-mode.el - A major mode for editing gn files.
-
-;; Copyright 2015 The Chromium Authors. All rights reserved.
-;; Use of this source code is governed by a BSD-style license that can be
-;; found in the LICENSE file.
-
-;; Author: Elliot Glaysher <erg@chromium.org>
-;; Created: April 03, 2015
-;; Keywords: tools, gn, ninja, chromium
-
-;; This file is not part of GNU Emacs.
-
-;;; Commentary:
-
-;; A major mode for editing GN files. GN stands for Generate Ninja. GN is the
-;; meta build system used in Chromium. For more information on GN, see the GN
-;; manual: <https://chromium.googlesource.com/chromium/src/+/master/tools/gn/README.md>
-
-;;; To Do:
-
-;; - We syntax highlight builtin actions, but don't highlight instantiations of
-;; templates. Should we?
-
-
-
-(require 'smie)
-
-(defgroup gn nil
- "Major mode for editing Generate Ninja files."
- :prefix "gn-"
- :group 'languages)
-
-(defcustom gn-indent-basic 2
- "The number of spaces to indent a new scope."
- :group 'gn
- :type 'integer)
-
-(defcustom gn-format-command "gn format --stdin"
- "The command to run to format gn files in place."
- :group 'gn
- :type 'string)
-
-(defgroup gn-faces nil
- "Faces used in Generate Ninja mode."
- :group 'gn
- :group 'faces)
-
-(defface gn-embedded-variable
- '((t :inherit font-lock-variable-name-face))
- "Font lock face used to highlight variable names in strings."
- :group 'gn-faces)
-
-(defface gn-embedded-variable-boundary
- '((t :bold t
- :inherit gn-embedded-variable))
- "Font lock face used to highlight the '$' that starts a
-variable name or the '{{' and '}}' which surround it."
- :group 'gn-faces)
-
-(defvar gn-font-lock-reserved-keywords
- '("true" "false" "if" "else"))
-
-(defvar gn-font-lock-target-declaration-keywords
- '("action" "action_foreach" "bundle_data" "copy" "create_bundle" "executable"
- "group" "loadable_module" "shared_library" "source_set" "static_library"
- "target"))
-
-;; pool() is handled specially since it's also a variable name
-(defvar gn-font-lock-buildfile-fun-keywords
- '("assert" "config" "declare_args" "defined" "exec_script" "foreach"
- "forward_variables_from" "get_label_info" "get_path_info"
- "get_target_outputs" "getenv" "import" "not_needed" "print"
- "process_file_template" "read_file" "rebase_path" "set_default_toolchain"
- "set_defaults" "set_sources_assignment_filter" "split_list" "template"
- "tool" "toolchain" "write_file"))
-
-(defvar gn-font-lock-predefined-var-keywords
- '("current_cpu" "current_os" "current_toolchain" "default_toolchain"
- "host_cpu" "host_os" "invoker" "python_path" "root_build_dir" "root_gen_dir"
- "root_out_dir" "target_cpu" "target_gen_dir" "target_name" "target_os"
- "target_out_dir"))
-
-(defvar gn-font-lock-var-keywords
- '("all_dependent_configs" "allow_circular_includes_from" "arflags" "args"
- "asmflags" "assert_no_deps" "bundle_deps_filter" "bundle_executable_dir"
- "bundle_plugins_dir" "bundle_resources_dir" "bundle_root_dir" "cflags"
- "cflags_c" "cflags_cc" "cflags_objc" "cflags_objcc" "check_includes"
- "code_signing_args" "code_signing_outputs" "code_signing_script"
- "code_signing_sources" "complete_static_lib" "configs" "data" "data_deps"
- "defines" "depfile" "deps" "include_dirs" "inputs" "ldflags" "lib_dirs"
- "libs" "output_dir" "output_extension" "output_name"
- "output_prefix_override" "outputs" "pool" "precompiled_header"
- "precompiled_header_type" "precompiled_source" "product_type" "public"
- "public_configs" "public_deps" "response_file_contents" "script" "sources"
- "testonly" "visibility" "write_runtime_deps" "bundle_contents_dir"))
-
-(defconst gn-font-lock-keywords
- `((,(regexp-opt gn-font-lock-reserved-keywords 'words) .
- font-lock-keyword-face)
- (,(regexp-opt gn-font-lock-target-declaration-keywords 'words) .
- font-lock-type-face)
- (,(regexp-opt gn-font-lock-buildfile-fun-keywords 'words) .
- font-lock-function-name-face)
- ;; pool() as a function
- ("\\<\\(pool\\)\\s-*("
- (1 font-lock-function-name-face))
- (,(regexp-opt gn-font-lock-predefined-var-keywords 'words) .
- font-lock-constant-face)
- (,(regexp-opt gn-font-lock-var-keywords 'words) .
- font-lock-variable-name-face)
- ;; $variables_like_this
- ("\\(\\$\\)\\([a-zA-Z0-9_]+\\)"
- (1 'gn-embedded-variable-boundary t)
- (2 'gn-embedded-variable t))
- ;; ${variables_like_this}
- ("\\(\\${\\)\\([^\n }]+\\)\\(}\\)"
- (1 'gn-embedded-variable-boundary t)
- (2 'gn-embedded-variable t)
- (3 'gn-embedded-variable-boundary t))
- ;; {{placeholders}} (see substitute_type.h)
- ("\\({{\\)\\([^\n }]+\\)\\(}}\\)"
- (1 'gn-embedded-variable-boundary t)
- (2 'gn-embedded-variable t)
- (3 'gn-embedded-variable-boundary t))))
-
-(defun gn-smie-rules (kind token)
- "These are slightly modified indentation rules from the SMIE
- Indentation Example info page. This changes the :before rule
- and adds a :list-intro to handle our x = [ ] syntax."
- (pcase (cons kind token)
- (`(:elem . basic) gn-indent-basic)
- (`(,_ . ",") (smie-rule-separator kind))
- (`(:list-intro . "") gn-indent-basic)
- (`(:before . ,(or `"[" `"(" `"{"))
- (if (smie-rule-hanging-p) (smie-rule-parent)))
- (`(:before . "if")
- (and (not (smie-rule-bolp)) (smie-rule-prev-p "else")
- (smie-rule-parent)))))
-
-(defun gn-fill-paragraph (&optional justify)
- "We only fill inside of comments in GN mode."
- (interactive "P")
- (or (fill-comment-paragraph justify)
- ;; Never return nil; `fill-paragraph' will perform its default behavior
- ;; if we do.
- t))
-
-(defun gn-run-format ()
- "Run 'gn format' on the buffer in place."
- (interactive)
- ;; We can't `save-excursion' here; that will put us at the beginning of the
- ;; shell output, aka the beginning of the document.
- (let ((my-start-line (line-number-at-pos)))
- (shell-command-on-region (point-min) (point-max) gn-format-command nil t)
- (goto-line my-start-line)))
-
-(defvar gn-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-c\C-f" 'gn-run-format)
- map))
-
-;;;###autoload
-(define-derived-mode gn-mode prog-mode "GN"
- "Major mode for editing gn (Generate Ninja)."
- :group 'gn
-
- (setq-local comment-use-syntax t)
- (setq-local comment-start "#")
- (setq-local comment-end "")
- (setq-local indent-tabs-mode nil)
-
- (setq-local fill-paragraph-function 'gn-fill-paragraph)
-
- (setq-local font-lock-defaults '(gn-font-lock-keywords))
-
- ;; For every 'rule("name") {', adds "name" to the imenu for quick navigation.
- (setq-local imenu-generic-expression
- '((nil "^\s*[a-zA-Z0-9_]+(\"\\([a-zA-Z0-9_]+\\)\")\s*{" 1)))
-
- (smie-setup nil #'gn-smie-rules)
- (setq-local smie-indent-basic gn-indent-basic)
-
- ;; python style comment: “# …”
- (modify-syntax-entry ?# "< b" gn-mode-syntax-table)
- (modify-syntax-entry ?\n "> b" gn-mode-syntax-table)
- (modify-syntax-entry ?_ "w" gn-mode-syntax-table))
-
-;;;###autoload
-(add-to-list 'auto-mode-alist '("\\.gni?\\'" . gn-mode))
-
-(provide 'gn-mode)
diff --git a/chromium/tools/gn/misc/tm/GN.tmLanguage b/chromium/tools/gn/misc/tm/GN.tmLanguage
deleted file mode 100644
index 6a80a36e5e0..00000000000
--- a/chromium/tools/gn/misc/tm/GN.tmLanguage
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>fileTypes</key>
- <array>
- <string>gn</string>
- <string>gni</string>
- </array>
- <key>name</key>
- <string>GN</string>
- <key>patterns</key>
- <array>
- <dict>
- <key>comment</key>
- <string>keywords</string>
- <key>match</key>
- <string>\b(?:if)\b</string>
- <key>name</key>
- <string>keyword.control.gn</string>
- </dict>
- <dict>
- <key>comment</key>
- <string>constants</string>
- <key>match</key>
- <string>\b(?:true|false)\b</string>
- <key>name</key>
- <string>constant.language.gn</string>
- </dict>
- <dict>
- <key>comment</key>
- <string>numbers</string>
- <key>match</key>
- <string>\b\d+\.?(?:\d+)?\b</string>
- <key>name</key>
- <string>constant.numeric.gn</string>
- </dict>
- <dict>
- <key>comment</key>
- <string>double quoted string</string>
- <key>match</key>
- <string>\"[^\"]*\"</string>
- <key>name</key>
- <string>string.quoted.double.gn</string>
- </dict>
- <dict>
- <key>comment</key>
- <string>comment</string>
- <key>begin</key>
- <string>#</string>
- <key>end</key>
- <string>$</string>
- <key>name</key>
- <string>comment.gn</string>
- </dict>
- <dict>
- <key>comment</key>
- <string>operators</string>
- <key>match</key>
- <string>(?:=|==|\+=|-=|\+|-)</string>
- <key>name</key>
- <string>keyword.operator.gn</string>
- </dict>
- <dict>
- <key>comment</key>
- <string>targets</string>
- <key>match</key>
- <string>\b(?:action|action_foreach|copy|executable|group|loadable_module|shared_library|source_set|static_library)\b</string>
- <key>name</key>
- <string>entity.name.tag.gn</string>
- </dict>
- <dict>
- <key>comment</key>
- <string>functions</string>
- <key>match</key>
- <string>\b(?:assert|config|declare_args|defined|exec_script|foreach|get_label_info|get_path_info|get_target_outputs|getenv|import|print|process_file_template|read_file|rebase_path|set_default_toolchain|set_defaults|set_sources_assignment_filter|template|tool|toolchain|toolchain_args|write_file)\b</string>
- <key>name</key>
- <string>entity.name.function.gn</string>
- </dict>
- <dict>
- <key>comment</key>
- <string>predefined variables</string>
- <key>match</key>
- <string>\b(?:current_cpu|current_os|current_toolchain|default_toolchain|host_cpu|host_os|python_path|root_build_dir|root_gen_dir|root_out_dir|target_cpu|target_gen_dir|target_os|target_out_dir)\b</string>
- <key>name</key>
- <string>variable.parameter.gn</string>
- </dict>
- <dict>
- <key>comment</key>
- <string>target variables</string>
- <key>match</key>
- <string>\b(?:all_dependent_configs|allow_circular_includes_from|args|asmflags|cflags|cflags_c|cflags_cc|cflags_objc|cflags_objcc|check_includes|complete_static_lib|configs|data|data_deps|defines|depfile|deps|include_dirs|inputs|ldflags|lib_dirs|libs|output_extension|output_name|outputs|public|public_configs|public_deps|script|sources|testonly|visibility)\b</string>
- <key>name</key>
- <string>entity.other.attribute-name.gn</string>
- </dict>
- </array>
- <key>scopeName</key>
- <string>source.gn</string>
- <key>uuid</key>
- <string>DE419F8C-EC46-4824-87F3-732BD08694DC</string>
-</dict>
-</plist>
diff --git a/chromium/tools/gn/misc/tm/GN.tmPreferences b/chromium/tools/gn/misc/tm/GN.tmPreferences
deleted file mode 100644
index 2706d51344a..00000000000
--- a/chromium/tools/gn/misc/tm/GN.tmPreferences
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
- <key>name</key>
- <string>Comments</string>
- <key>scope</key>
- <string>source.gn</string>
- <key>settings</key>
- <dict>
- <key>shellVariables</key>
- <array>
- <dict>
- <key>name</key>
- <string>TM_COMMENT_START</string>
- <key>value</key>
- <string># </string>
- </dict>
- </array>
- </dict>
-</dict>
-</plist> \ No newline at end of file
diff --git a/chromium/tools/gn/misc/vim/README.chromium b/chromium/tools/gn/misc/vim/README.chromium
deleted file mode 100644
index 7b73cfc2675..00000000000
--- a/chromium/tools/gn/misc/vim/README.chromium
+++ /dev/null
@@ -1,5 +0,0 @@
-You can use this by adding
-
- set runtimepath+=/path/to/src/tools/gn/misc/vim
-
-to your .vimrc.
diff --git a/chromium/tools/gn/misc/vim/autoload/gn.vim b/chromium/tools/gn/misc/vim/autoload/gn.vim
deleted file mode 100644
index 5573efc0af3..00000000000
--- a/chromium/tools/gn/misc/vim/autoload/gn.vim
+++ /dev/null
@@ -1,26 +0,0 @@
-" Copyright 2017 The Chromium Authors. All rights reserved.
-" Use of this source code is governed by a BSD-style license that can be
-" found in the LICENSE file.
-
-function! gn#TranslateToBuildFile(name) abort
- " Strip '//' prefix
- let l:new_path = substitute(a:name, '\v^//', '', '')
-
- " Strip the build target name (necessary if 'isfname' contains ':')
- let l:new_path = substitute(l:new_path, '\v:.*$', '', '')
-
- " Append 'BUILD.gn', only if this is a directory and not a file
- " Prefer using maktaba if it's available, but fallback to an alternative
- if exists('*maktaba#path#Basename')
- " Check if the last part of the path appears to be a file
- if maktaba#path#Basename(l:new_path) !~# '\V.'
- let l:new_path = maktaba#path#Join([l:new_path, 'BUILD.gn'])
- endif
- else
- " This will break if 'autochdir' is enabled
- if isdirectory(l:new_path)
- let l:new_path = substitute(l:new_path, '\v/?$', '/BUILD.gn', '')
- endif
- endif
- return l:new_path
-endfunction
diff --git a/chromium/tools/gn/misc/vim/ftdetect/gnfiletype.vim b/chromium/tools/gn/misc/vim/ftdetect/gnfiletype.vim
deleted file mode 100644
index 20448c15b11..00000000000
--- a/chromium/tools/gn/misc/vim/ftdetect/gnfiletype.vim
+++ /dev/null
@@ -1,27 +0,0 @@
-" Copyright 2014 The Chromium Authors. All rights reserved.
-" Use of this source code is governed by a BSD-style license that can be
-" found in the LICENSE file.
-
-" We take care to preserve the user's fileencodings and fileformats,
-" because those settings are global (not buffer local), yet we want
-" to override them for loading GN files, which should be UTF-8.
-let s:current_fileformats = ''
-let s:current_fileencodings = ''
-
-" define fileencodings to open as utf-8 encoding even if it's ascii.
-function! s:gnfiletype_pre()
- let s:current_fileformats = &g:fileformats
- let s:current_fileencodings = &g:fileencodings
- set fileencodings=utf-8 fileformats=unix
- setlocal filetype=gn
-endfunction
-
-" restore fileencodings as others
-function! s:gnfiletype_post()
- let &g:fileformats = s:current_fileformats
- let &g:fileencodings = s:current_fileencodings
-endfunction
-
-au BufNewFile *.gn,*.gni setlocal filetype=gn fileencoding=utf-8 fileformat=unix
-au BufRead *.gn,*.gni call s:gnfiletype_pre()
-au BufReadPost *.gn,*.gni call s:gnfiletype_post()
diff --git a/chromium/tools/gn/misc/vim/ftplugin/gn.vim b/chromium/tools/gn/misc/vim/ftplugin/gn.vim
deleted file mode 100644
index ede251dfe99..00000000000
--- a/chromium/tools/gn/misc/vim/ftplugin/gn.vim
+++ /dev/null
@@ -1,12 +0,0 @@
-" Copyright 2017 The Chromium Authors. All rights reserved.
-" Use of this source code is governed by a BSD-style license that can be
-" found in the LICENSE file.
-
-if exists('b:did_ftplugin')
- finish
-endif
-let b:did_ftplugin = 1
-
-setlocal includeexpr=gn#TranslateToBuildFile(v:fname)
-
-setlocal commentstring=#\ %s
diff --git a/chromium/tools/gn/misc/vim/syntax/gn.vim b/chromium/tools/gn/misc/vim/syntax/gn.vim
deleted file mode 100644
index 0fbd6e016b8..00000000000
--- a/chromium/tools/gn/misc/vim/syntax/gn.vim
+++ /dev/null
@@ -1,84 +0,0 @@
-" Copyright 2014 The Chromium Authors. All rights reserved.
-" Use of this source code is governed by a BSD-style license that can be
-" found in the LICENSE file.
-"
-" gn.vim: Vim syntax file for GN.
-"
-" Quit when a (custom) syntax file was already loaded
-"if exists("b:current_syntax")
- "finish
-"endif
-
-syn case match
-
-" Keywords within functions
-syn keyword gnConditional if else
-hi def link gnConditional Conditional
-
-" Predefined variables
-syn keyword gnPredefVar current_cpu current_os current_toolchain
-syn keyword gnPredefVar default_toolchain host_cpu host_os
-syn keyword gnPredefVar root_build_dir root_gen_dir root_out_dir
-syn keyword gnPredefVar target_cpu target_gen_dir target_out_dir
-syn keyword gnPredefVar target_os
-syn keyword gnPredefVar true false
-hi def link gnPredefVar Constant
-
-" Target declarations
-syn keyword gnTarget action action_foreach copy executable group
-syn keyword gnTarget shared_library source_set static_library
-syn keyword gnTarget loadable_module
-hi def link gnTarget Type
-
-" Buildfile functions
-syn keyword gnFunctions assert config declare_args defined exec_script
-syn keyword gnFunctions foreach get_label_info get_path_info
-syn keyword gnFunctions get_target_outputs getenv import print
-syn keyword gnFunctions process_file_template read_file rebase_path
-syn keyword gnFunctions set_default_toolchain set_defaults
-syn keyword gnFunctions set_sources_assignment_filter template tool
-syn keyword gnFunctions toolchain toolchain_args write_file
-hi def link gnFunctions Macro
-
-" Variables
-syn keyword gnVariable all_dependent_configs allow_circular_includes_from
-syn keyword gnVariable args asmflags cflags cflags_c cflags_cc cflags_objc
-syn keyword gnVariable cflags_objcc check_includes complete_static_lib
-syn keyword gnVariable configs data data_deps defines depfile deps
-syn keyword gnVariable include_dirs inputs ldflags lib_dirs libs
-syn keyword gnVariable output_extension output_name outputs public
-syn keyword gnVariable public_configs public_deps scripte sources testonly
-syn keyword gnVariable visibility
-hi def link gnVariable Keyword
-
-" Strings
-syn region gnString start=+L\="+ skip=+\\\\\|\\"+ end=+"+ contains=@Spell,gnTargetName
-syn match gnTargetName '\v:[^"]+' contained
-hi def link gnString String
-hi def link gnTargetName Special
-
-" Comments
-syn keyword gnTodo contained TODO FIXME XXX BUG NOTE
-syn cluster gnCommentGroup contains=gnTodo
-syn region gnComment start="#" end="$" contains=@gnCommentGroup,@Spell
-
-hi def link gnComment Comment
-hi def link gnTodo Todo
-
-" Operators; I think this is a bit too colourful.
-"syn match gnOperator /=/
-"syn match gnOperator /!=/
-"syn match gnOperator />=/
-"syn match gnOperator /<=/
-"syn match gnOperator /==/
-"syn match gnOperator /+=/
-"syn match gnOperator /-=/
-"syn match gnOperator /\s>\s/
-"syn match gnOperator /\s<\s/
-"syn match gnOperator /\s+\s/
-"syn match gnOperator /\s-\s/
-"hi def link gnOperator Operator
-
-syn sync minlines=500
-
-let b:current_syntax = "gn"
diff --git a/chromium/tools/gn/ninja_action_target_writer.cc b/chromium/tools/gn/ninja_action_target_writer.cc
deleted file mode 100644
index 263cf23821f..00000000000
--- a/chromium/tools/gn/ninja_action_target_writer.cc
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/ninja_action_target_writer.h"
-
-#include <stddef.h>
-
-#include "base/strings/string_util.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/err.h"
-#include "tools/gn/pool.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/string_utils.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/target.h"
-
-NinjaActionTargetWriter::NinjaActionTargetWriter(const Target* target,
- std::ostream& out)
- : NinjaTargetWriter(target, out),
- path_output_no_escaping_(
- target->settings()->build_settings()->build_dir(),
- target->settings()->build_settings()->root_path_utf8(),
- ESCAPE_NONE) {
-}
-
-NinjaActionTargetWriter::~NinjaActionTargetWriter() = default;
-
-void NinjaActionTargetWriter::Run() {
- std::string custom_rule_name = WriteRuleDefinition();
-
- // Collect our deps to pass as "extra hard dependencies" for input deps. This
- // will force all of the action's dependencies to be completed before the
- // action is run. Usually, if an action has a dependency, it will be
- // operating on the result of that previous step, so we need to be sure to
- // serialize these.
- std::vector<const Target*> extra_hard_deps;
- for (const auto& pair : target_->GetDeps(Target::DEPS_LINKED))
- extra_hard_deps.push_back(pair.ptr);
-
- // For ACTIONs, the input deps appear only once in the generated ninja
- // file, so WriteInputDepsStampAndGetDep() won't create a stamp file
- // and the action will just depend on all the input deps directly.
- size_t num_stamp_uses =
- target_->output_type() == Target::ACTION ? 1u : target_->sources().size();
- std::vector<OutputFile> input_deps =
- WriteInputDepsStampAndGetDep(extra_hard_deps, num_stamp_uses);
- out_ << std::endl;
-
- // Collects all output files for writing below.
- std::vector<OutputFile> output_files;
-
- if (target_->output_type() == Target::ACTION_FOREACH) {
- // Write separate build lines for each input source file.
- WriteSourceRules(custom_rule_name, input_deps, &output_files);
- } else {
- DCHECK(target_->output_type() == Target::ACTION);
-
- // Write a rule that invokes the script once with the outputs as outputs,
- // and the data as inputs. It does not depend on the sources.
- out_ << "build";
- SubstitutionWriter::GetListAsOutputFiles(
- settings_, target_->action_values().outputs(), &output_files);
- path_output_.WriteFiles(out_, output_files);
-
- out_ << ": " << custom_rule_name;
- if (!input_deps.empty()) {
- // As in WriteSourceRules, we want to force this target to rebuild any
- // time any of its dependencies change.
- out_ << " |";
- path_output_.WriteFiles(out_, input_deps);
- }
- out_ << std::endl;
- if (target_->action_values().has_depfile()) {
- out_ << " depfile = ";
- WriteDepfile(SourceFile());
- out_ << std::endl;
- }
- if (target_->action_values().pool().ptr) {
- out_ << " pool = ";
- out_ << target_->action_values().pool().ptr->GetNinjaName(
- settings_->default_toolchain_label());
- out_ << std::endl;
- }
- }
- out_ << std::endl;
-
- // Write the stamp, which also depends on all data deps. These are needed at
- // runtime and should be compiled when the action is, but don't need to be
- // done before we run the action.
- // TODO(thakis): If the action has just a single output, make things depend
- // on that output directly without writing a stamp file.
- std::vector<OutputFile> data_outs;
- for (const auto& dep : target_->data_deps())
- data_outs.push_back(dep.ptr->dependency_output_file());
- WriteStampForTarget(output_files, data_outs);
-}
-
-std::string NinjaActionTargetWriter::WriteRuleDefinition() {
- // Make a unique name for this rule.
- //
- // Use a unique name for the response file when there are multiple build
- // steps so that they don't stomp on each other. When there are no sources,
- // there will be only one invocation so we can use a simple name.
- std::string target_label = target_->label().GetUserVisibleName(true);
- std::string custom_rule_name(target_label);
- base::ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name);
- custom_rule_name.append("_rule");
-
- const SubstitutionList& args = target_->action_values().args();
- EscapeOptions args_escape_options;
- args_escape_options.mode = ESCAPE_NINJA_COMMAND;
-
- out_ << "rule " << custom_rule_name << std::endl;
-
- if (target_->action_values().uses_rsp_file()) {
- // Needs a response file. The unique_name part is for action_foreach so
- // each invocation of the rule gets a different response file. This isn't
- // strictly necessary for regular one-shot actions, but it's easier to
- // just always define unique_name.
- std::string rspfile = custom_rule_name;
- if (!target_->sources().empty())
- rspfile += ".$unique_name";
- rspfile += ".rsp";
- out_ << " rspfile = " << rspfile << std::endl;
-
- // Response file contents.
- out_ << " rspfile_content =";
- for (const auto& arg :
- target_->action_values().rsp_file_contents().list()) {
- out_ << " ";
- SubstitutionWriter::WriteWithNinjaVariables(
- arg, args_escape_options, out_);
- }
- out_ << std::endl;
- }
-
- out_ << " command = ";
- path_output_.WriteFile(out_, settings_->build_settings()->python_path());
- out_ << " ";
- path_output_.WriteFile(out_, target_->action_values().script());
- for (const auto& arg : args.list()) {
- out_ << " ";
- SubstitutionWriter::WriteWithNinjaVariables(
- arg, args_escape_options, out_);
- }
- out_ << std::endl;
- out_ << " description = ACTION " << target_label << std::endl;
- out_ << " restat = 1" << std::endl;
- const Tool* tool = target_->toolchain()->GetTool(Toolchain::TYPE_ACTION);
- if (tool && tool->pool().ptr) {
- out_ << " pool = ";
- out_ << tool->pool().ptr->GetNinjaName(
- settings_->default_toolchain_label());
- out_ << std::endl;
- }
-
- return custom_rule_name;
-}
-
-void NinjaActionTargetWriter::WriteSourceRules(
- const std::string& custom_rule_name,
- const std::vector<OutputFile>& input_deps,
- std::vector<OutputFile>* output_files) {
- EscapeOptions args_escape_options;
- args_escape_options.mode = ESCAPE_NINJA_COMMAND;
- // We're writing the substitution values, these should not be quoted since
- // they will get pasted into the real command line.
- args_escape_options.inhibit_quoting = true;
-
- const Target::FileList& sources = target_->sources();
- for (size_t i = 0; i < sources.size(); i++) {
- out_ << "build";
- WriteOutputFilesForBuildLine(sources[i], output_files);
-
- out_ << ": " << custom_rule_name << " ";
- path_output_.WriteFile(out_, sources[i]);
- if (!input_deps.empty()) {
- // Using "|" for the dependencies forces all implicit dependencies to be
- // fully up to date before running the action, and will re-run this
- // action if any input dependencies change. This is important because
- // this action may consume the outputs of previous steps.
- out_ << " |";
- path_output_.WriteFiles(out_, input_deps);
- }
- out_ << std::endl;
-
- // Response files require a unique name be defined.
- if (target_->action_values().uses_rsp_file())
- out_ << " unique_name = " << i << std::endl;
-
- // The required types is the union of the args and response file. This
- // might theoretically duplicate a definition if the same substitution is
- // used in both the args and the response file. However, this should be
- // very unusual (normally the substitutions will go in one place or the
- // other) and the redundant assignment won't bother Ninja.
- SubstitutionWriter::WriteNinjaVariablesForSource(
- target_, settings_, sources[i],
- target_->action_values().args().required_types(),
- args_escape_options, out_);
- SubstitutionWriter::WriteNinjaVariablesForSource(
- target_, settings_, sources[i],
- target_->action_values().rsp_file_contents().required_types(),
- args_escape_options, out_);
-
- if (target_->action_values().has_depfile()) {
- out_ << " depfile = ";
- WriteDepfile(sources[i]);
- out_ << std::endl;
- }
- if (target_->action_values().pool().ptr) {
- out_ << " pool = ";
- out_ << target_->action_values().pool().ptr->GetNinjaName(
- settings_->default_toolchain_label());
- out_ << std::endl;
- }
- }
-}
-
-void NinjaActionTargetWriter::WriteOutputFilesForBuildLine(
- const SourceFile& source,
- std::vector<OutputFile>* output_files) {
- size_t first_output_index = output_files->size();
-
- SubstitutionWriter::ApplyListToSourceAsOutputFile(
- target_, settings_, target_->action_values().outputs(), source,
- output_files);
-
- for (size_t i = first_output_index; i < output_files->size(); i++) {
- out_ << " ";
- path_output_.WriteFile(out_, (*output_files)[i]);
- }
-}
-
-void NinjaActionTargetWriter::WriteDepfile(const SourceFile& source) {
- path_output_.WriteFile(out_,
- SubstitutionWriter::ApplyPatternToSourceAsOutputFile(
- target_, settings_, target_->action_values().depfile(), source));
-}
diff --git a/chromium/tools/gn/ninja_action_target_writer.h b/chromium/tools/gn/ninja_action_target_writer.h
deleted file mode 100644
index d0010f95787..00000000000
--- a/chromium/tools/gn/ninja_action_target_writer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_NINJA_ACTION_TARGET_WRITER_H_
-#define TOOLS_GN_NINJA_ACTION_TARGET_WRITER_H_
-
-#include <vector>
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "tools/gn/ninja_target_writer.h"
-
-class OutputFile;
-
-// Writes a .ninja file for a action target type.
-class NinjaActionTargetWriter : public NinjaTargetWriter {
- public:
- NinjaActionTargetWriter(const Target* target, std::ostream& out);
- ~NinjaActionTargetWriter() override;
-
- void Run() override;
-
- private:
- FRIEND_TEST_ALL_PREFIXES(NinjaActionTargetWriter,
- WriteOutputFilesForBuildLine);
- FRIEND_TEST_ALL_PREFIXES(NinjaActionTargetWriter,
- WriteOutputFilesForBuildLineWithDepfile);
- FRIEND_TEST_ALL_PREFIXES(NinjaActionTargetWriter,
- WriteArgsSubstitutions);
-
- // Writes the Ninja rule for invoking the script.
- //
- // Returns the name of the custom rule generated. This will be based on the
- // target name, and will include the string "$unique_name" if there are
- // multiple inputs.
- std::string WriteRuleDefinition();
-
- // Writes the rules for compiling each source, writing all output files
- // to the given vector.
- //
- // input_deps are the dependencies common to all build steps.
- void WriteSourceRules(const std::string& custom_rule_name,
- const std::vector<OutputFile>& input_deps,
- std::vector<OutputFile>* output_files);
-
- // Writes the output files generated by the output template for the given
- // source file. This will start with a space and will not include a newline.
- // Appends the output files to the given vector.
- void WriteOutputFilesForBuildLine(const SourceFile& source,
- std::vector<OutputFile>* output_files);
-
- void WriteDepfile(const SourceFile& source);
-
- // Path output writer that doesn't do any escaping or quoting. It does,
- // however, convert slashes. Used for
- // computing intermediate strings.
- PathOutput path_output_no_escaping_;
-
- DISALLOW_COPY_AND_ASSIGN(NinjaActionTargetWriter);
-};
-
-#endif // TOOLS_GN_NINJA_ACTION_TARGET_WRITER_H_
diff --git a/chromium/tools/gn/ninja_action_target_writer_unittest.cc b/chromium/tools/gn/ninja_action_target_writer_unittest.cc
deleted file mode 100644
index 445a31a3337..00000000000
--- a/chromium/tools/gn/ninja_action_target_writer_unittest.cc
+++ /dev/null
@@ -1,485 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <sstream>
-
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/ninja_action_target_writer.h"
-#include "tools/gn/pool.h"
-#include "tools/gn/substitution_list.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scope.h"
-
-TEST(NinjaActionTargetWriter, WriteOutputFilesForBuildLine) {
- Err err;
- TestWithScope setup;
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::ACTION_FOREACH);
- target.action_values().outputs() = SubstitutionList::MakeForTest(
- "//out/Debug/gen/a b{{source_name_part}}.h",
- "//out/Debug/gen/{{source_name_part}}.cc");
-
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaActionTargetWriter writer(&target, out);
-
- SourceFile source("//foo/bar.in");
- std::vector<OutputFile> output_files;
- writer.WriteOutputFilesForBuildLine(source, &output_files);
-
- EXPECT_EQ(" gen/a$ bbar.h gen/bar.cc", out.str());
-}
-
-// Tests an action with no sources.
-TEST(NinjaActionTargetWriter, ActionNoSources) {
- Err err;
- TestWithScope setup;
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::ACTION);
-
- target.action_values().set_script(SourceFile("//foo/script.py"));
- target.config_values().inputs().push_back(SourceFile("//foo/included.txt"));
-
- target.action_values().outputs() =
- SubstitutionList::MakeForTest("//out/Debug/foo.out");
-
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
- "/usr/bin/python")));
-
- std::ostringstream out;
- NinjaActionTargetWriter writer(&target, out);
- writer.Run();
-
- const char* expected = 1 /* skip initial newline */ + R"(
-rule __foo_bar___rule
- command = /usr/bin/python ../../foo/script.py
- description = ACTION //foo:bar()
- restat = 1
-
-build foo.out: __foo_bar___rule | ../../foo/script.py ../../foo/included.txt
-
-build obj/foo/bar.stamp: stamp foo.out
-)";
- EXPECT_EQ(expected, out.str());
-}
-
-
-// Tests an action with no sources and pool
-TEST(NinjaActionTargetWriter, ActionNoSourcesConsole) {
- Err err;
- TestWithScope setup;
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::ACTION);
-
- target.action_values().set_script(SourceFile("//foo/script.py"));
- target.config_values().inputs().push_back(SourceFile("//foo/included.txt"));
-
- target.action_values().outputs() =
- SubstitutionList::MakeForTest("//out/Debug/foo.out");
-
- Pool pool(setup.settings(),
- Label(SourceDir("//"), "console", setup.toolchain()->label().dir(),
- setup.toolchain()->label().name()));
- pool.set_depth(1);
- target.action_values().set_pool(LabelPtrPair<Pool>(&pool));
-
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
- "/usr/bin/python")));
-
- std::ostringstream out;
- NinjaActionTargetWriter writer(&target, out);
- writer.Run();
-
- // The console pool's name must be mapped exactly to the string "console"
- // which is a special pre-defined pool name in ninja.
- const char* expected = 1 /* skip initial newline */ + R"(
-rule __foo_bar___rule
- command = /usr/bin/python ../../foo/script.py
- description = ACTION //foo:bar()
- restat = 1
-
-build foo.out: __foo_bar___rule | ../../foo/script.py ../../foo/included.txt
- pool = console
-
-build obj/foo/bar.stamp: stamp foo.out
-)";
- EXPECT_EQ(expected, out.str());
-}
-
-// Makes sure that we write sources as input dependencies for actions with
-// both sources and inputs (ACTION_FOREACH treats the sources differently).
-TEST(NinjaActionTargetWriter, ActionWithSources) {
- Err err;
- TestWithScope setup;
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::ACTION);
-
- target.action_values().set_script(SourceFile("//foo/script.py"));
-
- target.sources().push_back(SourceFile("//foo/source.txt"));
- target.config_values().inputs().push_back(SourceFile("//foo/included.txt"));
-
- target.action_values().outputs() =
- SubstitutionList::MakeForTest("//out/Debug/foo.out");
-
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
- "/usr/bin/python")));
-
- std::ostringstream out;
- NinjaActionTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected_linux[] =
- "rule __foo_bar___rule\n"
- " command = /usr/bin/python ../../foo/script.py\n"
- " description = ACTION //foo:bar()\n"
- " restat = 1\n"
- "\n"
- "build foo.out: __foo_bar___rule | ../../foo/script.py "
- "../../foo/included.txt ../../foo/source.txt\n"
- "\n"
- "build obj/foo/bar.stamp: stamp foo.out\n";
- EXPECT_EQ(expected_linux, out.str());
-}
-
-TEST(NinjaActionTargetWriter, ForEach) {
- Err err;
- TestWithScope setup;
-
- // Some dependencies that the action can depend on. Use actions for these
- // so they have a nice platform-independent stamp file that can appear in the
- // output (rather than having to worry about how the current platform names
- // binaries).
- Target dep(setup.settings(), Label(SourceDir("//foo/"), "dep"));
- dep.set_output_type(Target::ACTION);
- dep.visibility().SetPublic();
- dep.SetToolchain(setup.toolchain());
- ASSERT_TRUE(dep.OnResolved(&err));
-
- Target datadep(setup.settings(), Label(SourceDir("//foo/"), "datadep"));
- datadep.set_output_type(Target::ACTION);
- datadep.visibility().SetPublic();
- datadep.SetToolchain(setup.toolchain());
- ASSERT_TRUE(datadep.OnResolved(&err));
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::ACTION_FOREACH);
- target.private_deps().push_back(LabelTargetPair(&dep));
- target.data_deps().push_back(LabelTargetPair(&datadep));
-
- target.sources().push_back(SourceFile("//foo/input1.txt"));
- target.sources().push_back(SourceFile("//foo/input2.txt"));
-
- target.action_values().set_script(SourceFile("//foo/script.py"));
-
- target.action_values().args() = SubstitutionList::MakeForTest(
- "-i",
- "{{source}}",
- "--out=foo bar{{source_name_part}}.o");
- target.action_values().outputs() = SubstitutionList::MakeForTest(
- "//out/Debug/{{source_name_part}}.out");
-
- target.config_values().inputs().push_back(SourceFile("//foo/included.txt"));
-
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
- "/usr/bin/python")));
-
- std::ostringstream out;
- NinjaActionTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected_linux[] =
- "rule __foo_bar___rule\n"
- " command = /usr/bin/python ../../foo/script.py -i ${in} "
- // Escaping is different between Windows and Posix.
-#if defined(OS_WIN)
- "\"--out=foo$ bar${source_name_part}.o\"\n"
-#else
- "--out=foo\\$ bar${source_name_part}.o\n"
-#endif
- " description = ACTION //foo:bar()\n"
- " restat = 1\n"
- "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
- "../../foo/included.txt obj/foo/dep.stamp\n"
- "\n"
- "build input1.out: __foo_bar___rule ../../foo/input1.txt | "
- "obj/foo/bar.inputdeps.stamp\n"
- " source_name_part = input1\n"
- "build input2.out: __foo_bar___rule ../../foo/input2.txt | "
- "obj/foo/bar.inputdeps.stamp\n"
- " source_name_part = input2\n"
- "\n"
- "build obj/foo/bar.stamp: "
- "stamp input1.out input2.out || obj/foo/datadep.stamp\n";
-
- std::string out_str = out.str();
-#if defined(OS_WIN)
- std::replace(out_str.begin(), out_str.end(), '\\', '/');
-#endif
- EXPECT_EQ(expected_linux, out_str);
-}
-
-TEST(NinjaActionTargetWriter, ForEachWithDepfile) {
- Err err;
- TestWithScope setup;
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::ACTION_FOREACH);
-
- target.sources().push_back(SourceFile("//foo/input1.txt"));
- target.sources().push_back(SourceFile("//foo/input2.txt"));
-
- target.action_values().set_script(SourceFile("//foo/script.py"));
-
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- SubstitutionPattern depfile;
- ASSERT_TRUE(
- depfile.Parse("//out/Debug/gen/{{source_name_part}}.d", nullptr, &err));
- target.action_values().set_depfile(depfile);
-
- target.action_values().args() = SubstitutionList::MakeForTest(
- "-i",
- "{{source}}",
- "--out=foo bar{{source_name_part}}.o");
- target.action_values().outputs() = SubstitutionList::MakeForTest(
- "//out/Debug/{{source_name_part}}.out");
-
- target.config_values().inputs().push_back(SourceFile("//foo/included.txt"));
-
- setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
- "/usr/bin/python")));
-
- std::ostringstream out;
- NinjaActionTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected_linux[] =
- "rule __foo_bar___rule\n"
- " command = /usr/bin/python ../../foo/script.py -i ${in} "
-#if defined(OS_WIN)
- "\"--out=foo$ bar${source_name_part}.o\"\n"
-#else
- "--out=foo\\$ bar${source_name_part}.o\n"
-#endif
- " description = ACTION //foo:bar()\n"
- " restat = 1\n"
- "build obj/foo/bar.inputdeps.stamp: stamp ../../foo/script.py "
- "../../foo/included.txt\n"
- "\n"
- "build input1.out: __foo_bar___rule ../../foo/input1.txt"
- " | obj/foo/bar.inputdeps.stamp\n"
- " source_name_part = input1\n"
- " depfile = gen/input1.d\n"
- "build input2.out: __foo_bar___rule ../../foo/input2.txt"
- " | obj/foo/bar.inputdeps.stamp\n"
- " source_name_part = input2\n"
- " depfile = gen/input2.d\n"
- "\n"
- "build obj/foo/bar.stamp: stamp input1.out input2.out\n";
- EXPECT_EQ(expected_linux, out.str());
-}
-
-TEST(NinjaActionTargetWriter, ForEachWithResponseFile) {
- Err err;
- TestWithScope setup;
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::ACTION_FOREACH);
-
- target.sources().push_back(SourceFile("//foo/input1.txt"));
- target.action_values().set_script(SourceFile("//foo/script.py"));
-
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- // Make sure we get interesting substitutions for both the args and the
- // response file contents.
- target.action_values().args() = SubstitutionList::MakeForTest(
- "{{source}}",
- "{{source_file_part}}",
- "{{response_file_name}}");
- target.action_values().rsp_file_contents() = SubstitutionList::MakeForTest(
- "-j",
- "{{source_name_part}}");
- target.action_values().outputs() = SubstitutionList::MakeForTest(
- "//out/Debug/{{source_name_part}}.out");
-
- setup.build_settings()->set_python_path(base::FilePath(FILE_PATH_LITERAL(
- "/usr/bin/python")));
-
- std::ostringstream out;
- NinjaActionTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected_linux[] =
- "rule __foo_bar___rule\n"
- // This name is autogenerated from the target rule name.
- " rspfile = __foo_bar___rule.$unique_name.rsp\n"
- // These come from rsp_file_contents above.
- " rspfile_content = -j ${source_name_part}\n"
- // These come from the args.
- " command = /usr/bin/python ../../foo/script.py ${in} "
- "${source_file_part} ${rspfile}\n"
- " description = ACTION //foo:bar()\n"
- " restat = 1\n"
- "\n"
- "build input1.out: __foo_bar___rule ../../foo/input1.txt"
- " | ../../foo/script.py\n"
- // Necessary for the rspfile defined in the rule.
- " unique_name = 0\n"
- // Substitution for the args.
- " source_file_part = input1.txt\n"
- // Substitution for the rspfile contents.
- " source_name_part = input1\n"
- "\n"
- "build obj/foo/bar.stamp: stamp input1.out\n";
- EXPECT_EQ(expected_linux, out.str());
-}
-
-TEST(NinjaActionTargetWriter, ForEachWithPool) {
- Err err;
- TestWithScope setup;
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::ACTION_FOREACH);
-
- target.sources().push_back(SourceFile("//foo/input1.txt"));
- target.action_values().set_script(SourceFile("//foo/script.py"));
-
- Pool pool(setup.settings(),
- Label(SourceDir("//foo/"), "pool", setup.toolchain()->label().dir(),
- setup.toolchain()->label().name()));
- pool.set_depth(5);
- target.action_values().set_pool(LabelPtrPair<Pool>(&pool));
-
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- // Make sure we get interesting substitutions for both the args and the
- // response file contents.
- target.action_values().args() =
- SubstitutionList::MakeForTest("{{source}}", "{{source_file_part}}");
- target.action_values().outputs() =
- SubstitutionList::MakeForTest("//out/Debug/{{source_name_part}}.out");
-
- setup.build_settings()->set_python_path(
- base::FilePath(FILE_PATH_LITERAL("/usr/bin/python")));
-
- std::ostringstream out;
- NinjaActionTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected_linux[] =
- "rule __foo_bar___rule\n"
- // These come from the args.
- " command = /usr/bin/python ../../foo/script.py ${in} "
- "${source_file_part}\n"
- " description = ACTION //foo:bar()\n"
- " restat = 1\n"
- "\n"
- "build input1.out: __foo_bar___rule ../../foo/input1.txt"
- " | ../../foo/script.py\n"
- // Substitution for the args.
- " source_file_part = input1.txt\n"
- " pool = foo_pool\n"
- "\n"
- "build obj/foo/bar.stamp: stamp input1.out\n";
- EXPECT_EQ(expected_linux, out.str());
-}
-
-TEST(NinjaActionTargetWriter, NoTransitiveHardDeps) {
- Err err;
- TestWithScope setup;
-
- setup.build_settings()->set_python_path(
- base::FilePath(FILE_PATH_LITERAL("/usr/bin/python")));
-
- Target dep(setup.settings(), Label(SourceDir("//foo/"), "dep"));
- dep.set_output_type(Target::ACTION);
- dep.visibility().SetPublic();
- dep.SetToolchain(setup.toolchain());
- ASSERT_TRUE(dep.OnResolved(&err));
-
- Target foo(setup.settings(), Label(SourceDir("//foo/"), "foo"));
- foo.set_output_type(Target::ACTION);
- foo.visibility().SetPublic();
- foo.sources().push_back(SourceFile("//foo/input1.txt"));
- foo.action_values().set_script(SourceFile("//foo/script.py"));
- foo.private_deps().push_back(LabelTargetPair(&dep));
- foo.SetToolchain(setup.toolchain());
- foo.action_values().outputs() =
- SubstitutionList::MakeForTest("//out/Debug/foo.out");
- ASSERT_TRUE(foo.OnResolved(&err));
-
- {
- std::ostringstream out;
- NinjaActionTargetWriter writer(&foo, out);
- writer.Run();
-
- const char expected_linux[] =
- "rule __foo_foo___rule\n"
- // These come from the args.
- " command = /usr/bin/python ../../foo/script.py\n"
- " description = ACTION //foo:foo()\n"
- " restat = 1\n"
- "\n"
- "build foo.out: __foo_foo___rule | ../../foo/script.py"
- " ../../foo/input1.txt obj/foo/dep.stamp\n"
- "\n"
- "build obj/foo/foo.stamp: stamp foo.out\n";
- EXPECT_EQ(expected_linux, out.str());
- }
-
- Target bar(setup.settings(), Label(SourceDir("//bar/"), "bar"));
- bar.set_output_type(Target::ACTION);
- bar.sources().push_back(SourceFile("//bar/input1.txt"));
- bar.action_values().set_script(SourceFile("//bar/script.py"));
- bar.private_deps().push_back(LabelTargetPair(&foo));
- bar.SetToolchain(setup.toolchain());
- bar.action_values().outputs() =
- SubstitutionList::MakeForTest("//out/Debug/bar.out");
- ASSERT_TRUE(bar.OnResolved(&err)) << err.message();
-
- {
- std::ostringstream out;
- NinjaActionTargetWriter writer(&bar, out);
- writer.Run();
-
- const char expected_linux[] =
- "rule __bar_bar___rule\n"
- // These come from the args.
- " command = /usr/bin/python ../../bar/script.py\n"
- " description = ACTION //bar:bar()\n"
- " restat = 1\n"
- "\n"
- // Do not have obj/foo/dep.stamp as dependency.
- "build bar.out: __bar_bar___rule | ../../bar/script.py"
- " ../../bar/input1.txt obj/foo/foo.stamp\n"
- "\n"
- "build obj/bar/bar.stamp: stamp bar.out\n";
- EXPECT_EQ(expected_linux, out.str());
- }
-}
diff --git a/chromium/tools/gn/ninja_binary_target_writer.cc b/chromium/tools/gn/ninja_binary_target_writer.cc
deleted file mode 100644
index 1711ad23784..00000000000
--- a/chromium/tools/gn/ninja_binary_target_writer.cc
+++ /dev/null
@@ -1,1090 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/ninja_binary_target_writer.h"
-
-#include <stddef.h>
-#include <string.h>
-
-#include <cstring>
-#include <set>
-#include <sstream>
-
-#include "base/containers/hash_tables.h"
-#include "base/strings/string_util.h"
-#include "tools/gn/config_values_extractors.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/err.h"
-#include "tools/gn/escape.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/ninja_utils.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/source_file_type.h"
-#include "tools/gn/string_utils.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/target.h"
-
-// Represents a set of tool types. Must be first since it is also shared by
-// some helper functions in the anonymous namespace below.
-class NinjaBinaryTargetWriter::SourceFileTypeSet {
- public:
- SourceFileTypeSet() {
- memset(flags_, 0, sizeof(bool) * static_cast<int>(SOURCE_NUMTYPES));
- }
-
- void Set(SourceFileType type) {
- flags_[static_cast<int>(type)] = true;
- }
- bool Get(SourceFileType type) const {
- return flags_[static_cast<int>(type)];
- }
-
- private:
- bool flags_[static_cast<int>(SOURCE_NUMTYPES)];
-};
-
-namespace {
-
-// Returns the proper escape options for writing compiler and linker flags.
-EscapeOptions GetFlagOptions() {
- EscapeOptions opts;
- opts.mode = ESCAPE_NINJA_COMMAND;
- return opts;
-}
-
-struct DefineWriter {
- DefineWriter() {
- options.mode = ESCAPE_NINJA_COMMAND;
- }
-
- void operator()(const std::string& s, std::ostream& out) const {
- out << " -D";
- EscapeStringToStream(out, s, options);
- }
-
- EscapeOptions options;
-};
-
-struct IncludeWriter {
- explicit IncludeWriter(PathOutput& path_output) : path_output_(path_output) {
- }
- ~IncludeWriter() = default;
-
- void operator()(const SourceDir& d, std::ostream& out) const {
- std::ostringstream path_out;
- path_output_.WriteDir(path_out, d, PathOutput::DIR_NO_LAST_SLASH);
- const std::string& path = path_out.str();
- if (path[0] == '"')
- out << " \"-I" << path.substr(1);
- else
- out << " -I" << path;
- }
-
- PathOutput& path_output_;
-};
-
-// Returns the language-specific suffix for precompiled header files.
-const char* GetPCHLangSuffixForToolType(Toolchain::ToolType type) {
- switch (type) {
- case Toolchain::TYPE_CC:
- return "c";
- case Toolchain::TYPE_CXX:
- return "cc";
- case Toolchain::TYPE_OBJC:
- return "m";
- case Toolchain::TYPE_OBJCXX:
- return "mm";
- default:
- NOTREACHED() << "Not a valid PCH tool type: " << type;
- return "";
- }
-}
-
-std::string GetWindowsPCHObjectExtension(Toolchain::ToolType tool_type,
- const std::string& obj_extension) {
- const char* lang_suffix = GetPCHLangSuffixForToolType(tool_type);
- std::string result = ".";
- // For MSVC, annotate the obj files with the language type. For example:
- // obj/foo/target_name.precompile.obj ->
- // obj/foo/target_name.precompile.cc.obj
- result += lang_suffix;
- result += obj_extension;
- return result;
-}
-
-std::string GetGCCPCHOutputExtension(Toolchain::ToolType tool_type) {
- const char* lang_suffix = GetPCHLangSuffixForToolType(tool_type);
- std::string result = ".";
- // For GCC, the output name must have a .gch suffix and be annotated with
- // the language type. For example:
- // obj/foo/target_name.header.h ->
- // obj/foo/target_name.header.h-cc.gch
- // In order for the compiler to pick it up, the output name (minus the .gch
- // suffix MUST match whatever is passed to the -include flag).
- result += "h-";
- result += lang_suffix;
- result += ".gch";
- return result;
-}
-
-// Returns the language-specific lang recognized by gcc’s -x flag for
-// precompiled header files.
-const char* GetPCHLangForToolType(Toolchain::ToolType type) {
- switch (type) {
- case Toolchain::TYPE_CC:
- return "c-header";
- case Toolchain::TYPE_CXX:
- return "c++-header";
- case Toolchain::TYPE_OBJC:
- return "objective-c-header";
- case Toolchain::TYPE_OBJCXX:
- return "objective-c++-header";
- default:
- NOTREACHED() << "Not a valid PCH tool type: " << type;
- return "";
- }
-}
-
-// Fills |outputs| with the object or gch file for the precompiled header of the
-// given type (flag type and tool type must match).
-void GetPCHOutputFiles(const Target* target,
- Toolchain::ToolType tool_type,
- std::vector<OutputFile>* outputs) {
- outputs->clear();
-
- // Compute the tool. This must use the tool type passed in rather than the
- // detected file type of the precompiled source file since the same
- // precompiled source file will be used for separate C/C++ compiles.
- const Tool* tool = target->toolchain()->GetTool(tool_type);
- if (!tool)
- return;
- SubstitutionWriter::ApplyListToCompilerAsOutputFile(
- target, target->config_values().precompiled_source(),
- tool->outputs(), outputs);
-
- if (outputs->empty())
- return;
- if (outputs->size() > 1)
- outputs->resize(1); // Only link the first output from the compiler tool.
-
- std::string& output_value = (*outputs)[0].value();
- size_t extension_offset = FindExtensionOffset(output_value);
- if (extension_offset == std::string::npos) {
- // No extension found.
- return;
- }
- DCHECK(extension_offset >= 1);
- DCHECK(output_value[extension_offset - 1] == '.');
-
- std::string output_extension;
- Tool::PrecompiledHeaderType header_type = tool->precompiled_header_type();
- switch (header_type) {
- case Tool::PCH_MSVC:
- output_extension = GetWindowsPCHObjectExtension(
- tool_type, output_value.substr(extension_offset - 1));
- break;
- case Tool::PCH_GCC:
- output_extension = GetGCCPCHOutputExtension(tool_type);
- break;
- case Tool::PCH_NONE:
- NOTREACHED() << "No outputs for no PCH type.";
- break;
- }
- output_value.replace(extension_offset - 1,
- std::string::npos,
- output_extension);
-}
-
-// Appends the object files generated by the given source set to the given
-// output vector.
-void AddSourceSetObjectFiles(const Target* source_set,
- UniqueVector<OutputFile>* obj_files) {
- std::vector<OutputFile> tool_outputs; // Prevent allocation in loop.
- NinjaBinaryTargetWriter::SourceFileTypeSet used_types;
-
- // Compute object files for all sources. Only link the first output from
- // the tool if there are more than one.
- for (const auto& source : source_set->sources()) {
- Toolchain::ToolType tool_type = Toolchain::TYPE_NONE;
- if (source_set->GetOutputFilesForSource(source, &tool_type, &tool_outputs))
- obj_files->push_back(tool_outputs[0]);
-
- used_types.Set(GetSourceFileType(source));
- }
-
- // Add MSVC precompiled header object files. GCC .gch files are not object
- // files so they are omitted.
- if (source_set->config_values().has_precompiled_headers()) {
- if (used_types.Get(SOURCE_C)) {
- const Tool* tool = source_set->toolchain()->GetTool(Toolchain::TYPE_CC);
- if (tool && tool->precompiled_header_type() == Tool::PCH_MSVC) {
- GetPCHOutputFiles(source_set, Toolchain::TYPE_CC, &tool_outputs);
- obj_files->Append(tool_outputs.begin(), tool_outputs.end());
- }
- }
- if (used_types.Get(SOURCE_CPP)) {
- const Tool* tool = source_set->toolchain()->GetTool(Toolchain::TYPE_CXX);
- if (tool && tool->precompiled_header_type() == Tool::PCH_MSVC) {
- GetPCHOutputFiles(source_set, Toolchain::TYPE_CXX, &tool_outputs);
- obj_files->Append(tool_outputs.begin(), tool_outputs.end());
- }
- }
- if (used_types.Get(SOURCE_M)) {
- const Tool* tool = source_set->toolchain()->GetTool(Toolchain::TYPE_OBJC);
- if (tool && tool->precompiled_header_type() == Tool::PCH_MSVC) {
- GetPCHOutputFiles(source_set, Toolchain::TYPE_OBJC, &tool_outputs);
- obj_files->Append(tool_outputs.begin(), tool_outputs.end());
- }
- }
- if (used_types.Get(SOURCE_MM)) {
- const Tool* tool = source_set->toolchain()->GetTool(
- Toolchain::TYPE_OBJCXX);
- if (tool && tool->precompiled_header_type() == Tool::PCH_MSVC) {
- GetPCHOutputFiles(source_set, Toolchain::TYPE_OBJCXX, &tool_outputs);
- obj_files->Append(tool_outputs.begin(), tool_outputs.end());
- }
- }
- }
-}
-
-} // namespace
-
-NinjaBinaryTargetWriter::NinjaBinaryTargetWriter(const Target* target,
- std::ostream& out)
- : NinjaTargetWriter(target, out),
- tool_(target->toolchain()->GetToolForTargetFinalOutput(target)),
- rule_prefix_(GetNinjaRulePrefixForToolchain(settings_)) {
-}
-
-NinjaBinaryTargetWriter::~NinjaBinaryTargetWriter() = default;
-
-void NinjaBinaryTargetWriter::Run() {
- // Figure out what source types are needed.
- SourceFileTypeSet used_types;
- for (const auto& source : target_->sources())
- used_types.Set(GetSourceFileType(source));
-
- WriteCompilerVars(used_types);
-
- OutputFile input_dep = WriteInputsStampAndGetDep();
-
- // The input dependencies will be an order-only dependency. This will cause
- // Ninja to make sure the inputs are up to date before compiling this source,
- // but changes in the inputs deps won't cause the file to be recompiled.
- //
- // This is important to prevent changes in unrelated actions that are
- // upstream of this target from causing everything to be recompiled.
- //
- // Why can we get away with this rather than using implicit deps ("|", which
- // will force rebuilds when the inputs change)? For source code, the
- // computed dependencies of all headers will be computed by the compiler,
- // which will cause source rebuilds if any "real" upstream dependencies
- // change.
- //
- // If a .cc file is generated by an input dependency, Ninja will see the
- // input to the build rule doesn't exist, and that it is an output from a
- // previous step, and build the previous step first. This is a "real"
- // dependency and doesn't need | or || to express.
- //
- // The only case where this rule matters is for the first build where no .d
- // files exist, and Ninja doesn't know what that source file depends on. In
- // this case it's sufficient to ensure that the upstream dependencies are
- // built first. This is exactly what Ninja's order-only dependencies
- // expresses.
- //
- // The order only deps are referenced by each source file compile,
- // but also by PCH compiles. The latter are annoying to count, so omit
- // them here. This means that binary targets with a single source file
- // that also use PCH files won't have a stamp file even though having
- // one would make output ninja file size a bit lower. That's ok, binary
- // targets with a single source are rare.
- size_t num_stamp_uses = target_->sources().size();
- std::vector<OutputFile> order_only_deps = WriteInputDepsStampAndGetDep(
- std::vector<const Target*>(), num_stamp_uses);
-
- // For GCC builds, the .gch files are not object files, but still need to be
- // added as explicit dependencies below. The .gch output files are placed in
- // |pch_other_files|. This is to prevent linking against them.
- std::vector<OutputFile> pch_obj_files;
- std::vector<OutputFile> pch_other_files;
- WritePCHCommands(used_types, input_dep, order_only_deps, &pch_obj_files,
- &pch_other_files);
- std::vector<OutputFile>* pch_files = !pch_obj_files.empty() ?
- &pch_obj_files : &pch_other_files;
-
- // Treat all pch output files as explicit dependencies of all
- // compiles that support them. Some notes:
- //
- // - On Windows, the .pch file is the input to the compile, not the
- // precompiled header's corresponding object file that we're using here.
- // But Ninja's depslog doesn't support multiple outputs from the
- // precompiled header compile step (it outputs both the .pch file and a
- // corresponding .obj file). So we consistently list the .obj file and the
- // .pch file we really need comes along with it.
- //
- // - GCC .gch files are not object files, therefore they are not added to the
- // object file list.
- std::vector<OutputFile> obj_files;
- std::vector<SourceFile> other_files;
- WriteSources(*pch_files, input_dep, order_only_deps, &obj_files,
- &other_files);
-
- // Link all MSVC pch object files. The vector will be empty on GCC toolchains.
- obj_files.insert(obj_files.end(), pch_obj_files.begin(), pch_obj_files.end());
- if (!CheckForDuplicateObjectFiles(obj_files))
- return;
-
- if (target_->output_type() == Target::SOURCE_SET) {
- WriteSourceSetStamp(obj_files);
-#ifndef NDEBUG
- // Verify that the function that separately computes a source set's object
- // files match the object files just computed.
- UniqueVector<OutputFile> computed_obj;
- AddSourceSetObjectFiles(target_, &computed_obj);
- DCHECK_EQ(obj_files.size(), computed_obj.size());
- for (const auto& obj : obj_files)
- DCHECK_NE(static_cast<size_t>(-1), computed_obj.IndexOf(obj));
-#endif
- } else {
- WriteLinkerStuff(obj_files, other_files, input_dep);
- }
-}
-
-void NinjaBinaryTargetWriter::WriteCompilerVars(
- const SourceFileTypeSet& used_types) {
- const SubstitutionBits& subst = target_->toolchain()->substitution_bits();
-
- // Defines.
- if (subst.used[SUBSTITUTION_DEFINES]) {
- out_ << kSubstitutionNinjaNames[SUBSTITUTION_DEFINES] << " =";
- RecursiveTargetConfigToStream<std::string>(
- target_, &ConfigValues::defines, DefineWriter(), out_);
- out_ << std::endl;
- }
-
- // Include directories.
- if (subst.used[SUBSTITUTION_INCLUDE_DIRS]) {
- out_ << kSubstitutionNinjaNames[SUBSTITUTION_INCLUDE_DIRS] << " =";
- PathOutput include_path_output(
- path_output_.current_dir(),
- settings_->build_settings()->root_path_utf8(),
- ESCAPE_NINJA_COMMAND);
- RecursiveTargetConfigToStream<SourceDir>(
- target_, &ConfigValues::include_dirs,
- IncludeWriter(include_path_output), out_);
- out_ << std::endl;
- }
-
- bool has_precompiled_headers =
- target_->config_values().has_precompiled_headers();
-
- EscapeOptions opts = GetFlagOptions();
- if (used_types.Get(SOURCE_S) || used_types.Get(SOURCE_ASM)) {
- WriteOneFlag(SUBSTITUTION_ASMFLAGS, false, Toolchain::TYPE_NONE,
- &ConfigValues::asmflags, opts);
- }
- if (used_types.Get(SOURCE_C) || used_types.Get(SOURCE_CPP) ||
- used_types.Get(SOURCE_M) || used_types.Get(SOURCE_MM)) {
- WriteOneFlag(SUBSTITUTION_CFLAGS, false, Toolchain::TYPE_NONE,
- &ConfigValues::cflags, opts);
- }
- if (used_types.Get(SOURCE_C)) {
- WriteOneFlag(SUBSTITUTION_CFLAGS_C, has_precompiled_headers,
- Toolchain::TYPE_CC, &ConfigValues::cflags_c, opts);
- }
- if (used_types.Get(SOURCE_CPP)) {
- WriteOneFlag(SUBSTITUTION_CFLAGS_CC, has_precompiled_headers,
- Toolchain::TYPE_CXX, &ConfigValues::cflags_cc, opts);
- }
- if (used_types.Get(SOURCE_M)) {
- WriteOneFlag(SUBSTITUTION_CFLAGS_OBJC, has_precompiled_headers,
- Toolchain::TYPE_OBJC, &ConfigValues::cflags_objc, opts);
- }
- if (used_types.Get(SOURCE_MM)) {
- WriteOneFlag(SUBSTITUTION_CFLAGS_OBJCC, has_precompiled_headers,
- Toolchain::TYPE_OBJCXX, &ConfigValues::cflags_objcc, opts);
- }
-
- WriteSharedVars(subst);
-}
-
-OutputFile NinjaBinaryTargetWriter::WriteInputsStampAndGetDep() const {
- CHECK(target_->toolchain())
- << "Toolchain not set on target "
- << target_->label().GetUserVisibleName(true);
-
- std::vector<const SourceFile*> inputs;
- for (ConfigValuesIterator iter(target_); !iter.done(); iter.Next()) {
- for (const auto& input : iter.cur().inputs()) {
- inputs.push_back(&input);
- }
- }
-
- if (inputs.size() == 0)
- return OutputFile(); // No inputs
-
- // If we only have one input, return it directly instead of writing a stamp
- // file for it.
- if (inputs.size() == 1)
- return OutputFile(settings_->build_settings(), *inputs[0]);
-
- // Make a stamp file.
- OutputFile input_stamp_file =
- GetBuildDirForTargetAsOutputFile(target_, BuildDirType::OBJ);
- input_stamp_file.value().append(target_->label().name());
- input_stamp_file.value().append(".inputs.stamp");
-
- out_ << "build ";
- path_output_.WriteFile(out_, input_stamp_file);
- out_ << ": "
- << GetNinjaRulePrefixForToolchain(settings_)
- << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
-
- // File inputs.
- for (const auto* input : inputs) {
- out_ << " ";
- path_output_.WriteFile(out_, *input);
- }
-
- out_ << "\n";
- return input_stamp_file;
-}
-
-void NinjaBinaryTargetWriter::WriteOneFlag(
- SubstitutionType subst_enum,
- bool has_precompiled_headers,
- Toolchain::ToolType tool_type,
- const std::vector<std::string>& (ConfigValues::* getter)() const,
- EscapeOptions flag_escape_options) {
- if (!target_->toolchain()->substitution_bits().used[subst_enum])
- return;
-
- out_ << kSubstitutionNinjaNames[subst_enum] << " =";
-
- if (has_precompiled_headers) {
- const Tool* tool = target_->toolchain()->GetTool(tool_type);
- if (tool && tool->precompiled_header_type() == Tool::PCH_MSVC) {
- // Name the .pch file.
- out_ << " /Fp";
- path_output_.WriteFile(out_, GetWindowsPCHFile(tool_type));
-
- // Enables precompiled headers and names the .h file. It's a string
- // rather than a file name (so no need to rebase or use path_output_).
- out_ << " /Yu" << target_->config_values().precompiled_header();
- RecursiveTargetConfigStringsToStream(target_, getter,
- flag_escape_options, out_);
- } else if (tool && tool->precompiled_header_type() == Tool::PCH_GCC) {
- // The targets to build the .gch files should omit the -include flag
- // below. To accomplish this, each substitution flag is overwritten in the
- // target rule and these values are repeated. The -include flag is omitted
- // in place of the required -x <header lang> flag for .gch targets.
- RecursiveTargetConfigStringsToStream(target_, getter,
- flag_escape_options, out_);
-
- // Compute the gch file (it will be language-specific).
- std::vector<OutputFile> outputs;
- GetPCHOutputFiles(target_, tool_type, &outputs);
- if (!outputs.empty()) {
- // Trim the .gch suffix for the -include flag.
- // e.g. for gch file foo/bar/target.precompiled.h.gch:
- // -include foo/bar/target.precompiled.h
- std::string pch_file = outputs[0].value();
- pch_file.erase(pch_file.length() - 4);
- out_ << " -include " << pch_file;
- }
- } else {
- RecursiveTargetConfigStringsToStream(target_, getter,
- flag_escape_options, out_);
- }
- } else {
- RecursiveTargetConfigStringsToStream(target_, getter,
- flag_escape_options, out_);
- }
- out_ << std::endl;
-}
-
-void NinjaBinaryTargetWriter::WritePCHCommands(
- const SourceFileTypeSet& used_types,
- const OutputFile& input_dep,
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* object_files,
- std::vector<OutputFile>* other_files) {
- if (!target_->config_values().has_precompiled_headers())
- return;
-
- const Tool* tool_c = target_->toolchain()->GetTool(Toolchain::TYPE_CC);
- if (tool_c &&
- tool_c->precompiled_header_type() != Tool::PCH_NONE &&
- used_types.Get(SOURCE_C)) {
- WritePCHCommand(SUBSTITUTION_CFLAGS_C, Toolchain::TYPE_CC,
- tool_c->precompiled_header_type(), input_dep,
- order_only_deps, object_files, other_files);
- }
- const Tool* tool_cxx = target_->toolchain()->GetTool(Toolchain::TYPE_CXX);
- if (tool_cxx &&
- tool_cxx->precompiled_header_type() != Tool::PCH_NONE &&
- used_types.Get(SOURCE_CPP)) {
- WritePCHCommand(SUBSTITUTION_CFLAGS_CC, Toolchain::TYPE_CXX,
- tool_cxx->precompiled_header_type(), input_dep,
- order_only_deps, object_files, other_files);
- }
-
- const Tool* tool_objc = target_->toolchain()->GetTool(Toolchain::TYPE_OBJC);
- if (tool_objc &&
- tool_objc->precompiled_header_type() == Tool::PCH_GCC &&
- used_types.Get(SOURCE_M)) {
- WritePCHCommand(SUBSTITUTION_CFLAGS_OBJC, Toolchain::TYPE_OBJC,
- tool_objc->precompiled_header_type(), input_dep,
- order_only_deps, object_files, other_files);
- }
-
- const Tool* tool_objcxx =
- target_->toolchain()->GetTool(Toolchain::TYPE_OBJCXX);
- if (tool_objcxx &&
- tool_objcxx->precompiled_header_type() == Tool::PCH_GCC &&
- used_types.Get(SOURCE_MM)) {
- WritePCHCommand(SUBSTITUTION_CFLAGS_OBJCC, Toolchain::TYPE_OBJCXX,
- tool_objcxx->precompiled_header_type(), input_dep,
- order_only_deps, object_files, other_files);
- }
-}
-
-void NinjaBinaryTargetWriter::WritePCHCommand(
- SubstitutionType flag_type,
- Toolchain::ToolType tool_type,
- Tool::PrecompiledHeaderType header_type,
- const OutputFile& input_dep,
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* object_files,
- std::vector<OutputFile>* other_files) {
- switch (header_type) {
- case Tool::PCH_MSVC:
- WriteWindowsPCHCommand(flag_type, tool_type, input_dep, order_only_deps,
- object_files);
- break;
- case Tool::PCH_GCC:
- WriteGCCPCHCommand(flag_type, tool_type, input_dep, order_only_deps,
- other_files);
- break;
- case Tool::PCH_NONE:
- NOTREACHED() << "Cannot write a PCH command with no PCH header type";
- break;
- }
-}
-
-void NinjaBinaryTargetWriter::WriteGCCPCHCommand(
- SubstitutionType flag_type,
- Toolchain::ToolType tool_type,
- const OutputFile& input_dep,
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* gch_files) {
- // Compute the pch output file (it will be language-specific).
- std::vector<OutputFile> outputs;
- GetPCHOutputFiles(target_, tool_type, &outputs);
- if (outputs.empty())
- return;
-
- gch_files->insert(gch_files->end(), outputs.begin(), outputs.end());
-
- std::vector<OutputFile> extra_deps;
- if (!input_dep.value().empty())
- extra_deps.push_back(input_dep);
-
- // Build line to compile the file.
- WriteCompilerBuildLine(target_->config_values().precompiled_source(),
- extra_deps, order_only_deps, tool_type, outputs);
-
- // This build line needs a custom language-specific flags value. Rule-specific
- // variables are just indented underneath the rule line.
- out_ << " " << kSubstitutionNinjaNames[flag_type] << " =";
-
- // Each substitution flag is overwritten in the target rule to replace the
- // implicitly generated -include flag with the -x <header lang> flag required
- // for .gch targets.
- EscapeOptions opts = GetFlagOptions();
- if (tool_type == Toolchain::TYPE_CC) {
- RecursiveTargetConfigStringsToStream(target_,
- &ConfigValues::cflags_c, opts, out_);
- } else if (tool_type == Toolchain::TYPE_CXX) {
- RecursiveTargetConfigStringsToStream(target_,
- &ConfigValues::cflags_cc, opts, out_);
- } else if (tool_type == Toolchain::TYPE_OBJC) {
- RecursiveTargetConfigStringsToStream(target_,
- &ConfigValues::cflags_objc, opts, out_);
- } else if (tool_type == Toolchain::TYPE_OBJCXX) {
- RecursiveTargetConfigStringsToStream(target_,
- &ConfigValues::cflags_objcc, opts, out_);
- }
-
- // Append the command to specify the language of the .gch file.
- out_ << " -x " << GetPCHLangForToolType(tool_type);
-
- // Write two blank lines to help separate the PCH build lines from the
- // regular source build lines.
- out_ << std::endl << std::endl;
-}
-
-void NinjaBinaryTargetWriter::WriteWindowsPCHCommand(
- SubstitutionType flag_type,
- Toolchain::ToolType tool_type,
- const OutputFile& input_dep,
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* object_files) {
- // Compute the pch output file (it will be language-specific).
- std::vector<OutputFile> outputs;
- GetPCHOutputFiles(target_, tool_type, &outputs);
- if (outputs.empty())
- return;
-
- object_files->insert(object_files->end(), outputs.begin(), outputs.end());
-
- std::vector<OutputFile> extra_deps;
- if (!input_dep.value().empty())
- extra_deps.push_back(input_dep);
-
- // Build line to compile the file.
- WriteCompilerBuildLine(target_->config_values().precompiled_source(),
- extra_deps, order_only_deps, tool_type, outputs);
-
- // This build line needs a custom language-specific flags value. Rule-specific
- // variables are just indented underneath the rule line.
- out_ << " " << kSubstitutionNinjaNames[flag_type] << " =";
-
- // Append the command to generate the .pch file.
- // This adds the value to the existing flag instead of overwriting it.
- out_ << " ${" << kSubstitutionNinjaNames[flag_type] << "}";
- out_ << " /Yc" << target_->config_values().precompiled_header();
-
- // Write two blank lines to help separate the PCH build lines from the
- // regular source build lines.
- out_ << std::endl << std::endl;
-}
-
-void NinjaBinaryTargetWriter::WriteSources(
- const std::vector<OutputFile>& pch_deps,
- const OutputFile& input_dep,
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* object_files,
- std::vector<SourceFile>* other_files) {
- object_files->reserve(object_files->size() + target_->sources().size());
-
- std::vector<OutputFile> tool_outputs; // Prevent reallocation in loop.
- std::vector<OutputFile> deps;
- for (const auto& source : target_->sources()) {
- // Clear the vector but maintain the max capacity to prevent reallocations.
- deps.resize(0);
- Toolchain::ToolType tool_type = Toolchain::TYPE_NONE;
- if (!target_->GetOutputFilesForSource(source, &tool_type, &tool_outputs)) {
- if (GetSourceFileType(source) == SOURCE_DEF)
- other_files->push_back(source);
- continue; // No output for this source.
- }
-
- if (!input_dep.value().empty())
- deps.push_back(input_dep);
-
- if (tool_type != Toolchain::TYPE_NONE) {
- // Only include PCH deps that correspond to the tool type, for instance,
- // do not specify target_name.precompile.cc.obj (a CXX PCH file) as a dep
- // for the output of a C tool type.
- //
- // This makes the assumption that pch_deps only contains pch output files
- // with the naming scheme specified in GetWindowsPCHObjectExtension or
- // GetGCCPCHOutputExtension.
- const Tool* tool = target_->toolchain()->GetTool(tool_type);
- if (tool->precompiled_header_type() != Tool::PCH_NONE) {
- for (const auto& dep : pch_deps) {
- const std::string& output_value = dep.value();
- size_t extension_offset = FindExtensionOffset(output_value);
- if (extension_offset == std::string::npos)
- continue;
- std::string output_extension;
- if (tool->precompiled_header_type() == Tool::PCH_MSVC) {
- output_extension = GetWindowsPCHObjectExtension(
- tool_type, output_value.substr(extension_offset - 1));
- } else if (tool->precompiled_header_type() == Tool::PCH_GCC) {
- output_extension = GetGCCPCHOutputExtension(tool_type);
- }
- if (output_value.compare(output_value.size() -
- output_extension.size(), output_extension.size(),
- output_extension) == 0) {
- deps.push_back(dep);
- }
- }
- }
- WriteCompilerBuildLine(source, deps, order_only_deps, tool_type,
- tool_outputs);
- }
-
- // It's theoretically possible for a compiler to produce more than one
- // output, but we'll only link to the first output.
- object_files->push_back(tool_outputs[0]);
- }
- out_ << std::endl;
-}
-
-void NinjaBinaryTargetWriter::WriteCompilerBuildLine(
- const SourceFile& source,
- const std::vector<OutputFile>& extra_deps,
- const std::vector<OutputFile>& order_only_deps,
- Toolchain::ToolType tool_type,
- const std::vector<OutputFile>& outputs) {
- out_ << "build";
- path_output_.WriteFiles(out_, outputs);
-
- out_ << ": " << rule_prefix_ << Toolchain::ToolTypeToName(tool_type);
- out_ << " ";
- path_output_.WriteFile(out_, source);
-
- if (!extra_deps.empty()) {
- out_ << " |";
- path_output_.WriteFiles(out_, extra_deps);
- }
-
- if (!order_only_deps.empty()) {
- out_ << " ||";
- path_output_.WriteFiles(out_, order_only_deps);
- }
- out_ << std::endl;
-}
-
-void NinjaBinaryTargetWriter::WriteLinkerStuff(
- const std::vector<OutputFile>& object_files,
- const std::vector<SourceFile>& other_files,
- const OutputFile& input_dep) {
- std::vector<OutputFile> output_files;
- SubstitutionWriter::ApplyListToLinkerAsOutputFile(
- target_, tool_, tool_->outputs(), &output_files);
-
- out_ << "build";
- path_output_.WriteFiles(out_, output_files);
-
- out_ << ": " << rule_prefix_
- << Toolchain::ToolTypeToName(
- target_->toolchain()->GetToolTypeForTargetFinalOutput(target_));
-
- UniqueVector<OutputFile> extra_object_files;
- UniqueVector<const Target*> linkable_deps;
- UniqueVector<const Target*> non_linkable_deps;
- GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps);
-
- // Object files.
- path_output_.WriteFiles(out_, object_files);
- path_output_.WriteFiles(out_, extra_object_files);
-
- // Dependencies.
- std::vector<OutputFile> implicit_deps;
- std::vector<OutputFile> solibs;
- for (const Target* cur : linkable_deps) {
- // All linkable deps should have a link output file.
- DCHECK(!cur->link_output_file().value().empty())
- << "No link output file for "
- << target_->label().GetUserVisibleName(false);
-
- if (cur->dependency_output_file().value() !=
- cur->link_output_file().value()) {
- // This is a shared library with separate link and deps files. Save for
- // later.
- implicit_deps.push_back(cur->dependency_output_file());
- solibs.push_back(cur->link_output_file());
- } else {
- // Normal case, just link to this target.
- out_ << " ";
- path_output_.WriteFile(out_, cur->link_output_file());
- }
- }
-
- const SourceFile* optional_def_file = nullptr;
- if (!other_files.empty()) {
- for (const SourceFile& src_file : other_files) {
- if (GetSourceFileType(src_file) == SOURCE_DEF) {
- optional_def_file = &src_file;
- implicit_deps.push_back(
- OutputFile(settings_->build_settings(), src_file));
- break; // Only one def file is allowed.
- }
- }
- }
-
- // Libraries specified by paths.
- const OrderedSet<LibFile>& libs = target_->all_libs();
- for (size_t i = 0; i < libs.size(); i++) {
- if (libs[i].is_source_file()) {
- implicit_deps.push_back(
- OutputFile(settings_->build_settings(), libs[i].source_file()));
- }
- }
-
- // The input dependency is only needed if there are no object files, as the
- // dependency is normally provided transitively by the source files.
- if (!input_dep.value().empty() && object_files.empty())
- implicit_deps.push_back(input_dep);
-
- // Append implicit dependencies collected above.
- if (!implicit_deps.empty()) {
- out_ << " |";
- path_output_.WriteFiles(out_, implicit_deps);
- }
-
- // Append data dependencies as order-only dependencies.
- //
- // This will include data dependencies and input dependencies (like when
- // this target depends on an action). Having the data dependencies in this
- // list ensures that the data is available at runtime when the user builds
- // this target.
- //
- // The action dependencies are not strictly necessary in this case. They
- // should also have been collected via the input deps stamp that each source
- // file has for an order-only dependency, and since this target depends on
- // the sources, there is already an implicit order-only dependency. However,
- // it's extra work to separate these out and there's no disadvantage to
- // listing them again.
- WriteOrderOnlyDependencies(non_linkable_deps);
-
- // End of the link "build" line.
- out_ << std::endl;
-
- // The remaining things go in the inner scope of the link line.
- if (target_->output_type() == Target::EXECUTABLE ||
- target_->output_type() == Target::SHARED_LIBRARY ||
- target_->output_type() == Target::LOADABLE_MODULE) {
- WriteLinkerFlags(optional_def_file);
- WriteLibs();
- } else if (target_->output_type() == Target::STATIC_LIBRARY) {
- out_ << " arflags =";
- RecursiveTargetConfigStringsToStream(target_, &ConfigValues::arflags,
- GetFlagOptions(), out_);
- out_ << std::endl;
- }
- WriteOutputSubstitutions();
- WriteSolibs(solibs);
-}
-
-void NinjaBinaryTargetWriter::WriteLinkerFlags(
- const SourceFile* optional_def_file) {
- out_ << " ldflags =";
-
- // First the ldflags from the target and its config.
- RecursiveTargetConfigStringsToStream(target_, &ConfigValues::ldflags,
- GetFlagOptions(), out_);
-
- // Followed by library search paths that have been recursively pushed
- // through the dependency tree.
- const OrderedSet<SourceDir> all_lib_dirs = target_->all_lib_dirs();
- if (!all_lib_dirs.empty()) {
- // Since we're passing these on the command line to the linker and not
- // to Ninja, we need to do shell escaping.
- PathOutput lib_path_output(path_output_.current_dir(),
- settings_->build_settings()->root_path_utf8(),
- ESCAPE_NINJA_COMMAND);
- for (size_t i = 0; i < all_lib_dirs.size(); i++) {
- out_ << " " << tool_->lib_dir_switch();
- lib_path_output.WriteDir(out_, all_lib_dirs[i],
- PathOutput::DIR_NO_LAST_SLASH);
- }
- }
-
- if (optional_def_file) {
- out_ << " /DEF:";
- path_output_.WriteFile(out_, *optional_def_file);
- }
-
- out_ << std::endl;
-}
-
-void NinjaBinaryTargetWriter::WriteLibs() {
- out_ << " libs =";
-
- // Libraries that have been recursively pushed through the dependency tree.
- EscapeOptions lib_escape_opts;
- lib_escape_opts.mode = ESCAPE_NINJA_COMMAND;
- const OrderedSet<LibFile> all_libs = target_->all_libs();
- const std::string framework_ending(".framework");
- for (size_t i = 0; i < all_libs.size(); i++) {
- const LibFile& lib_file = all_libs[i];
- const std::string& lib_value = lib_file.value();
- if (lib_file.is_source_file()) {
- out_ << " ";
- path_output_.WriteFile(out_, lib_file.source_file());
- } else if (base::EndsWith(lib_value, framework_ending,
- base::CompareCase::INSENSITIVE_ASCII)) {
- // Special-case libraries ending in ".framework" to support Mac: Add the
- // -framework switch and don't add the extension to the output.
- out_ << " -framework ";
- EscapeStringToStream(
- out_, lib_value.substr(0, lib_value.size() - framework_ending.size()),
- lib_escape_opts);
- } else {
- out_ << " " << tool_->lib_switch();
- EscapeStringToStream(out_, lib_value, lib_escape_opts);
- }
- }
- out_ << std::endl;
-}
-
-void NinjaBinaryTargetWriter::WriteOutputSubstitutions() {
- out_ << " output_extension = "
- << SubstitutionWriter::GetLinkerSubstitution(
- target_, tool_, SUBSTITUTION_OUTPUT_EXTENSION);
- out_ << std::endl;
- out_ << " output_dir = "
- << SubstitutionWriter::GetLinkerSubstitution(
- target_, tool_, SUBSTITUTION_OUTPUT_DIR);
- out_ << std::endl;
-}
-
-void NinjaBinaryTargetWriter::WriteSolibs(
- const std::vector<OutputFile>& solibs) {
- if (solibs.empty())
- return;
-
- out_ << " solibs =";
- path_output_.WriteFiles(out_, solibs);
- out_ << std::endl;
-}
-
-void NinjaBinaryTargetWriter::WriteSourceSetStamp(
- const std::vector<OutputFile>& object_files) {
- // The stamp rule for source sets is generally not used, since targets that
- // depend on this will reference the object files directly. However, writing
- // this rule allows the user to type the name of the target and get a build
- // which can be convenient for development.
- UniqueVector<OutputFile> extra_object_files;
- UniqueVector<const Target*> linkable_deps;
- UniqueVector<const Target*> non_linkable_deps;
- GetDeps(&extra_object_files, &linkable_deps, &non_linkable_deps);
-
- // The classifier should never put extra object files in a source set:
- // any source sets that we depend on should appear in our non-linkable
- // deps instead.
- DCHECK(extra_object_files.empty());
-
- std::vector<OutputFile> order_only_deps;
- for (auto* dep : non_linkable_deps)
- order_only_deps.push_back(dep->dependency_output_file());
-
- WriteStampForTarget(object_files, order_only_deps);
-}
-
-void NinjaBinaryTargetWriter::GetDeps(
- UniqueVector<OutputFile>* extra_object_files,
- UniqueVector<const Target*>* linkable_deps,
- UniqueVector<const Target*>* non_linkable_deps) const {
- // Normal public/private deps.
- for (const auto& pair : target_->GetDeps(Target::DEPS_LINKED)) {
- ClassifyDependency(pair.ptr, extra_object_files,
- linkable_deps, non_linkable_deps);
- }
-
- // Inherited libraries.
- for (auto* inherited_target : target_->inherited_libraries().GetOrdered()) {
- ClassifyDependency(inherited_target, extra_object_files,
- linkable_deps, non_linkable_deps);
- }
-
- // Data deps.
- for (const auto& data_dep_pair : target_->data_deps())
- non_linkable_deps->push_back(data_dep_pair.ptr);
-}
-
-void NinjaBinaryTargetWriter::ClassifyDependency(
- const Target* dep,
- UniqueVector<OutputFile>* extra_object_files,
- UniqueVector<const Target*>* linkable_deps,
- UniqueVector<const Target*>* non_linkable_deps) const {
- // Only the following types of outputs have libraries linked into them:
- // EXECUTABLE
- // SHARED_LIBRARY
- // _complete_ STATIC_LIBRARY
- //
- // Child deps of intermediate static libraries get pushed up the
- // dependency tree until one of these is reached, and source sets
- // don't link at all.
- bool can_link_libs = target_->IsFinal();
-
- if (dep->output_type() == Target::SOURCE_SET ||
- // If a complete static library depends on an incomplete static library,
- // manually link in the object files of the dependent library as if it
- // were a source set. This avoids problems with braindead tools such as
- // ar which don't properly link dependent static libraries.
- (target_->complete_static_lib() &&
- dep->output_type() == Target::STATIC_LIBRARY &&
- !dep->complete_static_lib())) {
- // Source sets have their object files linked into final targets
- // (shared libraries, executables, loadable modules, and complete static
- // libraries). Intermediate static libraries and other source sets
- // just forward the dependency, otherwise the files in the source
- // set can easily get linked more than once which will cause
- // multiple definition errors.
- if (can_link_libs)
- AddSourceSetObjectFiles(dep, extra_object_files);
-
- // Add the source set itself as a non-linkable dependency on the current
- // target. This will make sure that anything the source set's stamp file
- // depends on (like data deps) are also built before the current target
- // can be complete. Otherwise, these will be skipped since this target
- // will depend only on the source set's object files.
- non_linkable_deps->push_back(dep);
- } else if (target_->complete_static_lib() && dep->IsFinal()) {
- non_linkable_deps->push_back(dep);
- } else if (can_link_libs && dep->IsLinkable()) {
- linkable_deps->push_back(dep);
- } else {
- non_linkable_deps->push_back(dep);
- }
-}
-
-void NinjaBinaryTargetWriter::WriteOrderOnlyDependencies(
- const UniqueVector<const Target*>& non_linkable_deps) {
- if (!non_linkable_deps.empty()) {
- out_ << " ||";
-
- // Non-linkable targets.
- for (auto* non_linkable_dep : non_linkable_deps) {
- out_ << " ";
- path_output_.WriteFile(out_, non_linkable_dep->dependency_output_file());
- }
- }
-}
-
-OutputFile NinjaBinaryTargetWriter::GetWindowsPCHFile(
- Toolchain::ToolType tool_type) const {
- // Use "obj/{dir}/{target_name}_{lang}.pch" which ends up
- // looking like "obj/chrome/browser/browser_cc.pch"
- OutputFile ret = GetBuildDirForTargetAsOutputFile(target_, BuildDirType::OBJ);
- ret.value().append(target_->label().name());
- ret.value().push_back('_');
- ret.value().append(GetPCHLangSuffixForToolType(tool_type));
- ret.value().append(".pch");
-
- return ret;
-}
-
-bool NinjaBinaryTargetWriter::CheckForDuplicateObjectFiles(
- const std::vector<OutputFile>& files) const {
- base::hash_set<std::string> set;
- for (const auto& file : files) {
- if (!set.insert(file.value()).second) {
- Err err(
- target_->defined_from(),
- "Duplicate object file",
- "The target " + target_->label().GetUserVisibleName(false) +
- "\ngenerates two object files with the same name:\n " +
- file.value() + "\n"
- "\n"
- "It could be you accidentally have a file listed twice in the\n"
- "sources. Or, depending on how your toolchain maps sources to\n"
- "object files, two source files with the same name in different\n"
- "directories could map to the same object file.\n"
- "\n"
- "In the latter case, either rename one of the files or move one of\n"
- "the sources to a separate source_set to avoid them both being in\n"
- "the same target.");
- g_scheduler->FailWithError(err);
- return false;
- }
- }
- return true;
-}
diff --git a/chromium/tools/gn/ninja_binary_target_writer.h b/chromium/tools/gn/ninja_binary_target_writer.h
deleted file mode 100644
index 91a7a2776cf..00000000000
--- a/chromium/tools/gn/ninja_binary_target_writer.h
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_NINJA_BINARY_TARGET_WRITER_H_
-#define TOOLS_GN_NINJA_BINARY_TARGET_WRITER_H_
-
-#include "base/macros.h"
-#include "tools/gn/config_values.h"
-#include "tools/gn/ninja_target_writer.h"
-#include "tools/gn/toolchain.h"
-#include "tools/gn/unique_vector.h"
-
-struct EscapeOptions;
-class SourceFileTypeSet;
-
-// Writes a .ninja file for a binary target type (an executable, a shared
-// library, or a static library).
-class NinjaBinaryTargetWriter : public NinjaTargetWriter {
- public:
- class SourceFileTypeSet;
-
- NinjaBinaryTargetWriter(const Target* target, std::ostream& out);
- ~NinjaBinaryTargetWriter() override;
-
- void Run() override;
-
- private:
- typedef std::set<OutputFile> OutputFileSet;
-
- // Writes all flags for the compiler: includes, defines, cflags, etc.
- void WriteCompilerVars(const SourceFileTypeSet& used_types);
-
- // Writes to the output stream a stamp rule for inputs, and
- // returns the file to be appended to source rules that encodes the
- // implicit dependencies for the current target. The returned OutputFile
- // will be empty if there are no inputs.
- OutputFile WriteInputsStampAndGetDep() const;
-
- // has_precompiled_headers is set when this substitution matches a tool type
- // that supports precompiled headers, and this target supports precompiled
- // headers. It doesn't indicate if the tool has precompiled headers (this
- // will be looked up by this function).
- //
- // The tool_type indicates the corresponding tool for flags that are
- // tool-specific (e.g. "cflags_c"). For non-tool-specific flags (e.g.
- // "defines") tool_type should be TYPE_NONE.
- void WriteOneFlag(
- SubstitutionType subst_enum,
- bool has_precompiled_headers,
- Toolchain::ToolType tool_type,
- const std::vector<std::string>& (ConfigValues::* getter)() const,
- EscapeOptions flag_escape_options);
-
- // Writes build lines required for precompiled headers. Any generated
- // object files will be appended to the |object_files|. Any generated
- // non-object files (for instance, .gch files from a GCC toolchain, are
- // appended to |other_files|).
- //
- // input_dep is the stamp file collecting the dependencies required before
- // compiling this target. It will be empty if there are no input deps.
- void WritePCHCommands(const SourceFileTypeSet& used_types,
- const OutputFile& input_dep,
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* object_files,
- std::vector<OutputFile>* other_files);
-
- // Writes a .pch compile build line for a language type.
- void WritePCHCommand(SubstitutionType flag_type,
- Toolchain::ToolType tool_type,
- Tool::PrecompiledHeaderType header_type,
- const OutputFile& input_dep,
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* object_files,
- std::vector<OutputFile>* other_files);
-
- void WriteGCCPCHCommand(SubstitutionType flag_type,
- Toolchain::ToolType tool_type,
- const OutputFile& input_dep,
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* gch_files);
-
- void WriteWindowsPCHCommand(SubstitutionType flag_type,
- Toolchain::ToolType tool_type,
- const OutputFile& input_dep,
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* object_files);
-
- // pch_deps are additional dependencies to run before the rule. They are
- // expected to abide by the naming conventions specified by GetPCHOutputFiles.
- //
- // order_only_dep are the dependencies that must be run before doing any
- // compiles.
- //
- // The files produced by the compiler will be added to two output vectors.
- void WriteSources(const std::vector<OutputFile>& pch_deps,
- const OutputFile& input_dep,
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* object_files,
- std::vector<SourceFile>* other_files);
-
- // Writes a build line.
- void WriteCompilerBuildLine(const SourceFile& source,
- const std::vector<OutputFile>& extra_deps,
- const std::vector<OutputFile>& order_only_deps,
- Toolchain::ToolType tool_type,
- const std::vector<OutputFile>& outputs);
-
- void WriteLinkerStuff(const std::vector<OutputFile>& object_files,
- const std::vector<SourceFile>& other_files,
- const OutputFile& input_dep);
- void WriteLinkerFlags(const SourceFile* optional_def_file);
- void WriteLibs();
- void WriteOutputSubstitutions();
- void WriteSolibs(const std::vector<OutputFile>& solibs);
-
- // Writes the stamp line for a source set. These are not linked.
- void WriteSourceSetStamp(const std::vector<OutputFile>& object_files);
-
- // Gets all target dependencies and classifies them, as well as accumulates
- // object files from source sets we need to link.
- void GetDeps(UniqueVector<OutputFile>* extra_object_files,
- UniqueVector<const Target*>* linkable_deps,
- UniqueVector<const Target*>* non_linkable_deps) const;
-
- // Classifies the dependency as linkable or nonlinkable with the current
- // target, adding it to the appropriate vector. If the dependency is a source
- // set we should link in, the source set's object files will be appended to
- // |extra_object_files|.
- void ClassifyDependency(const Target* dep,
- UniqueVector<OutputFile>* extra_object_files,
- UniqueVector<const Target*>* linkable_deps,
- UniqueVector<const Target*>* non_linkable_deps) const;
-
- // Writes the implicit dependencies for the link or stamp line. This is
- // the "||" and everything following it on the ninja line.
- //
- // The order-only dependencies are the non-linkable deps passed in as an
- // argument, plus the data file depdencies in the target.
- void WriteOrderOnlyDependencies(
- const UniqueVector<const Target*>& non_linkable_deps);
-
- // Returns the computed name of the Windows .pch file for the given
- // tool type. The tool must support precompiled headers.
- OutputFile GetWindowsPCHFile(Toolchain::ToolType tool_type) const;
-
- // Checks for duplicates in the given list of output files. If any duplicates
- // are found, throws an error and return false.
- bool CheckForDuplicateObjectFiles(const std::vector<OutputFile>& files) const;
-
- const Tool* tool_;
-
- // Cached version of the prefix used for rule types for this toolchain.
- std::string rule_prefix_;
-
- DISALLOW_COPY_AND_ASSIGN(NinjaBinaryTargetWriter);
-};
-
-#endif // TOOLS_GN_NINJA_BINARY_TARGET_WRITER_H_
-
diff --git a/chromium/tools/gn/ninja_binary_target_writer_unittest.cc b/chromium/tools/gn/ninja_binary_target_writer_unittest.cc
deleted file mode 100644
index 20239b05373..00000000000
--- a/chromium/tools/gn/ninja_binary_target_writer_unittest.cc
+++ /dev/null
@@ -1,1125 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/ninja_binary_target_writer.h"
-
-#include <memory>
-#include <sstream>
-#include <utility>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/config.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scheduler.h"
-#include "tools/gn/test_with_scope.h"
-
-using NinjaBinaryTargetWriterTest = TestWithScheduler;
-
-TEST_F(NinjaBinaryTargetWriterTest, SourceSet) {
- Err err;
- TestWithScope setup;
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::SOURCE_SET);
- target.visibility().SetPublic();
- target.sources().push_back(SourceFile("//foo/input1.cc"));
- target.sources().push_back(SourceFile("//foo/input2.cc"));
- // Also test object files, which should be just passed through to the
- // dependents to link.
- target.sources().push_back(SourceFile("//foo/input3.o"));
- target.sources().push_back(SourceFile("//foo/input4.obj"));
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- // Source set itself.
- {
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = bar\n"
- "\n"
- "build obj/foo/bar.input1.o: cxx ../../foo/input1.cc\n"
- "build obj/foo/bar.input2.o: cxx ../../foo/input2.cc\n"
- "\n"
- "build obj/foo/bar.stamp: stamp obj/foo/bar.input1.o "
- "obj/foo/bar.input2.o ../../foo/input3.o ../../foo/input4.obj\n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
- }
-
- // A shared library that depends on the source set.
- Target shlib_target(setup.settings(), Label(SourceDir("//foo/"), "shlib"));
- shlib_target.set_output_type(Target::SHARED_LIBRARY);
- shlib_target.public_deps().push_back(LabelTargetPair(&target));
- shlib_target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(shlib_target.OnResolved(&err));
-
- {
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&shlib_target, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = libshlib\n"
- "\n"
- "\n"
- // Ordering of the obj files here should come out in the order
- // specified, with the target's first, followed by the source set's, in
- // order.
- "build ./libshlib.so: solink obj/foo/bar.input1.o "
- "obj/foo/bar.input2.o ../../foo/input3.o ../../foo/input4.obj "
- "|| obj/foo/bar.stamp\n"
- " ldflags =\n"
- " libs =\n"
- " output_extension = .so\n"
- " output_dir = \n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
- }
-
- // A static library that depends on the source set (should not link it).
- Target stlib_target(setup.settings(), Label(SourceDir("//foo/"), "stlib"));
- stlib_target.set_output_type(Target::STATIC_LIBRARY);
- stlib_target.public_deps().push_back(LabelTargetPair(&target));
- stlib_target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(stlib_target.OnResolved(&err));
-
- {
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&stlib_target, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = libstlib\n"
- "\n"
- "\n"
- // There are no sources so there are no params to alink. (In practice
- // this will probably fail in the archive tool.)
- "build obj/foo/libstlib.a: alink || obj/foo/bar.stamp\n"
- " arflags =\n"
- " output_extension = \n"
- " output_dir = \n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
- }
-
- // Make the static library 'complete', which means it should be linked.
- stlib_target.set_complete_static_lib(true);
- {
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&stlib_target, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = libstlib\n"
- "\n"
- "\n"
- // Ordering of the obj files here should come out in the order
- // specified, with the target's first, followed by the source set's, in
- // order.
- "build obj/foo/libstlib.a: alink obj/foo/bar.input1.o "
- "obj/foo/bar.input2.o ../../foo/input3.o ../../foo/input4.obj "
- "|| obj/foo/bar.stamp\n"
- " arflags =\n"
- " output_extension = \n"
- " output_dir = \n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
- }
-}
-
-TEST_F(NinjaBinaryTargetWriterTest, StaticLibrary) {
- TestWithScope setup;
- Err err;
-
- TestTarget target(setup, "//foo:bar", Target::STATIC_LIBRARY);
- target.sources().push_back(SourceFile("//foo/input1.cc"));
- target.config_values().arflags().push_back("--asdf");
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = libbar\n"
- "\n"
- "build obj/foo/libbar.input1.o: cxx ../../foo/input1.cc\n"
- "\n"
- "build obj/foo/libbar.a: alink obj/foo/libbar.input1.o\n"
- " arflags = --asdf\n"
- " output_extension = \n"
- " output_dir = \n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
-}
-
-TEST_F(NinjaBinaryTargetWriterTest, CompleteStaticLibrary) {
- TestWithScope setup;
- Err err;
-
- TestTarget target(setup, "//foo:bar", Target::STATIC_LIBRARY);
- target.sources().push_back(SourceFile("//foo/input1.cc"));
- target.config_values().arflags().push_back("--asdf");
- target.set_complete_static_lib(true);
-
- TestTarget baz(setup, "//foo:baz", Target::STATIC_LIBRARY);
- baz.sources().push_back(SourceFile("//foo/input2.cc"));
-
- target.public_deps().push_back(LabelTargetPair(&baz));
-
- ASSERT_TRUE(target.OnResolved(&err));
- ASSERT_TRUE(baz.OnResolved(&err));
-
- // A complete static library that depends on an incomplete static library
- // should link in the dependent object files as if the dependent target
- // were a source set.
- {
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = libbar\n"
- "\n"
- "build obj/foo/libbar.input1.o: cxx ../../foo/input1.cc\n"
- "\n"
- "build obj/foo/libbar.a: alink obj/foo/libbar.input1.o "
- "obj/foo/libbaz.input2.o || obj/foo/libbaz.a\n"
- " arflags = --asdf\n"
- " output_extension = \n"
- " output_dir = \n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
- }
-
- // Make the dependent static library complete.
- baz.set_complete_static_lib(true);
-
- // Dependent complete static libraries should not be linked directly.
- {
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = libbar\n"
- "\n"
- "build obj/foo/libbar.input1.o: cxx ../../foo/input1.cc\n"
- "\n"
- "build obj/foo/libbar.a: alink obj/foo/libbar.input1.o "
- "|| obj/foo/libbaz.a\n"
- " arflags = --asdf\n"
- " output_extension = \n"
- " output_dir = \n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
- }
-}
-
-// This tests that output extension and output dir overrides apply, and input
-// dependencies are applied.
-TEST_F(NinjaBinaryTargetWriterTest, OutputExtensionAndInputDeps) {
- Err err;
- TestWithScope setup;
-
- // An action for our library to depend on.
- Target action(setup.settings(), Label(SourceDir("//foo/"), "action"));
- action.set_output_type(Target::ACTION_FOREACH);
- action.visibility().SetPublic();
- action.SetToolchain(setup.toolchain());
- ASSERT_TRUE(action.OnResolved(&err));
-
- // A shared library w/ the output_extension set to a custom value.
- Target target(setup.settings(), Label(SourceDir("//foo/"), "shlib"));
- target.set_output_type(Target::SHARED_LIBRARY);
- target.set_output_extension(std::string("so.6"));
- target.set_output_dir(SourceDir("//out/Debug/foo/"));
- target.sources().push_back(SourceFile("//foo/input1.cc"));
- target.sources().push_back(SourceFile("//foo/input2.cc"));
- target.public_deps().push_back(LabelTargetPair(&action));
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = libshlib\n"
- "\n"
- "build obj/foo/libshlib.input1.o: cxx ../../foo/input1.cc"
- " || obj/foo/action.stamp\n"
- "build obj/foo/libshlib.input2.o: cxx ../../foo/input2.cc"
- " || obj/foo/action.stamp\n"
- "\n"
- "build ./libshlib.so.6: solink obj/foo/libshlib.input1.o "
- // The order-only dependency here is stricly unnecessary since the
- // sources list this as an order-only dep. See discussion in the code
- // that writes this.
- "obj/foo/libshlib.input2.o || obj/foo/action.stamp\n"
- " ldflags =\n"
- " libs =\n"
- " output_extension = .so.6\n"
- " output_dir = foo\n";
-
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
-}
-
-TEST_F(NinjaBinaryTargetWriterTest, NoHardDepsToNoPublicHeaderTarget) {
- Err err;
- TestWithScope setup;
-
- SourceFile generated_file("//out/Debug/generated.cc");
-
- // An action does code generation.
- Target action(setup.settings(), Label(SourceDir("//foo/"), "generate"));
- action.set_output_type(Target::ACTION);
- action.visibility().SetPublic();
- action.SetToolchain(setup.toolchain());
- action.set_output_dir(SourceDir("//out/Debug/foo/"));
- action.action_values().outputs() =
- SubstitutionList::MakeForTest("//out/Debug/generated.cc");
- ASSERT_TRUE(action.OnResolved(&err));
-
- // A source set compiling geneated code, this target does not publicize any
- // headers.
- Target gen_obj(setup.settings(), Label(SourceDir("//foo/"), "gen_obj"));
- gen_obj.set_output_type(Target::SOURCE_SET);
- gen_obj.set_output_dir(SourceDir("//out/Debug/foo/"));
- gen_obj.sources().push_back(generated_file);
- gen_obj.visibility().SetPublic();
- gen_obj.private_deps().push_back(LabelTargetPair(&action));
- gen_obj.set_all_headers_public(false);
- gen_obj.SetToolchain(setup.toolchain());
- ASSERT_TRUE(gen_obj.OnResolved(&err));
-
- std::ostringstream obj_out;
- NinjaBinaryTargetWriter obj_writer(&gen_obj, obj_out);
- obj_writer.Run();
-
- const char obj_expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = gen_obj\n"
- "\n"
- "build obj/out/Debug/gen_obj.generated.o: cxx generated.cc"
- " || obj/foo/generate.stamp\n"
- "\n"
- "build obj/foo/gen_obj.stamp: stamp obj/out/Debug/gen_obj.generated.o"
- // The order-only dependency here is strictly unnecessary since the
- // sources list this as an order-only dep.
- " || obj/foo/generate.stamp\n";
-
- std::string obj_str = obj_out.str();
- EXPECT_EQ(obj_expected, obj_str);
-
- // A shared library depends on gen_obj, having corresponding header for
- // generated obj.
- Target gen_lib(setup.settings(), Label(SourceDir("//foo/"), "gen_lib"));
- gen_lib.set_output_type(Target::SHARED_LIBRARY);
- gen_lib.set_output_dir(SourceDir("//out/Debug/foo/"));
- gen_lib.sources().push_back(SourceFile("//foor/generated.h"));
- gen_lib.visibility().SetPublic();
- gen_lib.private_deps().push_back(LabelTargetPair(&gen_obj));
- gen_lib.SetToolchain(setup.toolchain());
- ASSERT_TRUE(gen_lib.OnResolved(&err));
-
- std::ostringstream lib_out;
- NinjaBinaryTargetWriter lib_writer(&gen_lib, lib_out);
- lib_writer.Run();
-
- const char lib_expected[] =
- "defines =\n"
- "include_dirs =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = libgen_lib\n"
- "\n"
- "\n"
- "build ./libgen_lib.so: solink obj/out/Debug/gen_obj.generated.o"
- // The order-only dependency here is strictly unnecessary since
- // obj/out/Debug/gen_obj.generated.o has dependency to
- // obj/foo/gen_obj.stamp
- " || obj/foo/gen_obj.stamp\n"
- " ldflags =\n"
- " libs =\n"
- " output_extension = .so\n"
- " output_dir = foo\n";
-
- std::string lib_str = lib_out.str();
- EXPECT_EQ(lib_expected, lib_str);
-
- // An executable depends on gen_lib.
- Target executable(setup.settings(),
- Label(SourceDir("//foo/"), "final_target"));
- executable.set_output_type(Target::EXECUTABLE);
- executable.set_output_dir(SourceDir("//out/Debug/foo/"));
- executable.sources().push_back(SourceFile("//foo/main.cc"));
- executable.private_deps().push_back(LabelTargetPair(&gen_lib));
- executable.SetToolchain(setup.toolchain());
- ASSERT_TRUE(executable.OnResolved(&err)) << err.message();
-
- std::ostringstream final_out;
- NinjaBinaryTargetWriter final_writer(&executable, final_out);
- final_writer.Run();
-
- // There is no order only dependency to action target.
- const char final_expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = final_target\n"
- "\n"
- "build obj/foo/final_target.main.o: cxx ../../foo/main.cc\n"
- "\n"
- "build ./final_target: link obj/foo/final_target.main.o"
- " ./libgen_lib.so\n"
- " ldflags =\n"
- " libs =\n"
- " output_extension = \n"
- " output_dir = foo\n";
-
- std::string final_str = final_out.str();
- EXPECT_EQ(final_expected, final_str);
-}
-
-// Tests libs are applied.
-TEST_F(NinjaBinaryTargetWriterTest, LibsAndLibDirs) {
- Err err;
- TestWithScope setup;
-
- // A shared library w/ libs and lib_dirs.
- Target target(setup.settings(), Label(SourceDir("//foo/"), "shlib"));
- target.set_output_type(Target::SHARED_LIBRARY);
- target.config_values().libs().push_back(LibFile(SourceFile("//foo/lib1.a")));
- target.config_values().libs().push_back(LibFile("foo"));
- target.config_values().lib_dirs().push_back(SourceDir("//foo/bar/"));
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = libshlib\n"
- "\n"
- "\n"
- "build ./libshlib.so: solink | ../../foo/lib1.a\n"
- " ldflags = -L../../foo/bar\n"
- " libs = ../../foo/lib1.a -lfoo\n"
- " output_extension = .so\n"
- " output_dir = \n";
-
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
-}
-
-TEST_F(NinjaBinaryTargetWriterTest, EmptyOutputExtension) {
- Err err;
- TestWithScope setup;
-
- // This test is the same as OutputExtensionAndInputDeps, except that we call
- // set_output_extension("") and ensure that we get an empty one and override
- // the output prefix so that the name matches the target exactly.
- Target target(setup.settings(), Label(SourceDir("//foo/"), "shlib"));
- target.set_output_type(Target::SHARED_LIBRARY);
- target.set_output_prefix_override(true);
- target.set_output_extension(std::string());
- target.sources().push_back(SourceFile("//foo/input1.cc"));
- target.sources().push_back(SourceFile("//foo/input2.cc"));
-
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = shlib\n"
- "\n"
- "build obj/foo/shlib.input1.o: cxx ../../foo/input1.cc\n"
- "build obj/foo/shlib.input2.o: cxx ../../foo/input2.cc\n"
- "\n"
- "build ./shlib: solink obj/foo/shlib.input1.o "
- "obj/foo/shlib.input2.o\n"
- " ldflags =\n"
- " libs =\n"
- " output_extension = \n"
- " output_dir = \n";
-
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
-}
-
-TEST_F(NinjaBinaryTargetWriterTest, SourceSetDataDeps) {
- Err err;
- TestWithScope setup;
-
- // This target is a data (runtime) dependency of the intermediate target.
- Target data(setup.settings(), Label(SourceDir("//foo/"), "data_target"));
- data.set_output_type(Target::EXECUTABLE);
- data.visibility().SetPublic();
- data.SetToolchain(setup.toolchain());
- ASSERT_TRUE(data.OnResolved(&err));
-
- // Intermediate source set target.
- Target inter(setup.settings(), Label(SourceDir("//foo/"), "inter"));
- inter.set_output_type(Target::SOURCE_SET);
- inter.visibility().SetPublic();
- inter.data_deps().push_back(LabelTargetPair(&data));
- inter.SetToolchain(setup.toolchain());
- inter.sources().push_back(SourceFile("//foo/inter.cc"));
- ASSERT_TRUE(inter.OnResolved(&err)) << err.message();
-
- // Write out the intermediate target.
- std::ostringstream inter_out;
- NinjaBinaryTargetWriter inter_writer(&inter, inter_out);
- inter_writer.Run();
-
- // The intermediate source set will be a stamp file that depends on the
- // object files, and will have an order-only dependency on its data dep and
- // data file.
- const char inter_expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = inter\n"
- "\n"
- "build obj/foo/inter.inter.o: cxx ../../foo/inter.cc\n"
- "\n"
- "build obj/foo/inter.stamp: stamp obj/foo/inter.inter.o || "
- "./data_target\n";
- EXPECT_EQ(inter_expected, inter_out.str());
-
- // Final target.
- Target exe(setup.settings(), Label(SourceDir("//foo/"), "exe"));
- exe.set_output_type(Target::EXECUTABLE);
- exe.public_deps().push_back(LabelTargetPair(&inter));
- exe.SetToolchain(setup.toolchain());
- exe.sources().push_back(SourceFile("//foo/final.cc"));
- ASSERT_TRUE(exe.OnResolved(&err));
-
- std::ostringstream final_out;
- NinjaBinaryTargetWriter final_writer(&exe, final_out);
- final_writer.Run();
-
- // The final output depends on both object files (one from the final target,
- // one from the source set) and has an order-only dependency on the source
- // set's stamp file and the final target's data file. The source set stamp
- // dependency will create an implicit order-only dependency on the data
- // target.
- const char final_expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = exe\n"
- "\n"
- "build obj/foo/exe.final.o: cxx ../../foo/final.cc\n"
- "\n"
- "build ./exe: link obj/foo/exe.final.o obj/foo/inter.inter.o || "
- "obj/foo/inter.stamp\n"
- " ldflags =\n"
- " libs =\n"
- " output_extension = \n"
- " output_dir = \n";
- EXPECT_EQ(final_expected, final_out.str());
-}
-
-TEST_F(NinjaBinaryTargetWriterTest, SharedLibraryModuleDefinitionFile) {
- Err err;
- TestWithScope setup;
-
- Target shared_lib(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- shared_lib.set_output_type(Target::SHARED_LIBRARY);
- shared_lib.SetToolchain(setup.toolchain());
- shared_lib.sources().push_back(SourceFile("//foo/sources.cc"));
- shared_lib.sources().push_back(SourceFile("//foo/bar.def"));
- ASSERT_TRUE(shared_lib.OnResolved(&err));
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&shared_lib, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = libbar\n"
- "\n"
- "build obj/foo/libbar.sources.o: cxx ../../foo/sources.cc\n"
- "\n"
- "build ./libbar.so: solink obj/foo/libbar.sources.o | ../../foo/bar.def\n"
- " ldflags = /DEF:../../foo/bar.def\n"
- " libs =\n"
- " output_extension = .so\n"
- " output_dir = \n";
- EXPECT_EQ(expected, out.str());
-}
-
-TEST_F(NinjaBinaryTargetWriterTest, LoadableModule) {
- Err err;
- TestWithScope setup;
-
- Target loadable_module(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- loadable_module.set_output_type(Target::LOADABLE_MODULE);
- loadable_module.visibility().SetPublic();
- loadable_module.SetToolchain(setup.toolchain());
- loadable_module.sources().push_back(SourceFile("//foo/sources.cc"));
- ASSERT_TRUE(loadable_module.OnResolved(&err)) << err.message();
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&loadable_module, out);
- writer.Run();
-
- const char loadable_expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = libbar\n"
- "\n"
- "build obj/foo/libbar.sources.o: cxx ../../foo/sources.cc\n"
- "\n"
- "build ./libbar.so: solink_module obj/foo/libbar.sources.o\n"
- " ldflags =\n"
- " libs =\n"
- " output_extension = .so\n"
- " output_dir = \n";
- EXPECT_EQ(loadable_expected, out.str());
-
- // Final target.
- Target exe(setup.settings(), Label(SourceDir("//foo/"), "exe"));
- exe.set_output_type(Target::EXECUTABLE);
- exe.public_deps().push_back(LabelTargetPair(&loadable_module));
- exe.SetToolchain(setup.toolchain());
- exe.sources().push_back(SourceFile("//foo/final.cc"));
- ASSERT_TRUE(exe.OnResolved(&err)) << err.message();
-
- std::ostringstream final_out;
- NinjaBinaryTargetWriter final_writer(&exe, final_out);
- final_writer.Run();
-
- // The final output depends on the loadable module so should have an
- // order-only dependency on the loadable modules's output file.
- const char final_expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = exe\n"
- "\n"
- "build obj/foo/exe.final.o: cxx ../../foo/final.cc\n"
- "\n"
- "build ./exe: link obj/foo/exe.final.o || ./libbar.so\n"
- " ldflags =\n"
- " libs =\n"
- " output_extension = \n"
- " output_dir = \n";
- EXPECT_EQ(final_expected, final_out.str());
-}
-
-TEST_F(NinjaBinaryTargetWriterTest, WinPrecompiledHeaders) {
- Err err;
-
- // This setup's toolchain does not have precompiled headers defined.
- TestWithScope setup;
-
- // A precompiled header toolchain.
- Settings pch_settings(setup.build_settings(), "withpch/");
- Toolchain pch_toolchain(&pch_settings,
- Label(SourceDir("//toolchain/"), "withpch"));
- pch_settings.set_toolchain_label(pch_toolchain.label());
- pch_settings.set_default_toolchain_label(setup.toolchain()->label());
-
- // Declare a C++ compiler that supports PCH.
- std::unique_ptr<Tool> cxx_tool = std::make_unique<Tool>();
- TestWithScope::SetCommandForTool(
- "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} "
- "-o {{output}}",
- cxx_tool.get());
- cxx_tool->set_outputs(SubstitutionList::MakeForTest(
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
- cxx_tool->set_precompiled_header_type(Tool::PCH_MSVC);
- pch_toolchain.SetTool(Toolchain::TYPE_CXX, std::move(cxx_tool));
-
- // Add a C compiler as well.
- std::unique_ptr<Tool> cc_tool = std::make_unique<Tool>();
- TestWithScope::SetCommandForTool(
- "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} "
- "-o {{output}}",
- cc_tool.get());
- cc_tool->set_outputs(SubstitutionList::MakeForTest(
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
- cc_tool->set_precompiled_header_type(Tool::PCH_MSVC);
- pch_toolchain.SetTool(Toolchain::TYPE_CC, std::move(cc_tool));
- pch_toolchain.ToolchainSetupComplete();
-
- // This target doesn't specify precompiled headers.
- {
- Target no_pch_target(&pch_settings,
- Label(SourceDir("//foo/"), "no_pch_target"));
- no_pch_target.set_output_type(Target::SOURCE_SET);
- no_pch_target.visibility().SetPublic();
- no_pch_target.sources().push_back(SourceFile("//foo/input1.cc"));
- no_pch_target.sources().push_back(SourceFile("//foo/input2.c"));
- no_pch_target.config_values().cflags_c().push_back("-std=c99");
- no_pch_target.SetToolchain(&pch_toolchain);
- ASSERT_TRUE(no_pch_target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&no_pch_target, out);
- writer.Run();
-
- const char no_pch_expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_c = -std=c99\n"
- "cflags_cc =\n"
- "target_output_name = no_pch_target\n"
- "\n"
- "build withpch/obj/foo/no_pch_target.input1.o: "
- "withpch_cxx ../../foo/input1.cc\n"
- "build withpch/obj/foo/no_pch_target.input2.o: "
- "withpch_cc ../../foo/input2.c\n"
- "\n"
- "build withpch/obj/foo/no_pch_target.stamp: "
- "withpch_stamp withpch/obj/foo/no_pch_target.input1.o "
- "withpch/obj/foo/no_pch_target.input2.o\n";
- EXPECT_EQ(no_pch_expected, out.str());
- }
-
- // This target specifies PCH.
- {
- Target pch_target(&pch_settings, Label(SourceDir("//foo/"), "pch_target"));
- pch_target.config_values().set_precompiled_header("build/precompile.h");
- pch_target.config_values().set_precompiled_source(
- SourceFile("//build/precompile.cc"));
- pch_target.set_output_type(Target::SOURCE_SET);
- pch_target.visibility().SetPublic();
- pch_target.sources().push_back(SourceFile("//foo/input1.cc"));
- pch_target.sources().push_back(SourceFile("//foo/input2.c"));
- pch_target.SetToolchain(&pch_toolchain);
- ASSERT_TRUE(pch_target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&pch_target, out);
- writer.Run();
-
- const char pch_win_expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- // It should output language-specific pch files.
- "cflags_c = /Fpwithpch/obj/foo/pch_target_c.pch "
- "/Yubuild/precompile.h\n"
- "cflags_cc = /Fpwithpch/obj/foo/pch_target_cc.pch "
- "/Yubuild/precompile.h\n"
- "target_output_name = pch_target\n"
- "\n"
- // Compile the precompiled source files with /Yc.
- "build withpch/obj/build/pch_target.precompile.c.o: "
- "withpch_cc ../../build/precompile.cc\n"
- " cflags_c = ${cflags_c} /Ycbuild/precompile.h\n"
- "\n"
- "build withpch/obj/build/pch_target.precompile.cc.o: "
- "withpch_cxx ../../build/precompile.cc\n"
- " cflags_cc = ${cflags_cc} /Ycbuild/precompile.h\n"
- "\n"
- "build withpch/obj/foo/pch_target.input1.o: "
- "withpch_cxx ../../foo/input1.cc | "
- // Explicit dependency on the PCH build step.
- "withpch/obj/build/pch_target.precompile.cc.o\n"
- "build withpch/obj/foo/pch_target.input2.o: "
- "withpch_cc ../../foo/input2.c | "
- // Explicit dependency on the PCH build step.
- "withpch/obj/build/pch_target.precompile.c.o\n"
- "\n"
- "build withpch/obj/foo/pch_target.stamp: withpch_stamp "
- "withpch/obj/foo/pch_target.input1.o "
- "withpch/obj/foo/pch_target.input2.o "
- // The precompiled object files were added to the outputs.
- "withpch/obj/build/pch_target.precompile.c.o "
- "withpch/obj/build/pch_target.precompile.cc.o\n";
- EXPECT_EQ(pch_win_expected, out.str());
- }
-}
-
-TEST_F(NinjaBinaryTargetWriterTest, GCCPrecompiledHeaders) {
- Err err;
-
- // This setup's toolchain does not have precompiled headers defined.
- TestWithScope setup;
-
- // A precompiled header toolchain.
- Settings pch_settings(setup.build_settings(), "withpch/");
- Toolchain pch_toolchain(&pch_settings,
- Label(SourceDir("//toolchain/"), "withpch"));
- pch_settings.set_toolchain_label(pch_toolchain.label());
- pch_settings.set_default_toolchain_label(setup.toolchain()->label());
-
- // Declare a C++ compiler that supports PCH.
- std::unique_ptr<Tool> cxx_tool = std::make_unique<Tool>();
- TestWithScope::SetCommandForTool(
- "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} "
- "-o {{output}}",
- cxx_tool.get());
- cxx_tool->set_outputs(SubstitutionList::MakeForTest(
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
- cxx_tool->set_precompiled_header_type(Tool::PCH_GCC);
- pch_toolchain.SetTool(Toolchain::TYPE_CXX, std::move(cxx_tool));
- pch_toolchain.ToolchainSetupComplete();
-
- // Add a C compiler as well.
- std::unique_ptr<Tool> cc_tool = std::make_unique<Tool>();
- TestWithScope::SetCommandForTool(
- "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} "
- "-o {{output}}",
- cc_tool.get());
- cc_tool->set_outputs(SubstitutionList::MakeForTest(
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
- cc_tool->set_precompiled_header_type(Tool::PCH_GCC);
- pch_toolchain.SetTool(Toolchain::TYPE_CC, std::move(cc_tool));
- pch_toolchain.ToolchainSetupComplete();
-
- // This target doesn't specify precompiled headers.
- {
- Target no_pch_target(&pch_settings,
- Label(SourceDir("//foo/"), "no_pch_target"));
- no_pch_target.set_output_type(Target::SOURCE_SET);
- no_pch_target.visibility().SetPublic();
- no_pch_target.sources().push_back(SourceFile("//foo/input1.cc"));
- no_pch_target.sources().push_back(SourceFile("//foo/input2.c"));
- no_pch_target.config_values().cflags_c().push_back("-std=c99");
- no_pch_target.SetToolchain(&pch_toolchain);
- ASSERT_TRUE(no_pch_target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&no_pch_target, out);
- writer.Run();
-
- const char no_pch_expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_c = -std=c99\n"
- "cflags_cc =\n"
- "target_output_name = no_pch_target\n"
- "\n"
- "build withpch/obj/foo/no_pch_target.input1.o: "
- "withpch_cxx ../../foo/input1.cc\n"
- "build withpch/obj/foo/no_pch_target.input2.o: "
- "withpch_cc ../../foo/input2.c\n"
- "\n"
- "build withpch/obj/foo/no_pch_target.stamp: "
- "withpch_stamp withpch/obj/foo/no_pch_target.input1.o "
- "withpch/obj/foo/no_pch_target.input2.o\n";
- EXPECT_EQ(no_pch_expected, out.str());
- }
-
- // This target specifies PCH.
- {
- Target pch_target(&pch_settings, Label(SourceDir("//foo/"), "pch_target"));
- pch_target.config_values().set_precompiled_source(
- SourceFile("//build/precompile.h"));
- pch_target.config_values().cflags_c().push_back("-std=c99");
- pch_target.set_output_type(Target::SOURCE_SET);
- pch_target.visibility().SetPublic();
- pch_target.sources().push_back(SourceFile("//foo/input1.cc"));
- pch_target.sources().push_back(SourceFile("//foo/input2.c"));
- pch_target.SetToolchain(&pch_toolchain);
- ASSERT_TRUE(pch_target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&pch_target, out);
- writer.Run();
-
- const char pch_gcc_expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_c = -std=c99 "
- "-include withpch/obj/build/pch_target.precompile.h-c\n"
- "cflags_cc = -include withpch/obj/build/pch_target.precompile.h-cc\n"
- "target_output_name = pch_target\n"
- "\n"
- // Compile the precompiled sources with -x <lang>.
- "build withpch/obj/build/pch_target.precompile.h-c.gch: "
- "withpch_cc ../../build/precompile.h\n"
- " cflags_c = -std=c99 -x c-header\n"
- "\n"
- "build withpch/obj/build/pch_target.precompile.h-cc.gch: "
- "withpch_cxx ../../build/precompile.h\n"
- " cflags_cc = -x c++-header\n"
- "\n"
- "build withpch/obj/foo/pch_target.input1.o: "
- "withpch_cxx ../../foo/input1.cc | "
- // Explicit dependency on the PCH build step.
- "withpch/obj/build/pch_target.precompile.h-cc.gch\n"
- "build withpch/obj/foo/pch_target.input2.o: "
- "withpch_cc ../../foo/input2.c | "
- // Explicit dependency on the PCH build step.
- "withpch/obj/build/pch_target.precompile.h-c.gch\n"
- "\n"
- "build withpch/obj/foo/pch_target.stamp: "
- "withpch_stamp withpch/obj/foo/pch_target.input1.o "
- "withpch/obj/foo/pch_target.input2.o\n";
- EXPECT_EQ(pch_gcc_expected, out.str());
- }
-}
-
-// Should throw an error with the scheduler if a duplicate object file exists.
-// This is dependent on the toolchain's object file mapping.
-TEST_F(NinjaBinaryTargetWriterTest, DupeObjFileError) {
- TestWithScope setup;
- TestTarget target(setup, "//foo:bar", Target::EXECUTABLE);
- target.sources().push_back(SourceFile("//a.cc"));
- target.sources().push_back(SourceFile("//a.cc"));
-
- EXPECT_FALSE(scheduler().is_failed());
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&target, out);
- writer.Run();
-
- // Should have issued an error.
- EXPECT_TRUE(scheduler().is_failed());
-}
-
-// This tests that output extension and output dir overrides apply, and input
-// dependencies are applied.
-TEST_F(NinjaBinaryTargetWriterTest, InputFiles) {
- Err err;
- TestWithScope setup;
-
- // This target has one input.
- {
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::SOURCE_SET);
- target.visibility().SetPublic();
- target.sources().push_back(SourceFile("//foo/input1.cc"));
- target.sources().push_back(SourceFile("//foo/input2.cc"));
- target.config_values().inputs().push_back(SourceFile("//foo/input.data"));
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = bar\n"
- "\n"
- "build obj/foo/bar.input1.o: cxx ../../foo/input1.cc"
- " | ../../foo/input.data\n"
- "build obj/foo/bar.input2.o: cxx ../../foo/input2.cc"
- " | ../../foo/input.data\n"
- "\n"
- "build obj/foo/bar.stamp: stamp obj/foo/bar.input1.o "
- "obj/foo/bar.input2.o\n";
-
- EXPECT_EQ(expected, out.str());
- }
-
- // This target has one input but no source files.
- {
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::SHARED_LIBRARY);
- target.visibility().SetPublic();
- target.config_values().inputs().push_back(SourceFile("//foo/input.data"));
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = libbar\n"
- "\n"
- "\n"
- "build ./libbar.so: solink | ../../foo/input.data\n"
- " ldflags =\n"
- " libs =\n"
- " output_extension = .so\n"
- " output_dir = \n";
-
- EXPECT_EQ(expected, out.str());
- }
-
- // This target has multiple inputs.
- {
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::SOURCE_SET);
- target.visibility().SetPublic();
- target.sources().push_back(SourceFile("//foo/input1.cc"));
- target.sources().push_back(SourceFile("//foo/input2.cc"));
- target.config_values().inputs().push_back(SourceFile("//foo/input1.data"));
- target.config_values().inputs().push_back(SourceFile("//foo/input2.data"));
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = bar\n"
- "\n"
- "build obj/foo/bar.inputs.stamp: stamp"
- " ../../foo/input1.data ../../foo/input2.data\n"
- "build obj/foo/bar.input1.o: cxx ../../foo/input1.cc"
- " | obj/foo/bar.inputs.stamp\n"
- "build obj/foo/bar.input2.o: cxx ../../foo/input2.cc"
- " | obj/foo/bar.inputs.stamp\n"
- "\n"
- "build obj/foo/bar.stamp: stamp obj/foo/bar.input1.o "
- "obj/foo/bar.input2.o\n";
-
- EXPECT_EQ(expected, out.str());
- }
-
- // This target has one input itself, one from an immediate config, and one
- // from a config tacked on to said config.
- {
- Config far_config(setup.settings(), Label(SourceDir("//foo/"), "qux"));
- far_config.own_values().inputs().push_back(SourceFile("//foo/input3.data"));
- ASSERT_TRUE(far_config.OnResolved(&err));
-
- Config config(setup.settings(), Label(SourceDir("//foo/"), "baz"));
- config.own_values().inputs().push_back(SourceFile("//foo/input2.data"));
- config.configs().push_back(LabelConfigPair(&far_config));
- ASSERT_TRUE(config.OnResolved(&err));
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::SOURCE_SET);
- target.visibility().SetPublic();
- target.sources().push_back(SourceFile("//foo/input1.cc"));
- target.sources().push_back(SourceFile("//foo/input2.cc"));
- target.config_values().inputs().push_back(SourceFile("//foo/input1.data"));
- target.configs().push_back(LabelConfigPair(&config));
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaBinaryTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected[] =
- "defines =\n"
- "include_dirs =\n"
- "cflags =\n"
- "cflags_cc =\n"
- "root_out_dir = .\n"
- "target_out_dir = obj/foo\n"
- "target_output_name = bar\n"
- "\n"
- "build obj/foo/bar.inputs.stamp: stamp"
- " ../../foo/input1.data ../../foo/input2.data ../../foo/input3.data\n"
- "build obj/foo/bar.input1.o: cxx ../../foo/input1.cc"
- " | obj/foo/bar.inputs.stamp\n"
- "build obj/foo/bar.input2.o: cxx ../../foo/input2.cc"
- " | obj/foo/bar.inputs.stamp\n"
- "\n"
- "build obj/foo/bar.stamp: stamp obj/foo/bar.input1.o "
- "obj/foo/bar.input2.o\n";
-
- EXPECT_EQ(expected, out.str());
- }
-}
diff --git a/chromium/tools/gn/ninja_build_writer.cc b/chromium/tools/gn/ninja_build_writer.cc
deleted file mode 100644
index 075592c2b46..00000000000
--- a/chromium/tools/gn/ninja_build_writer.cc
+++ /dev/null
@@ -1,594 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/ninja_build_writer.h"
-
-#include <stddef.h>
-
-#include <fstream>
-#include <map>
-#include <sstream>
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/path_service.h"
-#include "base/process/process_handle.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/builder.h"
-#include "tools/gn/err.h"
-#include "tools/gn/escape.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/input_file_manager.h"
-#include "tools/gn/loader.h"
-#include "tools/gn/ninja_utils.h"
-#include "tools/gn/pool.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/switches.h"
-#include "tools/gn/target.h"
-#include "tools/gn/trace.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-namespace {
-
-struct Counts {
- Counts() : count(0), last_seen(nullptr) {}
-
- // Number of targets of this type.
- int count;
-
- // The last one we encountered.
- const Target* last_seen;
-};
-
-std::string GetSelfInvocationCommand(const BuildSettings* build_settings) {
- const base::FilePath build_path =
- build_settings->build_dir().Resolve(build_settings->root_path());
-
- base::FilePath exe_path;
- base::PathService::Get(base::FILE_EXE, &exe_path);
- if (build_path.IsAbsolute())
- exe_path = MakeAbsoluteFilePathRelativeIfPossible(build_path, exe_path);
-
- base::CommandLine cmdline(exe_path.NormalizePathSeparatorsTo('/'));
-
- // Use "." for the directory to generate. When Ninja runs the command it
- // will have the build directory as the current one. Coding it explicitly
- // will cause everything to get confused if the user renames the directory.
- cmdline.AppendArg("gen");
- cmdline.AppendArg(".");
-
- base::FilePath root_path = build_settings->root_path();
- if (build_path.IsAbsolute())
- root_path = MakeAbsoluteFilePathRelativeIfPossible(build_path, root_path);
-
- cmdline.AppendSwitchPath(std::string("--") + switches::kRoot,
- root_path.NormalizePathSeparatorsTo('/'));
- // Successful automatic invocations shouldn't print output.
- cmdline.AppendSwitch(std::string("-") + switches::kQuiet);
-
- EscapeOptions escape_shell;
- escape_shell.mode = ESCAPE_NINJA_COMMAND;
-#if defined(OS_WIN)
- // The command line code quoting varies by platform. We have one string,
- // possibly with spaces, that we want to quote. The Windows command line
- // quotes again, so we don't want quoting. The Posix one doesn't.
- escape_shell.inhibit_quoting = true;
-#endif
-
- const base::CommandLine& our_cmdline =
- *base::CommandLine::ForCurrentProcess();
- const base::CommandLine::SwitchMap& switches = our_cmdline.GetSwitches();
- for (base::CommandLine::SwitchMap::const_iterator i = switches.begin();
- i != switches.end(); ++i) {
- // Only write arguments we haven't already written. Always skip "args"
- // since those will have been written to the file and will be used
- // implicitly in the future. Keeping --args would mean changes to the file
- // would be ignored.
- if (i->first != switches::kQuiet &&
- i->first != switches::kRoot &&
- i->first != switches::kArgs) {
- std::string escaped_value =
- EscapeString(FilePathToUTF8(i->second), escape_shell, nullptr);
- cmdline.AppendSwitchASCII(i->first, escaped_value);
- }
- }
-
-#if defined(OS_WIN)
- return base::WideToUTF8(cmdline.GetCommandLineString());
-#else
- return cmdline.GetCommandLineString();
-#endif
-}
-
-// Given an output that appears more than once, generates an error message
-// that describes the problem and which targets generate it.
-Err GetDuplicateOutputError(const std::vector<const Target*>& all_targets,
- const OutputFile& bad_output) {
- std::vector<const Target*> matches;
- for (const Target* target : all_targets) {
- for (const auto& output : target->computed_outputs()) {
- if (output == bad_output) {
- matches.push_back(target);
- break;
- }
- }
- }
-
- // There should always be at least two targets generating this file for this
- // function to be called in the first place.
- DCHECK(matches.size() >= 2);
- std::string matches_string;
- for (const Target* target : matches)
- matches_string += " " + target->label().GetUserVisibleName(false) + "\n";
-
- Err result(matches[0]->defined_from(), "Duplicate output file.",
- "Two or more targets generate the same output:\n " +
- bad_output.value() + "\n\n"
- "This is can often be fixed by changing one of the target names, or by \n"
- "setting an output_name on one of them.\n"
- "\nCollisions:\n" + matches_string);
- for (size_t i = 1; i < matches.size(); i++)
- result.AppendSubErr(Err(matches[i]->defined_from(), "Collision."));
- return result;
-}
-
-// Given two toolchains with the same name, generates an error message
-// that describes the problem.
-Err GetDuplicateToolchainError(const SourceFile& source_file,
- const Toolchain* previous_toolchain,
- const Toolchain* toolchain) {
- Err result(toolchain->defined_from(), "Duplicate toolchain.",
- "Two or more toolchains write to the same directory:\n " +
- source_file.GetDir().value() + "\n\n"
- "This can be fixed by making sure that distinct toolchains have\n"
- "distinct names.\n");
- result.AppendSubErr(
- Err(previous_toolchain->defined_from(), "Previous toolchain."));
- return result;
-}
-
-} // namespace
-
-NinjaBuildWriter::NinjaBuildWriter(
- const BuildSettings* build_settings,
- const std::unordered_map<const Settings*, const Toolchain*>&
- used_toolchains,
- const Toolchain* default_toolchain,
- const std::vector<const Target*>& default_toolchain_targets,
- std::ostream& out,
- std::ostream& dep_out)
- : build_settings_(build_settings),
- used_toolchains_(used_toolchains),
- default_toolchain_(default_toolchain),
- default_toolchain_targets_(default_toolchain_targets),
- out_(out),
- dep_out_(dep_out),
- path_output_(build_settings->build_dir(),
- build_settings->root_path_utf8(),
- ESCAPE_NINJA) {}
-
-NinjaBuildWriter::~NinjaBuildWriter() = default;
-
-bool NinjaBuildWriter::Run(Err* err) {
- WriteNinjaRules();
- WriteAllPools();
- return WriteSubninjas(err) && WritePhonyAndAllRules(err);
-}
-
-// static
-bool NinjaBuildWriter::RunAndWriteFile(
- const BuildSettings* build_settings,
- const Builder& builder,
- Err* err) {
- ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, "build.ninja");
-
- std::vector<const Target*> all_targets = builder.GetAllResolvedTargets();
- std::unordered_map<const Settings*, const Toolchain*> used_toolchains;
-
- // Find the default toolchain info.
- Label default_toolchain_label = builder.loader()->GetDefaultToolchain();
- const Settings* default_toolchain_settings =
- builder.loader()->GetToolchainSettings(default_toolchain_label);
- const Toolchain* default_toolchain =
- builder.GetToolchain(default_toolchain_label);
-
- // Most targets will be in the default toolchain. Add it at the beginning and
- // skip adding it to the list every time in the loop.
- used_toolchains[default_toolchain_settings] = default_toolchain;
-
- std::vector<const Target*> default_toolchain_targets;
- default_toolchain_targets.reserve(all_targets.size());
- for (const Target* target : all_targets) {
- if (target->settings() == default_toolchain_settings) {
- default_toolchain_targets.push_back(target);
- // The default toolchain will already have been added to the used
- // settings array.
- } else if (used_toolchains.find(target->settings()) ==
- used_toolchains.end()) {
- used_toolchains[target->settings()] =
- builder.GetToolchain(target->settings()->toolchain_label());
- }
- }
-
- std::stringstream file;
- std::stringstream depfile;
- NinjaBuildWriter gen(build_settings, used_toolchains, default_toolchain,
- default_toolchain_targets, file, depfile);
- if (!gen.Run(err))
- return false;
-
- // Unconditionally write the build.ninja. Ninja's build-out-of-date checking
- // will re-run GN when any build input is newer than build.ninja, so any time
- // the build is updated, build.ninja's timestamp needs to updated also, even
- // if the contents haven't been changed.
- base::FilePath ninja_file_name(build_settings->GetFullPath(
- SourceFile(build_settings->build_dir().value() + "build.ninja")));
- base::CreateDirectory(ninja_file_name.DirName());
- std::string ninja_contents = file.str();
- if (base::WriteFile(ninja_file_name, ninja_contents.data(),
- static_cast<int>(ninja_contents.size())) !=
- static_cast<int>(ninja_contents.size()))
- return false;
-
- // Dep file listing build dependencies.
- base::FilePath dep_file_name(build_settings->GetFullPath(
- SourceFile(build_settings->build_dir().value() + "build.ninja.d")));
- std::string dep_contents = depfile.str();
- if (base::WriteFile(dep_file_name, dep_contents.data(),
- static_cast<int>(dep_contents.size())) !=
- static_cast<int>(dep_contents.size()))
- return false;
-
- return true;
-}
-
-void NinjaBuildWriter::WriteNinjaRules() {
- out_ << "ninja_required_version = 1.7.2\n\n";
- out_ << "rule gn\n";
- out_ << " command = " << GetSelfInvocationCommand(build_settings_) << "\n";
- out_ << " description = Regenerating ninja files\n\n";
-
- // This rule will regenerate the ninja files when any input file has changed.
- out_ << "build build.ninja: gn\n"
- << " generator = 1\n"
- << " depfile = build.ninja.d\n";
-
- // Input build files. These go in the ".d" file. If we write them as
- // dependencies in the .ninja file itself, ninja will expect the files to
- // exist and will error if they don't. When files are listed in a depfile,
- // missing files are ignored.
- dep_out_ << "build.ninja:";
- std::vector<base::FilePath> input_files;
- g_scheduler->input_file_manager()->GetAllPhysicalInputFileNames(&input_files);
-
- // Other files read by the build.
- std::vector<base::FilePath> other_files = g_scheduler->GetGenDependencies();
-
- // Sort the input files to order them deterministically.
- // Additionally, remove duplicate filepaths that seem to creep in.
- std::set<base::FilePath> fileset(input_files.begin(), input_files.end());
- fileset.insert(other_files.begin(), other_files.end());
-
- const base::FilePath build_path =
- build_settings_->build_dir().Resolve(build_settings_->root_path());
- for (const auto& other_file : fileset) {
- const base::FilePath file =
- MakeAbsoluteFilePathRelativeIfPossible(build_path, other_file);
- dep_out_ << " " << FilePathToUTF8(file.NormalizePathSeparatorsTo('/'));
- }
-
- out_ << std::endl;
-}
-
-void NinjaBuildWriter::WriteAllPools() {
- // Compute the pools referenced by all tools of all used toolchains.
- std::unordered_set<const Pool*> used_pools;
- for (const auto& pair : used_toolchains_) {
- for (int j = Toolchain::TYPE_NONE + 1; j < Toolchain::TYPE_NUMTYPES; j++) {
- Toolchain::ToolType tool_type = static_cast<Toolchain::ToolType>(j);
- const Tool* tool = pair.second->GetTool(tool_type);
- if (tool && tool->pool().ptr)
- used_pools.insert(tool->pool().ptr);
- }
- }
-
- for (const Target* target : default_toolchain_targets_) {
- if (target->output_type() == Target::ACTION) {
- const LabelPtrPair<Pool>& pool = target->action_values().pool();
- if (pool.ptr)
- used_pools.insert(pool.ptr);
- }
- }
-
- // Write pools sorted by their name, to make output deterministic.
- std::vector<const Pool*> sorted_pools(used_pools.begin(), used_pools.end());
- auto pool_name = [this](const Pool* pool) {
- return pool->GetNinjaName(default_toolchain_->label());
- };
- std::sort(sorted_pools.begin(), sorted_pools.end(),
- [&pool_name](const Pool* a, const Pool* b) {
- return pool_name(a) < pool_name(b);
- });
- for (const Pool* pool : sorted_pools) {
- std::string name = pool_name(pool);
- if (name == "console")
- continue;
- out_ << "pool " << name << std::endl
- << " depth = " << pool->depth() << std::endl
- << std::endl;
- }
-}
-
-bool NinjaBuildWriter::WriteSubninjas(Err* err) {
- // Write toolchains sorted by their name, to make output deterministic.
- std::vector<std::pair<const Settings*, const Toolchain*>> sorted_settings(
- used_toolchains_.begin(), used_toolchains_.end());
- std::sort(sorted_settings.begin(), sorted_settings.end(),
- [this](const std::pair<const Settings*, const Toolchain*>& a,
- const std::pair<const Settings*, const Toolchain*>& b) {
- // Always put the default toolchain first.
- if (b.second == default_toolchain_)
- return false;
- if (a.second == default_toolchain_)
- return true;
- return GetNinjaFileForToolchain(a.first) <
- GetNinjaFileForToolchain(b.first);
- });
-
- SourceFile previous_subninja;
- const Toolchain* previous_toolchain = nullptr;
-
- for (const auto& pair : sorted_settings) {
- SourceFile subninja = GetNinjaFileForToolchain(pair.first);
-
- // Since the toolchains are sorted, comparing to the previous subninja is
- // enough to find duplicates.
- if (subninja == previous_subninja) {
- *err =
- GetDuplicateToolchainError(subninja, previous_toolchain, pair.second);
- return false;
- }
-
- out_ << "subninja ";
- path_output_.WriteFile(out_, subninja);
- out_ << std::endl;
- previous_subninja = subninja;
- previous_toolchain = pair.second;
- }
- out_ << std::endl;
- return true;
-}
-
-const char kNinjaRules_Help[] =
- R"(Ninja build rules
-
-The "all" and "default" rules
-
- All generated targets (see "gn help execution") will be added to an implicit
- build rule called "all" so "ninja all" will always compile everything. The
- default rule will be used by Ninja if no specific target is specified (just
- typing "ninja"). If there is a target named "default" in the root build file,
- it will be the default build rule, otherwise the implicit "all" rule will be
- used.
-
-Phony rules
-
- GN generates Ninja "phony" rules for targets in the default toolchain. The
- phony rules can collide with each other and with the names of generated files
- so are generated with the following priority:
-
- 1. Actual files generated by the build always take precedence.
-
- 2. Targets in the toplevel //BUILD.gn file.
-
- 3. Targets in toplevel directories matching the names of the directories.
- So "ninja foo" can be used to compile "//foo:foo". This only applies to
- the first level of directories since usually these are the most
- important (so this won't apply to "//foo/bar:bar").
-
- 4. The short names of executables if there is only one executable with that
- short name. Use "ninja doom_melon" to compile the
- "//tools/fruit:doom_melon" executable.
-
- 5. The short names of all targets if there is only one target with that
- short name.
-
- 6. Full label name with no leading slashes. So you can use
- "ninja tools/fruit:doom_melon" to build "//tools/fruit:doom_melon".
-
- 7. Labels with an implicit name part (when the short names match the
- directory). So you can use "ninja foo/bar" to compile "//foo/bar:bar".
-
- These "phony" rules are provided only for running Ninja since this matches
- people's historical expectations for building. For consistency with the rest
- of the program, GN introspection commands accept explicit labels.
-
- To explicitly compile a target in a non-default toolchain, you must give
- Ninja the exact name of the output file relative to the build directory.
-)";
-
-bool NinjaBuildWriter::WritePhonyAndAllRules(Err* err) {
- // Track rules as we generate them so we don't accidentally write a phony
- // rule that collides with something else.
- // GN internally generates an "all" target, so don't duplicate it.
- base::hash_set<std::string> written_rules;
- written_rules.insert("all");
-
- // Set if we encounter a target named "//:default".
- const Target* default_target = nullptr;
-
- // Targets in the root build file.
- std::vector<const Target*> toplevel_targets;
-
- // Targets with names matching their toplevel directories. For example
- // "//foo:foo". Expect this is the naming scheme for "big components."
- std::vector<const Target*> toplevel_dir_targets;
-
- // Tracks the number of each target with the given short name, as well
- // as the short names of executables (which will be a subset of short_names).
- std::map<std::string, Counts> short_names;
- std::map<std::string, Counts> exes;
-
- // ----------------------------------------------------
- // If you change this algorithm, update the help above!
- // ----------------------------------------------------
-
- for (const Target* target : default_toolchain_targets_) {
- const Label& label = target->label();
- const std::string& short_name = label.name();
-
- if (label.dir() == build_settings_->root_target_label().dir() &&
- short_name == "default")
- default_target = target;
-
- // Count the number of targets with the given short name.
- Counts& short_names_counts = short_names[short_name];
- short_names_counts.count++;
- short_names_counts.last_seen = target;
-
- // Count executables with the given short name.
- if (target->output_type() == Target::EXECUTABLE) {
- Counts& exes_counts = exes[short_name];
- exes_counts.count++;
- exes_counts.last_seen = target;
- }
-
- // Find targets in "important" directories.
- const std::string& dir_string = label.dir().value();
- if (dir_string.size() == 2 &&
- dir_string[0] == '/' && dir_string[1] == '/') {
- toplevel_targets.push_back(target);
- } else if (
- dir_string.size() == label.name().size() + 3 && // Size matches.
- dir_string[0] == '/' && dir_string[1] == '/' && // "//" at beginning.
- dir_string[dir_string.size() - 1] == '/' && // "/" at end.
- dir_string.compare(2, label.name().size(), label.name()) == 0) {
- toplevel_dir_targets.push_back(target);
- }
-
- // Add the output files from each target to the written rules so that
- // we don't write phony rules that collide with anything generated by the
- // build.
- //
- // If at this point there is a collision (no phony rules have been
- // generated yet), two targets make the same output so throw an error.
- for (const auto& output : target->computed_outputs()) {
- // Need to normalize because many toolchain outputs will be preceeded
- // with "./".
- std::string output_string(output.value());
- NormalizePath(&output_string);
- if (!written_rules.insert(output_string).second) {
- *err = GetDuplicateOutputError(default_toolchain_targets_, output);
- return false;
- }
- }
- }
-
- // First prefer the short names of toplevel targets.
- for (const Target* target : toplevel_targets) {
- if (written_rules.insert(target->label().name()).second)
- WritePhonyRule(target, target->label().name());
- }
-
- // Next prefer short names of toplevel dir targets.
- for (const Target* target : toplevel_dir_targets) {
- if (written_rules.insert(target->label().name()).second)
- WritePhonyRule(target, target->label().name());
- }
-
- // Write out the names labels of executables. Many toolchains will produce
- // executables in the root build directory with no extensions, so the names
- // will already exist and this will be a no-op. But on Windows such programs
- // will have extensions, and executables may override the output directory to
- // go into some other place.
- //
- // Putting this after the "toplevel" rules above also means that you can
- // steal the short name from an executable by outputting the executable to
- // a different directory or using a different output name, and writing a
- // toplevel build rule.
- for (const auto& pair : exes) {
- const Counts& counts = pair.second;
- const std::string& short_name = counts.last_seen->label().name();
- if (counts.count == 1 && written_rules.insert(short_name).second)
- WritePhonyRule(counts.last_seen, short_name);
- }
-
- // Write short names when those names are unique and not already taken.
- for (const auto& pair : short_names) {
- const Counts& counts = pair.second;
- const std::string& short_name = counts.last_seen->label().name();
- if (counts.count == 1 && written_rules.insert(short_name).second)
- WritePhonyRule(counts.last_seen, short_name);
- }
-
- // Write the label variants of the target name.
- for (const Target* target : default_toolchain_targets_) {
- const Label& label = target->label();
-
- // Write the long name "foo/bar:baz" for the target "//foo/bar:baz".
- std::string long_name = label.GetUserVisibleName(false);
- base::TrimString(long_name, "/", &long_name);
- if (written_rules.insert(long_name).second)
- WritePhonyRule(target, long_name);
-
- // Write the directory name with no target name if they match
- // (e.g. "//foo/bar:bar" -> "foo/bar").
- if (FindLastDirComponent(label.dir()) == label.name()) {
- std::string medium_name = DirectoryWithNoLastSlash(label.dir());
- base::TrimString(medium_name, "/", &medium_name);
- // That may have generated a name the same as the short name of the
- // target which we already wrote.
- if (medium_name != label.name() &&
- written_rules.insert(medium_name).second)
- WritePhonyRule(target, medium_name);
- }
- }
-
- // Write the autogenerated "all" rule.
- if (!default_toolchain_targets_.empty()) {
- out_ << "\nbuild all: phony";
-
- EscapeOptions ninja_escape;
- ninja_escape.mode = ESCAPE_NINJA;
- for (const Target* target : default_toolchain_targets_) {
- out_ << " $\n ";
- path_output_.WriteFile(out_, target->dependency_output_file());
- }
- }
- out_ << std::endl;
-
- if (default_target) {
- // Use the short name when available
- if (written_rules.find("default") != written_rules.end()) {
- out_ << "\ndefault default" << std::endl;
- } else {
- out_ << "\ndefault ";
- path_output_.WriteFile(out_, default_target->dependency_output_file());
- out_ << std::endl;
- }
- } else if (!default_toolchain_targets_.empty()) {
- out_ << "\ndefault all" << std::endl;
- }
-
- return true;
-}
-
-void NinjaBuildWriter::WritePhonyRule(const Target* target,
- const std::string& phony_name) {
- EscapeOptions ninja_escape;
- ninja_escape.mode = ESCAPE_NINJA;
-
- // Escape for special chars Ninja will handle.
- std::string escaped = EscapeString(phony_name, ninja_escape, nullptr);
-
- out_ << "build " << escaped << ": phony ";
- path_output_.WriteFile(out_, target->dependency_output_file());
- out_ << std::endl;
-}
diff --git a/chromium/tools/gn/ninja_build_writer.h b/chromium/tools/gn/ninja_build_writer.h
deleted file mode 100644
index df6d1c86a00..00000000000
--- a/chromium/tools/gn/ninja_build_writer.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_NINJA_BUILD_WRITER_H_
-#define TOOLS_GN_NINJA_BUILD_WRITER_H_
-
-#include <iosfwd>
-#include <map>
-#include <vector>
-
-#include "base/macros.h"
-#include "tools/gn/path_output.h"
-
-class Builder;
-class BuildSettings;
-class Err;
-class Settings;
-class Target;
-class Toolchain;
-
-// Generates the toplevel "build.ninja" file. This references the individual
-// toolchain files and lists all input .gn files as dependencies of the
-// build itself.
-class NinjaBuildWriter {
- public:
- NinjaBuildWriter(const BuildSettings* settings,
- const std::unordered_map<const Settings*, const Toolchain*>&
- used_toolchains,
- const Toolchain* default_toolchain,
- const std::vector<const Target*>& default_toolchain_targets,
- std::ostream& out,
- std::ostream& dep_out);
- ~NinjaBuildWriter();
-
- // The design of this class is that this static factory function takes the
- // Builder, extracts the relevant information, and passes it to the class
- // constructor. The class itself doesn't depend on the Builder at all which
- // makes testing much easier (tests integrating various functions along with
- // the Builder get very complicated).
- static bool RunAndWriteFile(
- const BuildSettings* settings,
- const Builder& builder,
- Err* err);
-
- bool Run(Err* err);
-
- private:
- void WriteNinjaRules();
- void WriteAllPools();
- bool WriteSubninjas(Err* err);
- bool WritePhonyAndAllRules(Err* err);
-
- void WritePhonyRule(const Target* target, const std::string& phony_name);
-
- const BuildSettings* build_settings_;
-
- const std::unordered_map<const Settings*, const Toolchain*>& used_toolchains_;
- const Toolchain* default_toolchain_;
- const std::vector<const Target*>& default_toolchain_targets_;
-
- std::ostream& out_;
- std::ostream& dep_out_;
- PathOutput path_output_;
-
- DISALLOW_COPY_AND_ASSIGN(NinjaBuildWriter);
-};
-
-extern const char kNinjaRules_Help[];
-
-#endif // TOOLS_GN_NINJA_BUILD_WRITER_H_
-
diff --git a/chromium/tools/gn/ninja_build_writer_unittest.cc b/chromium/tools/gn/ninja_build_writer_unittest.cc
deleted file mode 100644
index c27100c9c2c..00000000000
--- a/chromium/tools/gn/ninja_build_writer_unittest.cc
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <sstream>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/ninja_build_writer.h"
-#include "tools/gn/pool.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scheduler.h"
-#include "tools/gn/test_with_scope.h"
-
-using NinjaBuildWriterTest = TestWithScheduler;
-
-TEST_F(NinjaBuildWriterTest, TwoTargets) {
- TestWithScope setup;
- Err err;
-
- Target target_foo(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target_foo.set_output_type(Target::ACTION);
- target_foo.action_values().set_script(SourceFile("//foo/script.py"));
- target_foo.action_values().outputs() = SubstitutionList::MakeForTest(
- "//out/Debug/out1.out", "//out/Debug/out2.out");
- target_foo.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target_foo.OnResolved(&err));
-
- Target target_bar(setup.settings(), Label(SourceDir("//bar/"), "bar"));
- target_bar.set_output_type(Target::ACTION);
- target_bar.action_values().set_script(SourceFile("//bar/script.py"));
- target_bar.action_values().outputs() = SubstitutionList::MakeForTest(
- "//out/Debug/out3.out", "//out/Debug/out4.out");
- target_bar.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target_bar.OnResolved(&err));
-
- // Make a secondary toolchain that references two pools.
- Label other_toolchain_label(SourceDir("//other/"), "toolchain");
- Toolchain other_toolchain(setup.settings(), other_toolchain_label);
- TestWithScope::SetupToolchain(&other_toolchain);
-
- Pool other_regular_pool(
- setup.settings(),
- Label(SourceDir("//other/"), "depth_pool", other_toolchain_label.dir(),
- other_toolchain_label.name()));
- other_regular_pool.set_depth(42);
- other_toolchain.GetTool(Toolchain::TYPE_LINK)
- ->set_pool(LabelPtrPair<Pool>(&other_regular_pool));
-
- // The console pool must be in the default toolchain.
- Pool console_pool(setup.settings(), Label(SourceDir("//"), "console",
- setup.toolchain()->label().dir(),
- setup.toolchain()->label().name()));
- console_pool.set_depth(1);
- other_toolchain.GetTool(Toolchain::TYPE_STAMP)
- ->set_pool(LabelPtrPair<Pool>(&console_pool));
-
- // Settings to go with the other toolchain.
- Settings other_settings(setup.build_settings(), "toolchain/");
- other_settings.set_toolchain_label(other_toolchain_label);
-
- std::unordered_map<const Settings*, const Toolchain*> used_toolchains;
- used_toolchains[setup.settings()] = setup.toolchain();
- used_toolchains[&other_settings] = &other_toolchain;
-
- std::vector<const Target*> targets = { &target_foo, &target_bar };
-
- std::ostringstream ninja_out;
- std::ostringstream depfile_out;
-
- NinjaBuildWriter writer(setup.build_settings(), used_toolchains,
- setup.toolchain(), targets, ninja_out, depfile_out);
- ASSERT_TRUE(writer.Run(&err));
-
- const char expected_rule_gn[] = "rule gn\n";
- const char expected_build_ninja[] =
- "build build.ninja: gn\n"
- " generator = 1\n"
- " depfile = build.ninja.d\n";
- const char expected_other_pool[] =
- "pool other_toolchain_other_depth_pool\n"
- " depth = 42\n";
- const char expected_toolchain[] =
- "subninja toolchain.ninja\n";
- const char expected_targets[] =
- "build bar: phony obj/bar/bar.stamp\n"
- "build foo$:bar: phony obj/foo/bar.stamp\n"
- "build bar$:bar: phony obj/bar/bar.stamp\n";
- const char expected_root_target[] =
- "build all: phony $\n"
- " obj/foo/bar.stamp $\n"
- " obj/bar/bar.stamp\n";
- const char expected_default[] =
- "default all\n";
- std::string out_str = ninja_out.str();
-#define EXPECT_SNIPPET(expected) \
- EXPECT_NE(std::string::npos, out_str.find(expected)) << \
- "Expected to find: " << expected << std::endl << \
- "Within: " << out_str
- EXPECT_SNIPPET(expected_rule_gn);
- EXPECT_SNIPPET(expected_build_ninja);
- EXPECT_SNIPPET(expected_other_pool);
- EXPECT_SNIPPET(expected_toolchain);
- EXPECT_SNIPPET(expected_targets);
- EXPECT_SNIPPET(expected_root_target);
- EXPECT_SNIPPET(expected_default);
-#undef EXPECT_SNIPPET
-
- // A pool definition for ninja's built-in console pool must not be written.
- EXPECT_EQ(std::string::npos, out_str.find("pool console"));
-}
-
-TEST_F(NinjaBuildWriterTest, DuplicateOutputs) {
- TestWithScope setup;
- Err err;
-
- Target target_foo(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target_foo.set_output_type(Target::ACTION);
- target_foo.action_values().set_script(SourceFile("//foo/script.py"));
- target_foo.action_values().outputs() = SubstitutionList::MakeForTest(
- "//out/Debug/out1.out", "//out/Debug/out2.out");
- target_foo.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target_foo.OnResolved(&err));
-
- Target target_bar(setup.settings(), Label(SourceDir("//bar/"), "bar"));
- target_bar.set_output_type(Target::ACTION);
- target_bar.action_values().set_script(SourceFile("//bar/script.py"));
- target_bar.action_values().outputs() = SubstitutionList::MakeForTest(
- "//out/Debug/out3.out", "//out/Debug/out2.out");
- target_bar.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target_bar.OnResolved(&err));
-
- std::unordered_map<const Settings*, const Toolchain*> used_toolchains;
- used_toolchains[setup.settings()] = setup.toolchain();
- std::vector<const Target*> targets = { &target_foo, &target_bar };
- std::ostringstream ninja_out;
- std::ostringstream depfile_out;
- NinjaBuildWriter writer(setup.build_settings(), used_toolchains,
- setup.toolchain(), targets, ninja_out, depfile_out);
- ASSERT_FALSE(writer.Run(&err));
-
- const char expected_help_test[] =
- "Two or more targets generate the same output:\n"
- " out2.out\n"
- "\n"
- "This is can often be fixed by changing one of the target names, or by \n"
- "setting an output_name on one of them.\n"
- "\n"
- "Collisions:\n"
- " //foo:bar\n"
- " //bar:bar\n";
-
- EXPECT_EQ(expected_help_test, err.help_text());
-}
diff --git a/chromium/tools/gn/ninja_bundle_data_target_writer.cc b/chromium/tools/gn/ninja_bundle_data_target_writer.cc
deleted file mode 100644
index ec3cf74c207..00000000000
--- a/chromium/tools/gn/ninja_bundle_data_target_writer.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/ninja_bundle_data_target_writer.h"
-
-#include "tools/gn/output_file.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/target.h"
-
-NinjaBundleDataTargetWriter::NinjaBundleDataTargetWriter(const Target* target,
- std::ostream& out)
- : NinjaTargetWriter(target, out) {}
-
-NinjaBundleDataTargetWriter::~NinjaBundleDataTargetWriter() = default;
-
-void NinjaBundleDataTargetWriter::Run() {
- std::vector<OutputFile> output_files;
- for (const SourceFile& source_file : target_->sources()) {
- output_files.push_back(
- OutputFile(settings_->build_settings(), source_file));
- }
-
- std::vector<OutputFile> input_deps = WriteInputDepsStampAndGetDep(
- std::vector<const Target*>(), /*num_stamp_uses=*/1);
- output_files.insert(output_files.end(), input_deps.begin(), input_deps.end());
-
- std::vector<OutputFile> order_only_deps;
- for (const auto& pair : target_->data_deps())
- order_only_deps.push_back(pair.ptr->dependency_output_file());
-
- WriteStampForTarget(output_files, order_only_deps);
-}
diff --git a/chromium/tools/gn/ninja_bundle_data_target_writer.h b/chromium/tools/gn/ninja_bundle_data_target_writer.h
deleted file mode 100644
index c097f67b591..00000000000
--- a/chromium/tools/gn/ninja_bundle_data_target_writer.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_NINJA_BUNDLE_DATA_TARGET_WRITER_H_
-#define TOOLS_GN_NINJA_BUNDLE_DATA_TARGET_WRITER_H_
-
-#include "base/macros.h"
-#include "tools/gn/ninja_target_writer.h"
-
-// Writes a .ninja file for a bundle_data target type.
-class NinjaBundleDataTargetWriter : public NinjaTargetWriter {
- public:
- NinjaBundleDataTargetWriter(const Target* target, std::ostream& out);
- ~NinjaBundleDataTargetWriter() override;
-
- void Run() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NinjaBundleDataTargetWriter);
-};
-
-#endif // TOOLS_GN_NINJA_BUNDLE_DATA_TARGET_WRITER_H_
diff --git a/chromium/tools/gn/ninja_bundle_data_target_writer_unittest.cc b/chromium/tools/gn/ninja_bundle_data_target_writer_unittest.cc
deleted file mode 100644
index 1cbf83eb173..00000000000
--- a/chromium/tools/gn/ninja_bundle_data_target_writer_unittest.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/ninja_bundle_data_target_writer.h"
-
-#include <algorithm>
-#include <sstream>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scope.h"
-
-TEST(NinjaBundleDataTargetWriter, Run) {
- Err err;
- TestWithScope setup;
-
- Target bundle_data(setup.settings(), Label(SourceDir("//foo/"), "data"));
- bundle_data.set_output_type(Target::BUNDLE_DATA);
- bundle_data.sources().push_back(SourceFile("//foo/input1.txt"));
- bundle_data.sources().push_back(SourceFile("//foo/input2.txt"));
- bundle_data.sources().push_back(
- SourceFile("//foo/Foo.xcassets/Contents.json"));
- bundle_data.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/Contents.json"));
- bundle_data.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29.png"));
- bundle_data.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@2x.png"));
- bundle_data.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@3x.png"));
- bundle_data.action_values().outputs() = SubstitutionList::MakeForTest(
- "{{bundle_resources_dir}}/{{source_file_part}}");
- bundle_data.SetToolchain(setup.toolchain());
- bundle_data.visibility().SetPublic();
- ASSERT_TRUE(bundle_data.OnResolved(&err));
-
- std::ostringstream out;
- NinjaBundleDataTargetWriter writer(&bundle_data, out);
- writer.Run();
-
- const char expected[] =
- "build obj/foo/data.stamp: stamp "
- "../../foo/input1.txt "
- "../../foo/input2.txt "
- "../../foo/Foo.xcassets/Contents.json "
- "../../foo/Foo.xcassets/foo.imageset/Contents.json "
- "../../foo/Foo.xcassets/foo.imageset/FooIcon-29.png "
- "../../foo/Foo.xcassets/foo.imageset/FooIcon-29@2x.png "
- "../../foo/Foo.xcassets/foo.imageset/FooIcon-29@3x.png\n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
-}
diff --git a/chromium/tools/gn/ninja_copy_target_writer.cc b/chromium/tools/gn/ninja_copy_target_writer.cc
deleted file mode 100644
index 194e2aa6de0..00000000000
--- a/chromium/tools/gn/ninja_copy_target_writer.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/ninja_copy_target_writer.h"
-
-#include "base/strings/string_util.h"
-#include "tools/gn/ninja_utils.h"
-#include "tools/gn/output_file.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/string_utils.h"
-#include "tools/gn/substitution_list.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/target.h"
-#include "tools/gn/toolchain.h"
-
-NinjaCopyTargetWriter::NinjaCopyTargetWriter(const Target* target,
- std::ostream& out)
- : NinjaTargetWriter(target, out) {
-}
-
-NinjaCopyTargetWriter::~NinjaCopyTargetWriter() = default;
-
-void NinjaCopyTargetWriter::Run() {
- const Tool* copy_tool = target_->toolchain()->GetTool(Toolchain::TYPE_COPY);
- if (!copy_tool) {
- g_scheduler->FailWithError(Err(
- nullptr, "Copy tool not defined",
- "The toolchain " +
- target_->toolchain()->label().GetUserVisibleName(false) +
- "\n used by target " + target_->label().GetUserVisibleName(false) +
- "\n doesn't define a \"copy\" tool."));
- return;
- }
-
- const Tool* stamp_tool = target_->toolchain()->GetTool(Toolchain::TYPE_STAMP);
- if (!stamp_tool) {
- g_scheduler->FailWithError(Err(
- nullptr, "Copy tool not defined",
- "The toolchain " +
- target_->toolchain()->label().GetUserVisibleName(false) +
- "\n used by target " + target_->label().GetUserVisibleName(false) +
- "\n doesn't define a \"stamp\" tool."));
- return;
- }
-
- // Figure out the substitutions used by the copy and stamp tools.
- SubstitutionBits required_bits = copy_tool->substitution_bits();
- required_bits.MergeFrom(stamp_tool->substitution_bits());
-
- // General target-related substitutions needed by both tools.
- WriteSharedVars(required_bits);
-
- std::vector<OutputFile> output_files;
- WriteCopyRules(&output_files);
- out_ << std::endl;
- WriteStampForTarget(output_files, std::vector<OutputFile>());
-}
-
-void NinjaCopyTargetWriter::WriteCopyRules(
- std::vector<OutputFile>* output_files) {
- CHECK(target_->action_values().outputs().list().size() == 1);
- const SubstitutionList& output_subst_list =
- target_->action_values().outputs();
- CHECK_EQ(1u, output_subst_list.list().size())
- << "Should have one entry exactly.";
- const SubstitutionPattern& output_subst = output_subst_list.list()[0];
-
- std::string tool_name =
- GetNinjaRulePrefixForToolchain(settings_) +
- Toolchain::ToolTypeToName(Toolchain::TYPE_COPY);
-
- size_t num_stamp_uses = target_->sources().size();
- std::vector<OutputFile> input_deps = WriteInputDepsStampAndGetDep(
- std::vector<const Target*>(), num_stamp_uses);
-
- // Note that we don't write implicit deps for copy steps. "copy" only
- // depends on the output files themselves, rather than having includes
- // (the possibility of generated #includes is the main reason for implicit
- // dependencies).
- //
- // It would seem that specifying implicit dependencies on the deps of the
- // copy command would still be harmeless. But Chrome implements copy tools
- // as hard links (much faster) which don't change the timestamp. If the
- // ninja rule looks like this:
- // output: copy input | foo.stamp
- // The copy will not make a new timestamp on the output file, but the
- // foo.stamp file generated from a previous step will have a new timestamp.
- // The copy rule will therefore look out-of-date to Ninja and the rule will
- // get rebuilt.
- //
- // If this copy is copying a generated file, not listing the implicit
- // dependency will be fine as long as the input to the copy is properly
- // listed as the output from the step that generated it.
- //
- // Moreover, doing this assumes that the copy step is always a simple
- // locally run command, so there is no need for a toolchain dependency.
- //
- // Note that there is the need in some cases for order-only dependencies
- // where a command might need to make sure something else runs before it runs
- // to avoid conflicts. Such cases should be avoided where possible, but
- // sometimes that's not possible.
- for (const auto& input_file : target_->sources()) {
- OutputFile output_file =
- SubstitutionWriter::ApplyPatternToSourceAsOutputFile(
- target_, target_->settings(), output_subst, input_file);
- output_files->push_back(output_file);
-
- out_ << "build ";
- path_output_.WriteFile(out_, output_file);
- out_ << ": " << tool_name << " ";
- path_output_.WriteFile(out_, input_file);
- if (!input_deps.empty()) {
- out_ << " ||";
- path_output_.WriteFiles(out_, input_deps);
- }
- out_ << std::endl;
- }
-}
diff --git a/chromium/tools/gn/ninja_copy_target_writer.h b/chromium/tools/gn/ninja_copy_target_writer.h
deleted file mode 100644
index a45a470a3d4..00000000000
--- a/chromium/tools/gn/ninja_copy_target_writer.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_NINJA_COPY_TARGET_WRITER_H_
-#define TOOLS_GN_NINJA_COPY_TARGET_WRITER_H_
-
-#include "base/macros.h"
-#include "tools/gn/ninja_target_writer.h"
-
-// Writes a .ninja file for a copy target type.
-class NinjaCopyTargetWriter : public NinjaTargetWriter {
- public:
- NinjaCopyTargetWriter(const Target* target, std::ostream& out);
- ~NinjaCopyTargetWriter() override;
-
- void Run() override;
-
- private:
- // Writes the rules top copy the file(s), putting the computed output file
- // name(s) into the given vector.
- void WriteCopyRules(std::vector<OutputFile>* output_files);
-
- DISALLOW_COPY_AND_ASSIGN(NinjaCopyTargetWriter);
-};
-
-#endif // TOOLS_GN_NINJA_COPY_TARGET_WRITER_H_
diff --git a/chromium/tools/gn/ninja_copy_target_writer_unittest.cc b/chromium/tools/gn/ninja_copy_target_writer_unittest.cc
deleted file mode 100644
index b00a644f299..00000000000
--- a/chromium/tools/gn/ninja_copy_target_writer_unittest.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <algorithm>
-#include <sstream>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/ninja_copy_target_writer.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scope.h"
-
-// Tests multiple files with an output pattern and no toolchain dependency.
-TEST(NinjaCopyTargetWriter, Run) {
- Err err;
- TestWithScope setup;
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::COPY_FILES);
-
- target.sources().push_back(SourceFile("//foo/input1.txt"));
- target.sources().push_back(SourceFile("//foo/input2.txt"));
-
- target.action_values().outputs() =
- SubstitutionList::MakeForTest("//out/Debug/{{source_name_part}}.out");
-
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaCopyTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected_linux[] =
- "build input1.out: copy ../../foo/input1.txt\n"
- "build input2.out: copy ../../foo/input2.txt\n"
- "\n"
- "build obj/foo/bar.stamp: stamp input1.out input2.out\n";
- std::string out_str = out.str();
- EXPECT_EQ(expected_linux, out_str);
-}
-
-// Tests a single file with no output pattern.
-TEST(NinjaCopyTargetWriter, ToolchainDeps) {
- Err err;
- TestWithScope setup;
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::COPY_FILES);
-
- target.sources().push_back(SourceFile("//foo/input1.txt"));
-
- target.action_values().outputs() =
- SubstitutionList::MakeForTest("//out/Debug/output.out");
-
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaCopyTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected_linux[] =
- "build output.out: copy ../../foo/input1.txt\n"
- "\n"
- "build obj/foo/bar.stamp: stamp output.out\n";
- std::string out_str = out.str();
- EXPECT_EQ(expected_linux, out_str);
-}
-
-TEST(NinjaCopyTargetWriter, OrderOnlyDeps) {
- Err err;
- TestWithScope setup;
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::COPY_FILES);
- target.sources().push_back(SourceFile("//foo/input1.txt"));
- target.action_values().outputs() =
- SubstitutionList::MakeForTest("//out/Debug/{{source_name_part}}.out");
- target.config_values().inputs().push_back(SourceFile("//foo/script.py"));
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaCopyTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected_linux[] =
- "build input1.out: copy ../../foo/input1.txt || ../../foo/script.py\n"
- "\n"
- "build obj/foo/bar.stamp: stamp input1.out\n";
- std::string out_str = out.str();
- EXPECT_EQ(expected_linux, out_str);
-}
diff --git a/chromium/tools/gn/ninja_create_bundle_target_writer.cc b/chromium/tools/gn/ninja_create_bundle_target_writer.cc
deleted file mode 100644
index 3602df46237..00000000000
--- a/chromium/tools/gn/ninja_create_bundle_target_writer.cc
+++ /dev/null
@@ -1,332 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/ninja_create_bundle_target_writer.h"
-
-#include "base/macros.h"
-#include "base/strings/string_util.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/ninja_utils.h"
-#include "tools/gn/output_file.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/target.h"
-#include "tools/gn/toolchain.h"
-
-namespace {
-
-void FailWithMissingToolError(Toolchain::ToolType tool, const Target* target) {
- const std::string& tool_name = Toolchain::ToolTypeToName(tool);
- g_scheduler->FailWithError(Err(
- nullptr, tool_name + " tool not defined",
- "The toolchain " +
- target->toolchain()->label().GetUserVisibleName(false) + "\n"
- "used by target " + target->label().GetUserVisibleName(false) + "\n"
- "doesn't define a \"" + tool_name + "\" tool."));
-}
-
-bool EnsureAllToolsAvailable(const Target* target) {
- const Toolchain::ToolType kRequiredTools[] = {
- Toolchain::TYPE_COPY_BUNDLE_DATA, Toolchain::TYPE_COMPILE_XCASSETS,
- Toolchain::TYPE_STAMP,
- };
-
- for (size_t i = 0; i < arraysize(kRequiredTools); ++i) {
- if (!target->toolchain()->GetTool(kRequiredTools[i])) {
- FailWithMissingToolError(kRequiredTools[i], target);
- return false;
- }
- }
-
- return true;
-}
-
-} // namespace
-
-NinjaCreateBundleTargetWriter::NinjaCreateBundleTargetWriter(
- const Target* target,
- std::ostream& out)
- : NinjaTargetWriter(target, out) {}
-
-NinjaCreateBundleTargetWriter::~NinjaCreateBundleTargetWriter() = default;
-
-void NinjaCreateBundleTargetWriter::Run() {
- if (!EnsureAllToolsAvailable(target_))
- return;
-
- // Stamp users are CopyBundleData, CompileAssetsCatalog, CodeSigning and
- // StampForTarget.
- size_t num_stamp_uses = 4;
- std::vector<OutputFile> order_only_deps = WriteInputDepsStampAndGetDep(
- std::vector<const Target*>(), num_stamp_uses);
-
- std::string code_signing_rule_name = WriteCodeSigningRuleDefinition();
-
- std::vector<OutputFile> output_files;
- WriteCopyBundleDataSteps(order_only_deps, &output_files);
- WriteCompileAssetsCatalogStep(order_only_deps, &output_files);
- WriteCodeSigningStep(code_signing_rule_name, order_only_deps, &output_files);
-
- for (const auto& pair : target_->data_deps())
- order_only_deps.push_back(pair.ptr->dependency_output_file());
- WriteStampForTarget(output_files, order_only_deps);
-
- // Write a phony target for the outer bundle directory. This allows other
- // targets to treat the entire bundle as a single unit, even though it is
- // a directory, so that it can be depended upon as a discrete build edge.
- out_ << "build ";
- path_output_.WriteFile(
- out_,
- OutputFile(settings_->build_settings(),
- target_->bundle_data().GetBundleRootDirOutput(settings_)));
- out_ << ": phony " << target_->dependency_output_file().value();
- out_ << std::endl;
-}
-
-std::string NinjaCreateBundleTargetWriter::WriteCodeSigningRuleDefinition() {
- if (target_->bundle_data().code_signing_script().is_null())
- return std::string();
-
- std::string target_label = target_->label().GetUserVisibleName(true);
- std::string custom_rule_name(target_label);
- base::ReplaceChars(custom_rule_name, ":/()", "_", &custom_rule_name);
- custom_rule_name.append("_code_signing_rule");
-
- out_ << "rule " << custom_rule_name << std::endl;
- out_ << " command = ";
- path_output_.WriteFile(out_, settings_->build_settings()->python_path());
- out_ << " ";
- path_output_.WriteFile(out_, target_->bundle_data().code_signing_script());
-
- const SubstitutionList& args = target_->bundle_data().code_signing_args();
- EscapeOptions args_escape_options;
- args_escape_options.mode = ESCAPE_NINJA_COMMAND;
-
- for (const auto& arg : args.list()) {
- out_ << " ";
- SubstitutionWriter::WriteWithNinjaVariables(arg, args_escape_options, out_);
- }
- out_ << std::endl;
- out_ << " description = CODE SIGNING " << target_label << std::endl;
- out_ << " restat = 1" << std::endl;
- out_ << std::endl;
-
- return custom_rule_name;
-}
-
-void NinjaCreateBundleTargetWriter::WriteCopyBundleDataSteps(
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* output_files) {
- for (const BundleFileRule& file_rule : target_->bundle_data().file_rules())
- WriteCopyBundleFileRuleSteps(file_rule, order_only_deps, output_files);
-}
-
-void NinjaCreateBundleTargetWriter::WriteCopyBundleFileRuleSteps(
- const BundleFileRule& file_rule,
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* output_files) {
- // Note that we don't write implicit deps for copy steps. "copy_bundle_data"
- // steps as this is most likely implemented using hardlink in the common case.
- // See NinjaCopyTargetWriter::WriteCopyRules() for a detailed explanation.
- for (const SourceFile& source_file : file_rule.sources()) {
- OutputFile output_file = file_rule.ApplyPatternToSourceAsOutputFile(
- settings_, target_->bundle_data(), source_file);
- output_files->push_back(output_file);
-
- out_ << "build ";
- path_output_.WriteFile(out_, output_file);
- out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
- << Toolchain::ToolTypeToName(Toolchain::TYPE_COPY_BUNDLE_DATA) << " ";
- path_output_.WriteFile(out_, source_file);
-
- if (!order_only_deps.empty()) {
- out_ << " ||";
- path_output_.WriteFiles(out_, order_only_deps);
- }
-
- out_ << std::endl;
- }
-}
-
-void NinjaCreateBundleTargetWriter::WriteCompileAssetsCatalogStep(
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* output_files) {
- if (target_->bundle_data().assets_catalog_sources().empty() &&
- target_->bundle_data().partial_info_plist().is_null())
- return;
-
- OutputFile compiled_catalog;
- if (!target_->bundle_data().assets_catalog_sources().empty()) {
- compiled_catalog =
- OutputFile(settings_->build_settings(),
- target_->bundle_data().GetCompiledAssetCatalogPath());
- output_files->push_back(compiled_catalog);
- }
-
- OutputFile partial_info_plist;
- if (!target_->bundle_data().partial_info_plist().is_null()) {
- partial_info_plist =
- OutputFile(settings_->build_settings(),
- target_->bundle_data().partial_info_plist());
-
- output_files->push_back(partial_info_plist);
- }
-
- // If there are no asset catalog to compile but the "partial_info_plist" is
- // non-empty, then add a target to generate an empty file (to avoid breaking
- // code that depends on this file existence).
- if (target_->bundle_data().assets_catalog_sources().empty()) {
- DCHECK(!target_->bundle_data().partial_info_plist().is_null());
-
- out_ << "build ";
- path_output_.WriteFile(out_, partial_info_plist);
- out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
- << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
- if (!order_only_deps.empty()) {
- out_ << " ||";
- path_output_.WriteFiles(out_, order_only_deps);
- }
- out_ << std::endl;
- return;
- }
-
- OutputFile input_dep = WriteCompileAssetsCatalogInputDepsStamp(
- target_->bundle_data().assets_catalog_deps());
- DCHECK(!input_dep.value().empty());
-
- out_ << "build ";
- path_output_.WriteFile(out_, compiled_catalog);
- if (partial_info_plist != OutputFile()) {
- // If "partial_info_plist" is non-empty, then add it to list of implicit
- // outputs of the asset catalog compilation, so that target can use it
- // without getting the ninja error "'foo', needed by 'bar', missing and
- // no known rule to make it".
- out_ << " | ";
- path_output_.WriteFile(out_, partial_info_plist);
- }
-
- out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
- << Toolchain::ToolTypeToName(Toolchain::TYPE_COMPILE_XCASSETS);
-
- std::set<SourceFile> asset_catalog_bundles;
- for (const auto& source : target_->bundle_data().assets_catalog_sources()) {
- out_ << " ";
- path_output_.WriteFile(out_, source);
- asset_catalog_bundles.insert(source);
- }
-
- out_ << " | ";
- path_output_.WriteFile(out_, input_dep);
-
- if (!order_only_deps.empty()) {
- out_ << " ||";
- path_output_.WriteFiles(out_, order_only_deps);
- }
-
- out_ << std::endl;
-
- out_ << " product_type = " << target_->bundle_data().product_type()
- << std::endl;
-
- if (partial_info_plist != OutputFile()) {
- out_ << " partial_info_plist = ";
- path_output_.WriteFile(out_, partial_info_plist);
- out_ << std::endl;
- }
-}
-
-OutputFile
-NinjaCreateBundleTargetWriter::WriteCompileAssetsCatalogInputDepsStamp(
- const std::vector<const Target*>& dependencies) {
- DCHECK(!dependencies.empty());
- if (dependencies.size() == 1)
- return dependencies[0]->dependency_output_file();
-
- OutputFile xcassets_input_stamp_file =
- GetBuildDirForTargetAsOutputFile(target_, BuildDirType::OBJ);
- xcassets_input_stamp_file.value().append(target_->label().name());
- xcassets_input_stamp_file.value().append(".xcassets.inputdeps.stamp");
-
- out_ << "build ";
- path_output_.WriteFile(out_, xcassets_input_stamp_file);
- out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
- << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
-
- for (const Target* target : dependencies) {
- out_ << " ";
- path_output_.WriteFile(out_, target->dependency_output_file());
- }
- out_ << std::endl;
- return xcassets_input_stamp_file;
-}
-
-void NinjaCreateBundleTargetWriter::WriteCodeSigningStep(
- const std::string& code_signing_rule_name,
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* output_files) {
- if (code_signing_rule_name.empty())
- return;
-
- OutputFile code_signing_input_stamp_file =
- WriteCodeSigningInputDepsStamp(order_only_deps, output_files);
- DCHECK(!code_signing_input_stamp_file.value().empty());
-
- out_ << "build";
- std::vector<OutputFile> code_signing_output_files;
- SubstitutionWriter::GetListAsOutputFiles(
- settings_, target_->bundle_data().code_signing_outputs(),
- &code_signing_output_files);
- path_output_.WriteFiles(out_, code_signing_output_files);
-
- // Since the code signature step depends on all the files from the bundle,
- // the create_bundle stamp can just depends on the output of the signature
- // script (dependencies are transitive).
- output_files->swap(code_signing_output_files);
-
- out_ << ": " << code_signing_rule_name;
- out_ << " | ";
- path_output_.WriteFile(out_, code_signing_input_stamp_file);
- out_ << std::endl;
-}
-
-OutputFile NinjaCreateBundleTargetWriter::WriteCodeSigningInputDepsStamp(
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* output_files) {
- std::vector<SourceFile> code_signing_input_files;
- code_signing_input_files.push_back(
- target_->bundle_data().code_signing_script());
- code_signing_input_files.insert(
- code_signing_input_files.end(),
- target_->bundle_data().code_signing_sources().begin(),
- target_->bundle_data().code_signing_sources().end());
- for (const OutputFile& output_file : *output_files) {
- code_signing_input_files.push_back(
- output_file.AsSourceFile(settings_->build_settings()));
- }
-
- DCHECK(!code_signing_input_files.empty());
- if (code_signing_input_files.size() == 1 && order_only_deps.empty())
- return OutputFile(settings_->build_settings(), code_signing_input_files[0]);
-
- OutputFile code_signing_input_stamp_file =
- GetBuildDirForTargetAsOutputFile(target_, BuildDirType::OBJ);
- code_signing_input_stamp_file.value().append(target_->label().name());
- code_signing_input_stamp_file.value().append(".codesigning.inputdeps.stamp");
-
- out_ << "build ";
- path_output_.WriteFile(out_, code_signing_input_stamp_file);
- out_ << ": " << GetNinjaRulePrefixForToolchain(settings_)
- << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
-
- for (const SourceFile& source : code_signing_input_files) {
- out_ << " ";
- path_output_.WriteFile(out_, source);
- }
- if (!order_only_deps.empty()) {
- out_ << " ||";
- path_output_.WriteFiles(out_, order_only_deps);
- }
- out_ << std::endl;
- return code_signing_input_stamp_file;
-}
diff --git a/chromium/tools/gn/ninja_create_bundle_target_writer.h b/chromium/tools/gn/ninja_create_bundle_target_writer.h
deleted file mode 100644
index 072e02c2a73..00000000000
--- a/chromium/tools/gn/ninja_create_bundle_target_writer.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_NINJA_CREATE_BUNDLE_TARGET_WRITER_H_
-#define TOOLS_GN_NINJA_CREATE_BUNDLE_TARGET_WRITER_H_
-
-#include "base/macros.h"
-#include "tools/gn/ninja_target_writer.h"
-
-class BundleFileRule;
-
-// Writes a .ninja file for a bundle_data target type.
-class NinjaCreateBundleTargetWriter : public NinjaTargetWriter {
- public:
- NinjaCreateBundleTargetWriter(const Target* target, std::ostream& out);
- ~NinjaCreateBundleTargetWriter() override;
-
- void Run() override;
-
- private:
- // Writes the Ninja rule for invoking the code signing script.
- //
- // Returns the name of the custom rule generated for the code signing step if
- // defined, otherwise returns an empty string.
- std::string WriteCodeSigningRuleDefinition();
-
- // Writes the steps to copy files into the bundle.
- //
- // The list of newly created files will be added to |output_files|.
- void WriteCopyBundleDataSteps(const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* output_files);
-
- // Writes the step to copy files BundleFileRule into the bundle.
- //
- // The list of newly created files will be added to |output_files|.
- void WriteCopyBundleFileRuleSteps(
- const BundleFileRule& file_rule,
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* output_files);
-
- // Writes the step to compile assets catalogs.
- //
- // The list of newly created files will be added to |output_files|.
- void WriteCompileAssetsCatalogStep(
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* output_files);
-
- // Writes the stamp file for the assets catalog compilation input
- // dependencies.
- OutputFile WriteCompileAssetsCatalogInputDepsStamp(
- const std::vector<const Target*>& dependencies);
-
- // Writes the code signing step (if a script is defined).
- //
- // The list of newly created files will be added to |output_files|. As the
- // code signing may depends on the full bundle structure, this step will
- // depends on all files generated via other rules.
- void WriteCodeSigningStep(const std::string& code_signing_rule_name,
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* output_files);
-
- // Writes the stamp file for the code signing input dependencies.
- OutputFile WriteCodeSigningInputDepsStamp(
- const std::vector<OutputFile>& order_only_deps,
- std::vector<OutputFile>* output_files);
-
- DISALLOW_COPY_AND_ASSIGN(NinjaCreateBundleTargetWriter);
-};
-
-#endif // TOOLS_GN_NINJA_CREATE_BUNDLE_TARGET_WRITER_H_
diff --git a/chromium/tools/gn/ninja_create_bundle_target_writer_unittest.cc b/chromium/tools/gn/ninja_create_bundle_target_writer_unittest.cc
deleted file mode 100644
index c745939c196..00000000000
--- a/chromium/tools/gn/ninja_create_bundle_target_writer_unittest.cc
+++ /dev/null
@@ -1,457 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/ninja_create_bundle_target_writer.h"
-
-#include <algorithm>
-#include <memory>
-#include <sstream>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-void SetupBundleDataDir(BundleData* bundle_data, const std::string& root_dir) {
- std::string bundle_root_dir = root_dir + "/bar.bundle";
- bundle_data->root_dir() = SourceDir(bundle_root_dir);
- bundle_data->contents_dir() = SourceDir(bundle_root_dir + "/Contents");
- bundle_data->resources_dir() =
- SourceDir(bundle_data->contents_dir().value() + "/Resources");
- bundle_data->executable_dir() =
- SourceDir(bundle_data->contents_dir().value() + "/MacOS");
- bundle_data->plugins_dir() =
- SourceDir(bundle_data->contents_dir().value() + "/Plug Ins");
-}
-
-std::unique_ptr<Target> NewAction(const TestWithScope& setup) {
- Err err;
- auto action = std::make_unique<Target>(setup.settings(),
- Label(SourceDir("//foo/"), "bar"));
- action->set_output_type(Target::ACTION);
- action->visibility().SetPublic();
- action->action_values().set_script(SourceFile("//foo/script.py"));
-
- action->action_values().outputs() =
- SubstitutionList::MakeForTest("//out/Debug/foo.out");
-
- action->SetToolchain(setup.toolchain());
- return action;
-}
-
-} // namespace
-
-// Tests multiple files with an output pattern.
-TEST(NinjaCreateBundleTargetWriter, Run) {
- Err err;
- TestWithScope setup;
-
- std::unique_ptr<Target> action = NewAction(setup);
- ASSERT_TRUE(action->OnResolved(&err)) << err.message();
-
- Target bundle_data(setup.settings(), Label(SourceDir("//foo/"), "data"));
- bundle_data.set_output_type(Target::BUNDLE_DATA);
- bundle_data.sources().push_back(SourceFile("//foo/input1.txt"));
- bundle_data.sources().push_back(SourceFile("//foo/input2.txt"));
- bundle_data.action_values().outputs() = SubstitutionList::MakeForTest(
- "{{bundle_resources_dir}}/{{source_file_part}}");
- bundle_data.SetToolchain(setup.toolchain());
- bundle_data.visibility().SetPublic();
- ASSERT_TRUE(bundle_data.OnResolved(&err));
-
- Target create_bundle(
- setup.settings(),
- Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
- setup.toolchain()->label().name()));
- SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
- create_bundle.set_output_type(Target::CREATE_BUNDLE);
- create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data));
- create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
- create_bundle.SetToolchain(setup.toolchain());
- ASSERT_TRUE(create_bundle.OnResolved(&err));
-
- std::ostringstream out;
- NinjaCreateBundleTargetWriter writer(&create_bundle, out);
- writer.Run();
-
- const char expected[] =
- "build obj/baz/bar.inputdeps.stamp: stamp obj/foo/bar.stamp "
- "obj/foo/data.stamp\n"
- "build bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
- "../../foo/input1.txt || obj/baz/bar.inputdeps.stamp\n"
- "build bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
- "../../foo/input2.txt || obj/baz/bar.inputdeps.stamp\n"
- "build obj/baz/bar.stamp: stamp "
- "bar.bundle/Contents/Resources/input1.txt "
- "bar.bundle/Contents/Resources/input2.txt"
- " || obj/baz/bar.inputdeps.stamp\n"
- "build bar.bundle: phony obj/baz/bar.stamp\n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
-}
-
-// Tests creating a bundle in a sub-directory of $root_out_dir.
-TEST(NinjaCreateBundleTargetWriter, InSubDirectory) {
- Err err;
- TestWithScope setup;
-
- std::unique_ptr<Target> action = NewAction(setup);
- ASSERT_TRUE(action->OnResolved(&err)) << err.message();
-
- Target bundle_data(setup.settings(), Label(SourceDir("//foo/"), "data"));
- bundle_data.set_output_type(Target::BUNDLE_DATA);
- bundle_data.sources().push_back(SourceFile("//foo/input1.txt"));
- bundle_data.sources().push_back(SourceFile("//foo/input2.txt"));
- bundle_data.action_values().outputs() = SubstitutionList::MakeForTest(
- "{{bundle_resources_dir}}/{{source_file_part}}");
- bundle_data.SetToolchain(setup.toolchain());
- bundle_data.visibility().SetPublic();
- ASSERT_TRUE(bundle_data.OnResolved(&err));
-
- Target create_bundle(
- setup.settings(),
- Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
- setup.toolchain()->label().name()));
- SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug/gen");
- create_bundle.set_output_type(Target::CREATE_BUNDLE);
- create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data));
- create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
- create_bundle.SetToolchain(setup.toolchain());
- ASSERT_TRUE(create_bundle.OnResolved(&err));
-
- std::ostringstream out;
- NinjaCreateBundleTargetWriter writer(&create_bundle, out);
- writer.Run();
-
- const char expected[] =
- "build obj/baz/bar.inputdeps.stamp: stamp obj/foo/bar.stamp "
- "obj/foo/data.stamp\n"
- "build gen/bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
- "../../foo/input1.txt || obj/baz/bar.inputdeps.stamp\n"
- "build gen/bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
- "../../foo/input2.txt || obj/baz/bar.inputdeps.stamp\n"
- "build obj/baz/bar.stamp: stamp "
- "gen/bar.bundle/Contents/Resources/input1.txt "
- "gen/bar.bundle/Contents/Resources/input2.txt || "
- "obj/baz/bar.inputdeps.stamp\n"
- "build gen/bar.bundle: phony obj/baz/bar.stamp\n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
-}
-
-// Tests empty asset catalog with partial_info_plist property defined.
-TEST(NinjaCreateBundleTargetWriter, JustPartialInfoPlist) {
- Err err;
- TestWithScope setup;
-
- std::unique_ptr<Target> action = NewAction(setup);
- ASSERT_TRUE(action->OnResolved(&err)) << err.message();
-
- Target create_bundle(
- setup.settings(),
- Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
- setup.toolchain()->label().name()));
- SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
- create_bundle.set_output_type(Target::CREATE_BUNDLE);
- create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
- create_bundle.bundle_data().product_type().assign("com.apple.product-type");
- create_bundle.bundle_data().set_partial_info_plist(
- SourceFile("//out/Debug/baz/bar/bar_partial_info.plist"));
- create_bundle.SetToolchain(setup.toolchain());
- ASSERT_TRUE(create_bundle.OnResolved(&err));
-
- std::ostringstream out;
- NinjaCreateBundleTargetWriter writer(&create_bundle, out);
- writer.Run();
-
- const char expected[] =
- "build baz/bar/bar_partial_info.plist: stamp || obj/foo/bar.stamp\n"
- "build obj/baz/bar.stamp: stamp "
- "baz/bar/bar_partial_info.plist || obj/foo/bar.stamp\n"
- "build bar.bundle: phony obj/baz/bar.stamp\n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
-}
-
-
-// Tests multiple files from asset catalog.
-TEST(NinjaCreateBundleTargetWriter, AssetCatalog) {
- Err err;
- TestWithScope setup;
-
- std::unique_ptr<Target> action = NewAction(setup);
- ASSERT_TRUE(action->OnResolved(&err)) << err.message();
-
- Target bundle_data(setup.settings(), Label(SourceDir("//foo/"), "data"));
- bundle_data.set_output_type(Target::BUNDLE_DATA);
- bundle_data.sources().push_back(
- SourceFile("//foo/Foo.xcassets/Contents.json"));
- bundle_data.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/Contents.json"));
- bundle_data.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29.png"));
- bundle_data.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@2x.png"));
- bundle_data.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@3x.png"));
- bundle_data.action_values().outputs() = SubstitutionList::MakeForTest(
- "{{bundle_resources_dir}}/{{source_file_part}}");
- bundle_data.SetToolchain(setup.toolchain());
- bundle_data.visibility().SetPublic();
- ASSERT_TRUE(bundle_data.OnResolved(&err));
-
- Target create_bundle(
- setup.settings(),
- Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
- setup.toolchain()->label().name()));
- SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
- create_bundle.set_output_type(Target::CREATE_BUNDLE);
- create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data));
- create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
- create_bundle.bundle_data().product_type().assign("com.apple.product-type");
- create_bundle.SetToolchain(setup.toolchain());
- ASSERT_TRUE(create_bundle.OnResolved(&err));
-
- std::ostringstream out;
- NinjaCreateBundleTargetWriter writer(&create_bundle, out);
- writer.Run();
-
- const char expected[] =
- "build obj/baz/bar.inputdeps.stamp: stamp obj/foo/bar.stamp "
- "obj/foo/data.stamp\n"
- "build bar.bundle/Contents/Resources/Assets.car: compile_xcassets "
- "../../foo/Foo.xcassets | obj/foo/data.stamp || "
- "obj/baz/bar.inputdeps.stamp\n"
- " product_type = com.apple.product-type\n"
- "build obj/baz/bar.stamp: stamp "
- "bar.bundle/Contents/Resources/Assets.car || "
- "obj/baz/bar.inputdeps.stamp\n"
- "build bar.bundle: phony obj/baz/bar.stamp\n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
-}
-
-// Tests that the phony target for the top-level bundle directory is generated
-// correctly.
-TEST(NinjaCreateBundleTargetWriter, PhonyTarget) {
- Err err;
- TestWithScope setup;
-
- Target create_bundle(
- setup.settings(),
- Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
- setup.toolchain()->label().name()));
- SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
- create_bundle.set_output_type(Target::CREATE_BUNDLE);
- create_bundle.SetToolchain(setup.toolchain());
- ASSERT_TRUE(create_bundle.OnResolved(&err));
-
- std::ostringstream out;
- NinjaCreateBundleTargetWriter writer(&create_bundle, out);
- writer.Run();
-
- const char expected[] =
- "build obj/baz/bar.stamp: stamp\n"
- "build bar.bundle: phony obj/baz/bar.stamp\n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
-}
-
-// Tests complex target with multiple bundle_data sources, including
-// some asset catalog.
-TEST(NinjaCreateBundleTargetWriter, Complex) {
- Err err;
- TestWithScope setup;
-
- std::unique_ptr<Target> action = NewAction(setup);
- ASSERT_TRUE(action->OnResolved(&err)) << err.message();
-
- Target bundle_data0(setup.settings(),
- Label(SourceDir("//qux/"), "info_plist"));
- bundle_data0.set_output_type(Target::BUNDLE_DATA);
- bundle_data0.sources().push_back(SourceFile("//qux/qux-Info.plist"));
- bundle_data0.action_values().outputs() =
- SubstitutionList::MakeForTest("{{bundle_contents_dir}}/Info.plist");
- bundle_data0.SetToolchain(setup.toolchain());
- bundle_data0.visibility().SetPublic();
- ASSERT_TRUE(bundle_data0.OnResolved(&err));
-
- Target bundle_data1(setup.settings(), Label(SourceDir("//foo/"), "data"));
- bundle_data1.set_output_type(Target::BUNDLE_DATA);
- bundle_data1.sources().push_back(SourceFile("//foo/input1.txt"));
- bundle_data1.sources().push_back(SourceFile("//foo/input2.txt"));
- bundle_data1.action_values().outputs() = SubstitutionList::MakeForTest(
- "{{bundle_resources_dir}}/{{source_file_part}}");
- bundle_data1.SetToolchain(setup.toolchain());
- bundle_data1.visibility().SetPublic();
- ASSERT_TRUE(bundle_data1.OnResolved(&err));
-
- Target bundle_data2(setup.settings(), Label(SourceDir("//foo/"), "assets"));
- bundle_data2.set_output_type(Target::BUNDLE_DATA);
- bundle_data2.sources().push_back(
- SourceFile("//foo/Foo.xcassets/Contents.json"));
- bundle_data2.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/Contents.json"));
- bundle_data2.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29.png"));
- bundle_data2.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@2x.png"));
- bundle_data2.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/FooIcon-29@3x.png"));
- bundle_data2.action_values().outputs() = SubstitutionList::MakeForTest(
- "{{bundle_resources_dir}}/{{source_file_part}}");
- bundle_data2.SetToolchain(setup.toolchain());
- bundle_data2.visibility().SetPublic();
- ASSERT_TRUE(bundle_data2.OnResolved(&err));
-
- Target bundle_data3(setup.settings(), Label(SourceDir("//quz/"), "assets"));
- bundle_data3.set_output_type(Target::BUNDLE_DATA);
- bundle_data3.sources().push_back(
- SourceFile("//quz/Quz.xcassets/Contents.json"));
- bundle_data3.sources().push_back(
- SourceFile("//quz/Quz.xcassets/quz.imageset/Contents.json"));
- bundle_data3.sources().push_back(
- SourceFile("//quz/Quz.xcassets/quz.imageset/QuzIcon-29.png"));
- bundle_data3.sources().push_back(
- SourceFile("//quz/Quz.xcassets/quz.imageset/QuzIcon-29@2x.png"));
- bundle_data3.sources().push_back(
- SourceFile("//quz/Quz.xcassets/quz.imageset/QuzIcon-29@3x.png"));
- bundle_data3.action_values().outputs() = SubstitutionList::MakeForTest(
- "{{bundle_resources_dir}}/{{source_file_part}}");
- bundle_data3.SetToolchain(setup.toolchain());
- bundle_data3.visibility().SetPublic();
- ASSERT_TRUE(bundle_data3.OnResolved(&err));
-
- Target create_bundle(
- setup.settings(),
- Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
- setup.toolchain()->label().name()));
- SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
- create_bundle.set_output_type(Target::CREATE_BUNDLE);
- create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data0));
- create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data1));
- create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data2));
- create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data3));
- create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
- create_bundle.bundle_data().product_type().assign("com.apple.product-type");
- create_bundle.bundle_data().set_partial_info_plist(
- SourceFile("//out/Debug/baz/bar/bar_partial_info.plist"));
- create_bundle.SetToolchain(setup.toolchain());
- ASSERT_TRUE(create_bundle.OnResolved(&err));
-
- std::ostringstream out;
- NinjaCreateBundleTargetWriter writer(&create_bundle, out);
- writer.Run();
-
- const char expected[] =
- "build obj/baz/bar.inputdeps.stamp: stamp obj/foo/assets.stamp "
- "obj/foo/bar.stamp obj/foo/data.stamp obj/qux/info_plist.stamp "
- "obj/quz/assets.stamp\n"
- "build bar.bundle/Contents/Info.plist: copy_bundle_data "
- "../../qux/qux-Info.plist || obj/baz/bar.inputdeps.stamp\n"
- "build bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
- "../../foo/input1.txt || obj/baz/bar.inputdeps.stamp\n"
- "build bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
- "../../foo/input2.txt || obj/baz/bar.inputdeps.stamp\n"
- "build obj/baz/bar.xcassets.inputdeps.stamp: stamp "
- "obj/foo/assets.stamp "
- "obj/quz/assets.stamp\n"
- "build bar.bundle/Contents/Resources/Assets.car | "
- "baz/bar/bar_partial_info.plist: compile_xcassets "
- "../../foo/Foo.xcassets "
- "../../quz/Quz.xcassets | obj/baz/bar.xcassets.inputdeps.stamp || "
- "obj/baz/bar.inputdeps.stamp\n"
- " product_type = com.apple.product-type\n"
- " partial_info_plist = baz/bar/bar_partial_info.plist\n"
- "build obj/baz/bar.stamp: stamp "
- "bar.bundle/Contents/Info.plist "
- "bar.bundle/Contents/Resources/input1.txt "
- "bar.bundle/Contents/Resources/input2.txt "
- "bar.bundle/Contents/Resources/Assets.car "
- "baz/bar/bar_partial_info.plist || obj/baz/bar.inputdeps.stamp\n"
- "build bar.bundle: phony obj/baz/bar.stamp\n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
-}
-
-// Tests code signing steps.
-TEST(NinjaCreateBundleTargetWriter, CodeSigning) {
- Err err;
- TestWithScope setup;
-
- std::unique_ptr<Target> action = NewAction(setup);
- ASSERT_TRUE(action->OnResolved(&err)) << err.message();
-
- Target executable(setup.settings(), Label(SourceDir("//baz/"), "quz"));
- executable.set_output_type(Target::EXECUTABLE);
- executable.sources().push_back(SourceFile("//baz/quz.c"));
- executable.SetToolchain(setup.toolchain());
- executable.visibility().SetPublic();
- ASSERT_TRUE(executable.OnResolved(&err));
-
- Target bundle_data(setup.settings(), Label(SourceDir("//foo/"), "data"));
- bundle_data.set_output_type(Target::BUNDLE_DATA);
- bundle_data.sources().push_back(SourceFile("//foo/input1.txt"));
- bundle_data.sources().push_back(SourceFile("//foo/input2.txt"));
- bundle_data.action_values().outputs() = SubstitutionList::MakeForTest(
- "{{bundle_resources_dir}}/{{source_file_part}}");
- bundle_data.SetToolchain(setup.toolchain());
- bundle_data.visibility().SetPublic();
- ASSERT_TRUE(bundle_data.OnResolved(&err));
-
- Target create_bundle(
- setup.settings(),
- Label(SourceDir("//baz/"), "bar", setup.toolchain()->label().dir(),
- setup.toolchain()->label().name()));
- SetupBundleDataDir(&create_bundle.bundle_data(), "//out/Debug");
- create_bundle.set_output_type(Target::CREATE_BUNDLE);
- create_bundle.bundle_data().set_code_signing_script(
- SourceFile("//build/codesign.py"));
- create_bundle.bundle_data().code_signing_sources().push_back(
- SourceFile("//out/Debug/quz"));
- create_bundle.bundle_data().code_signing_outputs() =
- SubstitutionList::MakeForTest(
- "//out/Debug/bar.bundle/Contents/quz",
- "//out/Debug/bar.bundle/_CodeSignature/CodeResources");
- create_bundle.bundle_data().code_signing_args() =
- SubstitutionList::MakeForTest("-b=quz", "bar.bundle");
- create_bundle.public_deps().push_back(LabelTargetPair(&executable));
- create_bundle.private_deps().push_back(LabelTargetPair(&bundle_data));
- create_bundle.private_deps().push_back(LabelTargetPair(action.get()));
- create_bundle.SetToolchain(setup.toolchain());
- ASSERT_TRUE(create_bundle.OnResolved(&err));
-
- std::ostringstream out;
- NinjaCreateBundleTargetWriter writer(&create_bundle, out);
- writer.Run();
-
- const char expected[] =
- "build obj/baz/bar.inputdeps.stamp: stamp ./quz obj/foo/bar.stamp "
- "obj/foo/data.stamp\n"
- "rule __baz_bar___toolchain_default__code_signing_rule\n"
- " command = ../../build/codesign.py -b=quz bar.bundle\n"
- " description = CODE SIGNING //baz:bar(//toolchain:default)\n"
- " restat = 1\n"
- "\n"
- "build bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
- "../../foo/input1.txt || obj/baz/bar.inputdeps.stamp\n"
- "build bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
- "../../foo/input2.txt || obj/baz/bar.inputdeps.stamp\n"
- "build obj/baz/bar.codesigning.inputdeps.stamp: stamp "
- "../../build/codesign.py "
- "quz "
- "bar.bundle/Contents/Resources/input1.txt "
- "bar.bundle/Contents/Resources/input2.txt || "
- "obj/baz/bar.inputdeps.stamp\n"
- "build bar.bundle/Contents/quz bar.bundle/_CodeSignature/CodeResources: "
- "__baz_bar___toolchain_default__code_signing_rule "
- "| obj/baz/bar.codesigning.inputdeps.stamp\n"
- "build obj/baz/bar.stamp: stamp "
- "bar.bundle/Contents/quz "
- "bar.bundle/_CodeSignature/CodeResources || obj/baz/bar.inputdeps.stamp\n"
- "build bar.bundle: phony obj/baz/bar.stamp\n";
- std::string out_str = out.str();
- EXPECT_EQ(expected, out_str);
-}
diff --git a/chromium/tools/gn/ninja_group_target_writer.cc b/chromium/tools/gn/ninja_group_target_writer.cc
deleted file mode 100644
index baff95a680b..00000000000
--- a/chromium/tools/gn/ninja_group_target_writer.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/ninja_group_target_writer.h"
-
-#include "base/strings/string_util.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/output_file.h"
-#include "tools/gn/string_utils.h"
-#include "tools/gn/target.h"
-
-NinjaGroupTargetWriter::NinjaGroupTargetWriter(const Target* target,
- std::ostream& out)
- : NinjaTargetWriter(target, out) {
-}
-
-NinjaGroupTargetWriter::~NinjaGroupTargetWriter() = default;
-
-void NinjaGroupTargetWriter::Run() {
- // A group rule just generates a stamp file with dependencies on each of
- // the deps and data_deps in the group.
- std::vector<OutputFile> output_files;
- for (const auto& pair : target_->GetDeps(Target::DEPS_LINKED))
- output_files.push_back(pair.ptr->dependency_output_file());
-
- std::vector<OutputFile> data_output_files;
- const LabelTargetVector& data_deps = target_->data_deps();
- for (const auto& pair : data_deps)
- data_output_files.push_back(pair.ptr->dependency_output_file());
-
- WriteStampForTarget(output_files, data_output_files);
-}
diff --git a/chromium/tools/gn/ninja_group_target_writer.h b/chromium/tools/gn/ninja_group_target_writer.h
deleted file mode 100644
index 66e5f043155..00000000000
--- a/chromium/tools/gn/ninja_group_target_writer.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_NINJA_GROUP_TARGET_WRITER_H_
-#define TOOLS_GN_NINJA_GROUP_TARGET_WRITER_H_
-
-#include "base/macros.h"
-#include "tools/gn/ninja_target_writer.h"
-
-// Writes a .ninja file for a group target type.
-class NinjaGroupTargetWriter : public NinjaTargetWriter {
- public:
- NinjaGroupTargetWriter(const Target* target, std::ostream& out);
- ~NinjaGroupTargetWriter() override;
-
- void Run() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NinjaGroupTargetWriter);
-};
-
-#endif // TOOLS_GN_NINJA_GROUP_TARGET_WRITER_H_
diff --git a/chromium/tools/gn/ninja_group_target_writer_unittest.cc b/chromium/tools/gn/ninja_group_target_writer_unittest.cc
deleted file mode 100644
index 9feb4bd6059..00000000000
--- a/chromium/tools/gn/ninja_group_target_writer_unittest.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/ninja_group_target_writer.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scope.h"
-
-TEST(NinjaGroupTargetWriter, Run) {
- Err err;
- TestWithScope setup;
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
- target.set_output_type(Target::GROUP);
- target.visibility().SetPublic();
-
- Target dep(setup.settings(), Label(SourceDir("//foo/"), "dep"));
- dep.set_output_type(Target::ACTION);
- dep.visibility().SetPublic();
- dep.SetToolchain(setup.toolchain());
- ASSERT_TRUE(dep.OnResolved(&err));
-
- Target dep2(setup.settings(), Label(SourceDir("//foo/"), "dep2"));
- dep2.set_output_type(Target::ACTION);
- dep2.visibility().SetPublic();
- dep2.SetToolchain(setup.toolchain());
- ASSERT_TRUE(dep2.OnResolved(&err));
-
- Target datadep(setup.settings(), Label(SourceDir("//foo/"), "datadep"));
- datadep.set_output_type(Target::ACTION);
- datadep.visibility().SetPublic();
- datadep.SetToolchain(setup.toolchain());
- ASSERT_TRUE(datadep.OnResolved(&err));
-
- target.public_deps().push_back(LabelTargetPair(&dep));
- target.public_deps().push_back(LabelTargetPair(&dep2));
- target.data_deps().push_back(LabelTargetPair(&datadep));
-
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::ostringstream out;
- NinjaGroupTargetWriter writer(&target, out);
- writer.Run();
-
- const char expected[] =
- "build obj/foo/bar.stamp: stamp obj/foo/dep.stamp obj/foo/dep2.stamp || obj/foo/datadep.stamp\n";
- EXPECT_EQ(expected, out.str());
-}
diff --git a/chromium/tools/gn/ninja_target_writer.cc b/chromium/tools/gn/ninja_target_writer.cc
deleted file mode 100644
index c8d1b84cb48..00000000000
--- a/chromium/tools/gn/ninja_target_writer.cc
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/ninja_target_writer.h"
-
-#include <sstream>
-
-#include "base/files/file_util.h"
-#include "base/strings/string_util.h"
-#include "tools/gn/config_values_extractors.h"
-#include "tools/gn/err.h"
-#include "tools/gn/escape.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/ninja_action_target_writer.h"
-#include "tools/gn/ninja_binary_target_writer.h"
-#include "tools/gn/ninja_bundle_data_target_writer.h"
-#include "tools/gn/ninja_copy_target_writer.h"
-#include "tools/gn/ninja_create_bundle_target_writer.h"
-#include "tools/gn/ninja_group_target_writer.h"
-#include "tools/gn/ninja_utils.h"
-#include "tools/gn/output_file.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/string_utils.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/target.h"
-#include "tools/gn/trace.h"
-
-NinjaTargetWriter::NinjaTargetWriter(const Target* target,
- std::ostream& out)
- : settings_(target->settings()),
- target_(target),
- out_(out),
- path_output_(settings_->build_settings()->build_dir(),
- settings_->build_settings()->root_path_utf8(),
- ESCAPE_NINJA) {
-}
-
-NinjaTargetWriter::~NinjaTargetWriter() = default;
-
-// static
-std::string NinjaTargetWriter::RunAndWriteFile(const Target* target) {
- const Settings* settings = target->settings();
-
- ScopedTrace trace(TraceItem::TRACE_FILE_WRITE,
- target->label().GetUserVisibleName(false));
- trace.SetToolchain(settings->toolchain_label());
-
- if (g_scheduler->verbose_logging())
- g_scheduler->Log("Computing", target->label().GetUserVisibleName(true));
-
- // It's ridiculously faster to write to a string and then write that to
- // disk in one operation than to use an fstream here.
- std::stringstream rules;
-
- // Call out to the correct sub-type of writer. Binary targets need to be
- // written to separate files for compiler flag scoping, but other target
- // types can have their rules coalesced.
- //
- // In ninja, if a rule uses a variable (like $include_dirs) it will use
- // the value set by indenting it under the build line or it takes the value
- // from the end of the invoking scope (otherwise the current file). It does
- // not copy the value from what it was when the build line was encountered.
- // To avoid writing lots of duplicate rules for defines and cflags, etc. on
- // each source file build line, we use separate .ninja files with the shared
- // variables set at the top.
- //
- // Groups and actions don't use this type of flag, they make unique rules
- // or write variables scoped under each build line. As a result, they don't
- // need the separate files.
- bool needs_file_write = false;
- if (target->output_type() == Target::BUNDLE_DATA) {
- NinjaBundleDataTargetWriter writer(target, rules);
- writer.Run();
- } else if (target->output_type() == Target::CREATE_BUNDLE) {
- NinjaCreateBundleTargetWriter writer(target, rules);
- writer.Run();
- } else if (target->output_type() == Target::COPY_FILES) {
- NinjaCopyTargetWriter writer(target, rules);
- writer.Run();
- } else if (target->output_type() == Target::ACTION ||
- target->output_type() == Target::ACTION_FOREACH) {
- NinjaActionTargetWriter writer(target, rules);
- writer.Run();
- } else if (target->output_type() == Target::GROUP) {
- NinjaGroupTargetWriter writer(target, rules);
- writer.Run();
- } else if (target->IsBinary()) {
- needs_file_write = true;
- NinjaBinaryTargetWriter writer(target, rules);
- writer.Run();
- } else {
- CHECK(0) << "Output type of target not handled.";
- }
-
- if (needs_file_write) {
- // Write the ninja file.
- SourceFile ninja_file = GetNinjaFileForTarget(target);
- base::FilePath full_ninja_file =
- settings->build_settings()->GetFullPath(ninja_file);
- base::CreateDirectory(full_ninja_file.DirName());
- WriteFileIfChanged(full_ninja_file, rules.str(), nullptr);
-
- EscapeOptions options;
- options.mode = ESCAPE_NINJA;
-
- // Return the subninja command to load the rules file.
- std::string result = "subninja ";
- result.append(EscapeString(
- OutputFile(target->settings()->build_settings(), ninja_file).value(),
- options, nullptr));
- result.push_back('\n');
- return result;
- }
-
- // No separate file required, just return the rules.
- return rules.str();
-}
-
-void NinjaTargetWriter::WriteEscapedSubstitution(SubstitutionType type) {
- EscapeOptions opts;
- opts.mode = ESCAPE_NINJA;
-
- out_ << kSubstitutionNinjaNames[type] << " = ";
- EscapeStringToStream(out_,
- SubstitutionWriter::GetTargetSubstitution(target_, type),
- opts);
- out_ << std::endl;
-}
-
-void NinjaTargetWriter::WriteSharedVars(const SubstitutionBits& bits) {
- bool written_anything = false;
-
- // Target label.
- if (bits.used[SUBSTITUTION_LABEL]) {
- WriteEscapedSubstitution(SUBSTITUTION_LABEL);
- written_anything = true;
- }
-
- // Target label name
- if (bits.used[SUBSTITUTION_LABEL_NAME]) {
- WriteEscapedSubstitution(SUBSTITUTION_LABEL_NAME);
- written_anything = true;
- }
-
- // Root gen dir.
- if (bits.used[SUBSTITUTION_ROOT_GEN_DIR]) {
- WriteEscapedSubstitution(SUBSTITUTION_ROOT_GEN_DIR);
- written_anything = true;
- }
-
- // Root out dir.
- if (bits.used[SUBSTITUTION_ROOT_OUT_DIR]) {
- WriteEscapedSubstitution(SUBSTITUTION_ROOT_OUT_DIR);
- written_anything = true;
- }
-
- // Target gen dir.
- if (bits.used[SUBSTITUTION_TARGET_GEN_DIR]) {
- WriteEscapedSubstitution(SUBSTITUTION_TARGET_GEN_DIR);
- written_anything = true;
- }
-
- // Target out dir.
- if (bits.used[SUBSTITUTION_TARGET_OUT_DIR]) {
- WriteEscapedSubstitution(SUBSTITUTION_TARGET_OUT_DIR);
- written_anything = true;
- }
-
- // Target output name.
- if (bits.used[SUBSTITUTION_TARGET_OUTPUT_NAME]) {
- WriteEscapedSubstitution(SUBSTITUTION_TARGET_OUTPUT_NAME);
- written_anything = true;
- }
-
- // If we wrote any vars, separate them from the rest of the file that follows
- // with a blank line.
- if (written_anything)
- out_ << std::endl;
-}
-
-std::vector<OutputFile> NinjaTargetWriter::WriteInputDepsStampAndGetDep(
- const std::vector<const Target*>& extra_hard_deps,
- size_t num_stamp_uses) const {
- CHECK(target_->toolchain())
- << "Toolchain not set on target "
- << target_->label().GetUserVisibleName(true);
-
- // ----------
- // Collect all input files that are input deps of this target. Knowing the
- // number before writing allows us to either skip writing the input deps
- // stamp or optimize it. Use pointers to avoid copies here.
- std::vector<const SourceFile*> input_deps_sources;
- input_deps_sources.reserve(32);
-
- // Actions get implicit dependencies on the script itself.
- if (target_->output_type() == Target::ACTION ||
- target_->output_type() == Target::ACTION_FOREACH)
- input_deps_sources.push_back(&target_->action_values().script());
-
- // Input files are only considered for non-binary targets which use an
- // implicit dependency instead. The implicit depedency in this case is
- // handled separately by the binary target writer.
- if (!target_->IsBinary()) {
- for (ConfigValuesIterator iter(target_); !iter.done(); iter.Next()) {
- for (const auto& input : iter.cur().inputs())
- input_deps_sources.push_back(&input);
- }
- }
-
- // For an action (where we run a script only once) the sources are the same
- // as the inputs. For action_foreach, the sources will be operated on
- // separately so don't handle them here.
- if (target_->output_type() == Target::ACTION) {
- for (const auto& source : target_->sources())
- input_deps_sources.push_back(&source);
- }
-
- // ----------
- // Collect all target input dependencies of this target as was done for the
- // files above.
- std::vector<const Target*> input_deps_targets;
- input_deps_targets.reserve(32);
-
- // Hard dependencies that are direct or indirect dependencies.
- // These are large (up to 100s), hence why we check other
- const std::set<const Target*>& hard_deps(target_->recursive_hard_deps());
- for (const Target* target : hard_deps)
- input_deps_targets.push_back(target);
-
- // Extra hard dependencies passed in. These are usually empty or small, and
- // we don't want to duplicate the explicit hard deps of the target.
- for (const Target* target : extra_hard_deps) {
- if (!hard_deps.count(target))
- input_deps_targets.push_back(target);
- }
-
- // Toolchain dependencies. These must be resolved before doing anything.
- // This just writes all toolchain deps for simplicity. If we find that
- // toolchains often have more than one dependency, we could consider writing
- // a toolchain-specific stamp file and only include the stamp here.
- // Note that these are usually empty/small.
- const LabelTargetVector& toolchain_deps = target_->toolchain()->deps();
- for (const auto& toolchain_dep : toolchain_deps) {
- // This could theoretically duplicate dependencies already in the list,
- // but it shouldn't happen in practice, is inconvenient to check for,
- // and only results in harmless redundant dependencies listed.
- input_deps_targets.push_back(toolchain_dep.ptr);
- }
-
- // ---------
- // Write the outputs.
-
- if (input_deps_sources.size() + input_deps_targets.size() == 0)
- return std::vector<OutputFile>(); // No input dependencies.
-
- // If we're only generating one input dependency, return it directly instead
- // of writing a stamp file for it.
- if (input_deps_sources.size() == 1 && input_deps_targets.size() == 0)
- return std::vector<OutputFile>{
- OutputFile(settings_->build_settings(), *input_deps_sources[0])};
- if (input_deps_sources.size() == 0 && input_deps_targets.size() == 1) {
- const OutputFile& dep = input_deps_targets[0]->dependency_output_file();
- DCHECK(!dep.value().empty());
- return std::vector<OutputFile>{dep};
- }
-
- std::vector<OutputFile> outs;
- // File input deps.
- for (const SourceFile* source : input_deps_sources)
- outs.push_back(OutputFile(settings_->build_settings(), *source));
- // Target input deps. Sort by label so the output is deterministic (otherwise
- // some of the targets will have gone through std::sets which will have
- // sorted them by pointer).
- std::sort(
- input_deps_targets.begin(), input_deps_targets.end(),
- [](const Target* a, const Target* b) { return a->label() < b->label(); });
- for (auto* dep : input_deps_targets) {
- DCHECK(!dep->dependency_output_file().value().empty());
- outs.push_back(dep->dependency_output_file());
- }
-
- // If there are multiple inputs, but the stamp file would be referenced only
- // once, don't write it but depend on the inputs directly.
- if (num_stamp_uses == 1u)
- return outs;
-
- // Make a stamp file.
- OutputFile input_stamp_file =
- GetBuildDirForTargetAsOutputFile(target_, BuildDirType::OBJ);
- input_stamp_file.value().append(target_->label().name());
- input_stamp_file.value().append(".inputdeps.stamp");
-
- out_ << "build ";
- path_output_.WriteFile(out_, input_stamp_file);
- out_ << ": "
- << GetNinjaRulePrefixForToolchain(settings_)
- << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
- path_output_.WriteFiles(out_, outs);
-
- out_ << "\n";
- return std::vector<OutputFile>{input_stamp_file};
-}
-
-void NinjaTargetWriter::WriteStampForTarget(
- const std::vector<OutputFile>& files,
- const std::vector<OutputFile>& order_only_deps) {
- const OutputFile& stamp_file = target_->dependency_output_file();
-
- // First validate that the target's dependency is a stamp file. Otherwise,
- // we shouldn't have gotten here!
- CHECK(base::EndsWith(stamp_file.value(), ".stamp",
- base::CompareCase::INSENSITIVE_ASCII))
- << "Output should end in \".stamp\" for stamp file output. Instead got: "
- << "\"" << stamp_file.value() << "\"";
-
- out_ << "build ";
- path_output_.WriteFile(out_, stamp_file);
-
- out_ << ": "
- << GetNinjaRulePrefixForToolchain(settings_)
- << Toolchain::ToolTypeToName(Toolchain::TYPE_STAMP);
- path_output_.WriteFiles(out_, files);
-
- if (!order_only_deps.empty()) {
- out_ << " ||";
- path_output_.WriteFiles(out_, order_only_deps);
- }
- out_ << std::endl;
-}
diff --git a/chromium/tools/gn/ninja_target_writer.h b/chromium/tools/gn/ninja_target_writer.h
deleted file mode 100644
index dc9a8855a20..00000000000
--- a/chromium/tools/gn/ninja_target_writer.h
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_NINJA_TARGET_WRITER_H_
-#define TOOLS_GN_NINJA_TARGET_WRITER_H_
-
-#include <iosfwd>
-
-#include "base/macros.h"
-#include "tools/gn/path_output.h"
-#include "tools/gn/substitution_type.h"
-
-class OutputFile;
-class Settings;
-class Target;
-struct SubstitutionBits;
-
-// Generates one target's ".ninja" file. The toplevel "build.ninja" file is
-// generated by the NinjaBuildWriter.
-class NinjaTargetWriter {
- public:
- NinjaTargetWriter(const Target* target, std::ostream& out);
- virtual ~NinjaTargetWriter();
-
- // Returns the build line to be written to the toolchain build file.
- //
- // Some targets have their rules written to separate files, and some can have
- // their rules coalesced in the main build file. For the coalesced case, this
- // function will return the rules as a string. For the separate file case,
- // the separate ninja file will be written and the return string will be the
- // subninja command to load that file.
- static std::string RunAndWriteFile(const Target* target);
-
- virtual void Run() = 0;
-
- protected:
- // Writes out the substitution values that are shared between the different
- // types of tools (target gen dir, target label, etc.). Only the substitutions
- // identified by the given bits will be written.
- void WriteSharedVars(const SubstitutionBits& bits);
-
- // Writes to the output stream a stamp rule for input dependencies, and
- // returns the file to be appended to source rules that encodes the
- // order-only dependencies for the current target.
- // If num_stamp_uses is small, this might return all input dependencies
- // directly, without writing a stamp file.
- // If there are no implicit dependencies and no extra target dependencies
- // are passed in, this returns an empty vector.
- std::vector<OutputFile> WriteInputDepsStampAndGetDep(
- const std::vector<const Target*>& extra_hard_deps,
- size_t num_stamp_uses) const;
-
- // Writes to the output file a final stamp rule for the target that stamps
- // the given list of files. This function assumes the stamp is for the target
- // as a whole so the stamp file is set as the target's dependency output.
- void WriteStampForTarget(const std::vector<OutputFile>& deps,
- const std::vector<OutputFile>& order_only_deps);
-
- const Settings* settings_; // Non-owning.
- const Target* target_; // Non-owning.
- std::ostream& out_;
- PathOutput path_output_;
-
- private:
- void WriteCopyRules();
- void WriteEscapedSubstitution(SubstitutionType type);
-
- DISALLOW_COPY_AND_ASSIGN(NinjaTargetWriter);
-};
-
-#endif // TOOLS_GN_NINJA_TARGET_WRITER_H_
diff --git a/chromium/tools/gn/ninja_target_writer_unittest.cc b/chromium/tools/gn/ninja_target_writer_unittest.cc
deleted file mode 100644
index 38dd8de56a3..00000000000
--- a/chromium/tools/gn/ninja_target_writer_unittest.cc
+++ /dev/null
@@ -1,164 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <sstream>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/ninja_action_target_writer.h"
-#include "tools/gn/ninja_target_writer.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-class TestingNinjaTargetWriter : public NinjaTargetWriter {
- public:
- TestingNinjaTargetWriter(const Target* target,
- const Toolchain* toolchain,
- std::ostream& out)
- : NinjaTargetWriter(target, out) {
- }
-
- void Run() override {}
-
- // Make this public so the test can call it.
- std::vector<OutputFile> WriteInputDepsStampAndGetDep(
- const std::vector<const Target*>& extra_hard_deps,
- size_t num_stamp_uses) {
- return NinjaTargetWriter::WriteInputDepsStampAndGetDep(extra_hard_deps,
- num_stamp_uses);
- }
-};
-
-} // namespace
-
-TEST(NinjaTargetWriter, WriteInputDepsStampAndGetDep) {
- TestWithScope setup;
- Err err;
-
- // Make a base target that's a hard dep (action).
- Target base_target(setup.settings(), Label(SourceDir("//foo/"), "base"));
- base_target.set_output_type(Target::ACTION);
- base_target.visibility().SetPublic();
- base_target.SetToolchain(setup.toolchain());
- base_target.action_values().set_script(SourceFile("//foo/script.py"));
-
- // Dependent target that also includes a source prerequisite (should get
- // included) and a source (should not be included).
- Target target(setup.settings(), Label(SourceDir("//foo/"), "target"));
- target.set_output_type(Target::EXECUTABLE);
- target.visibility().SetPublic();
- target.SetToolchain(setup.toolchain());
- target.config_values().inputs().push_back(SourceFile("//foo/input.txt"));
- target.sources().push_back(SourceFile("//foo/source.txt"));
- target.public_deps().push_back(LabelTargetPair(&base_target));
-
- // Dependent action to test that action sources will be treated the same as
- // inputs.
- Target action(setup.settings(), Label(SourceDir("//foo/"), "action"));
- action.set_output_type(Target::ACTION);
- action.visibility().SetPublic();
- action.SetToolchain(setup.toolchain());
- action.action_values().set_script(SourceFile("//foo/script.py"));
- action.sources().push_back(SourceFile("//foo/action_source.txt"));
- action.public_deps().push_back(LabelTargetPair(&target));
-
- ASSERT_TRUE(base_target.OnResolved(&err));
- ASSERT_TRUE(target.OnResolved(&err));
- ASSERT_TRUE(action.OnResolved(&err));
-
- // Input deps for the base (should be only the script itself).
- {
- std::ostringstream stream;
- TestingNinjaTargetWriter writer(&base_target, setup.toolchain(), stream);
- std::vector<OutputFile> dep =
- writer.WriteInputDepsStampAndGetDep(std::vector<const Target*>(), 10u);
-
- // Since there is only one dependency, it should just be returned and
- // nothing written to the stream.
- ASSERT_EQ(1u, dep.size());
- EXPECT_EQ("../../foo/script.py", dep[0].value());
- EXPECT_EQ("", stream.str());
- }
-
- // Input deps for the target (should depend on the base).
- {
- std::ostringstream stream;
- TestingNinjaTargetWriter writer(&target, setup.toolchain(), stream);
- std::vector<OutputFile> dep =
- writer.WriteInputDepsStampAndGetDep(std::vector<const Target*>(), 10u);
-
- // Since there is only one dependency, a stamp file will be returned
- // directly without writing any additional rules.
- ASSERT_EQ(1u, dep.size());
- EXPECT_EQ("obj/foo/base.stamp", dep[0].value());
- }
-
- {
- std::ostringstream stream;
- NinjaActionTargetWriter writer(&action, stream);
- writer.Run();
- EXPECT_EQ(
- "rule __foo_action___rule\n"
- " command = ../../foo/script.py\n"
- " description = ACTION //foo:action()\n"
- " restat = 1\n"
- "\n"
- "build: __foo_action___rule | ../../foo/script.py"
- " ../../foo/action_source.txt ./target\n"
- "\n"
- "build obj/foo/action.stamp: stamp\n",
- stream.str());
- }
-
- // Input deps for action which should depend on the base since its a hard dep
- // that is a (indirect) dependency, as well as the the action source.
- {
- std::ostringstream stream;
- TestingNinjaTargetWriter writer(&action, setup.toolchain(), stream);
- std::vector<OutputFile> dep =
- writer.WriteInputDepsStampAndGetDep(std::vector<const Target*>(), 10u);
-
- ASSERT_EQ(1u, dep.size());
- EXPECT_EQ("obj/foo/action.inputdeps.stamp", dep[0].value());
- EXPECT_EQ(
- "build obj/foo/action.inputdeps.stamp: stamp ../../foo/script.py "
- "../../foo/action_source.txt ./target\n",
- stream.str());
- }
-}
-
-// Tests WriteInputDepsStampAndGetDep when toolchain deps are present.
-TEST(NinjaTargetWriter, WriteInputDepsStampAndGetDepWithToolchainDeps) {
- TestWithScope setup;
- Err err;
-
- // Toolchain dependency. Here we make a target in the same toolchain for
- // simplicity, but in real life (using the Builder) this would be rejected
- // because it would be a circular dependency (the target depends on its
- // toolchain, and the toolchain depends on this target).
- Target toolchain_dep_target(setup.settings(),
- Label(SourceDir("//foo/"), "setup"));
- toolchain_dep_target.set_output_type(Target::ACTION);
- toolchain_dep_target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(toolchain_dep_target.OnResolved(&err));
- setup.toolchain()->deps().push_back(LabelTargetPair(&toolchain_dep_target));
-
- // Make a binary target
- Target target(setup.settings(), Label(SourceDir("//foo/"), "target"));
- target.set_output_type(Target::EXECUTABLE);
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::ostringstream stream;
- TestingNinjaTargetWriter writer(&target, setup.toolchain(), stream);
- std::vector<OutputFile> dep =
- writer.WriteInputDepsStampAndGetDep(std::vector<const Target*>(), 10u);
-
- // Since there is more than one dependency, a stamp file will be returned
- // and the rule for the stamp file will be written to the stream.
- ASSERT_EQ(1u, dep.size());
- EXPECT_EQ("obj/foo/setup.stamp", dep[0].value());
- EXPECT_EQ("", stream.str());
-}
diff --git a/chromium/tools/gn/ninja_toolchain_writer.cc b/chromium/tools/gn/ninja_toolchain_writer.cc
deleted file mode 100644
index d22740fd4df..00000000000
--- a/chromium/tools/gn/ninja_toolchain_writer.cc
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/ninja_toolchain_writer.h"
-
-#include <fstream>
-
-#include "base/files/file_util.h"
-#include "base/strings/stringize_macros.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/ninja_utils.h"
-#include "tools/gn/pool.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/target.h"
-#include "tools/gn/toolchain.h"
-#include "tools/gn/trace.h"
-
-namespace {
-
-const char kIndent[] = " ";
-
-} // namespace
-
-NinjaToolchainWriter::NinjaToolchainWriter(
- const Settings* settings,
- const Toolchain* toolchain,
- std::ostream& out)
- : settings_(settings),
- toolchain_(toolchain),
- out_(out),
- path_output_(settings_->build_settings()->build_dir(),
- settings_->build_settings()->root_path_utf8(),
- ESCAPE_NINJA) {
-}
-
-NinjaToolchainWriter::~NinjaToolchainWriter() = default;
-
-void NinjaToolchainWriter::Run(
- const std::vector<NinjaWriter::TargetRulePair>& rules) {
- std::string rule_prefix = GetNinjaRulePrefixForToolchain(settings_);
-
- for (int i = Toolchain::TYPE_NONE + 1; i < Toolchain::TYPE_NUMTYPES; i++) {
- Toolchain::ToolType tool_type = static_cast<Toolchain::ToolType>(i);
- const Tool* tool = toolchain_->GetTool(tool_type);
- if (tool_type == Toolchain::TYPE_ACTION)
- continue;
- if (tool)
- WriteToolRule(tool_type, tool, rule_prefix);
- }
- out_ << std::endl;
-
- for (const auto& pair : rules)
- out_ << pair.second;
-}
-
-// static
-bool NinjaToolchainWriter::RunAndWriteFile(
- const Settings* settings,
- const Toolchain* toolchain,
- const std::vector<NinjaWriter::TargetRulePair>& rules) {
- base::FilePath ninja_file(settings->build_settings()->GetFullPath(
- GetNinjaFileForToolchain(settings)));
- ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, FilePathToUTF8(ninja_file));
-
- base::CreateDirectory(ninja_file.DirName());
-
- std::ofstream file;
- file.open(FilePathToUTF8(ninja_file).c_str(),
- std::ios_base::out | std::ios_base::binary);
- if (file.fail())
- return false;
-
- NinjaToolchainWriter gen(settings, toolchain, file);
- gen.Run(rules);
- return true;
-}
-
-void NinjaToolchainWriter::WriteToolRule(const Toolchain::ToolType type,
- const Tool* tool,
- const std::string& rule_prefix) {
- out_ << "rule " << rule_prefix << Toolchain::ToolTypeToName(type)
- << std::endl;
-
- // Rules explicitly include shell commands, so don't try to escape.
- EscapeOptions options;
- options.mode = ESCAPE_NINJA_PREFORMATTED_COMMAND;
-
- CHECK(!tool->command().empty()) << "Command should not be empty";
- WriteRulePattern("command", tool->command(), options);
-
- WriteRulePattern("description", tool->description(), options);
- WriteRulePattern("rspfile", tool->rspfile(), options);
- WriteRulePattern("rspfile_content", tool->rspfile_content(), options);
-
- if (tool->depsformat() == Tool::DEPS_GCC) {
- // GCC-style deps require a depfile.
- if (!tool->depfile().empty()) {
- WriteRulePattern("depfile", tool->depfile(), options);
- out_ << kIndent << "deps = gcc" << std::endl;
- }
- } else if (tool->depsformat() == Tool::DEPS_MSVC) {
- // MSVC deps don't have a depfile.
- out_ << kIndent << "deps = msvc" << std::endl;
- }
-
- // Use pool is specified.
- if (tool->pool().ptr) {
- std::string pool_name =
- tool->pool().ptr->GetNinjaName(settings_->default_toolchain_label());
- out_ << kIndent << "pool = " << pool_name << std::endl;
- }
-
- if (tool->restat())
- out_ << kIndent << "restat = 1" << std::endl;
-}
-
-void NinjaToolchainWriter::WriteRulePattern(const char* name,
- const SubstitutionPattern& pattern,
- const EscapeOptions& options) {
- if (pattern.empty())
- return;
- out_ << kIndent << name << " = ";
- SubstitutionWriter::WriteWithNinjaVariables(pattern, options, out_);
- out_ << std::endl;
-}
diff --git a/chromium/tools/gn/ninja_toolchain_writer.h b/chromium/tools/gn/ninja_toolchain_writer.h
deleted file mode 100644
index 9c6ad24b96b..00000000000
--- a/chromium/tools/gn/ninja_toolchain_writer.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_NINJA_TOOLCHAIN_WRITER_H_
-#define TOOLS_GN_NINJA_TOOLCHAIN_WRITER_H_
-
-#include <iosfwd>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "tools/gn/ninja_writer.h"
-#include "tools/gn/path_output.h"
-#include "tools/gn/toolchain.h"
-
-struct EscapeOptions;
-class Settings;
-class Tool;
-
-class NinjaToolchainWriter {
- public:
- // Takes the settings for the toolchain, as well as the list of all targets
- // associated with the toolchain.
- static bool RunAndWriteFile(
- const Settings* settings,
- const Toolchain* toolchain,
- const std::vector<NinjaWriter::TargetRulePair>& rules);
-
- private:
- FRIEND_TEST_ALL_PREFIXES(NinjaToolchainWriter, WriteToolRule);
-
- NinjaToolchainWriter(const Settings* settings,
- const Toolchain* toolchain,
- std::ostream& out);
- ~NinjaToolchainWriter();
-
- void Run(const std::vector<NinjaWriter::TargetRulePair>& extra_rules);
-
- void WriteRules();
- void WriteToolRule(Toolchain::ToolType type,
- const Tool* tool,
- const std::string& rule_prefix);
- void WriteRulePattern(const char* name,
- const SubstitutionPattern& pattern,
- const EscapeOptions& options);
-
- const Settings* settings_;
- const Toolchain* toolchain_;
- std::ostream& out_;
- PathOutput path_output_;
-
- DISALLOW_COPY_AND_ASSIGN(NinjaToolchainWriter);
-};
-
-#endif // TOOLS_GN_NINJA_TOOLCHAIN_WRITER_H_
diff --git a/chromium/tools/gn/ninja_toolchain_writer_unittest.cc b/chromium/tools/gn/ninja_toolchain_writer_unittest.cc
deleted file mode 100644
index 4e9d7674957..00000000000
--- a/chromium/tools/gn/ninja_toolchain_writer_unittest.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <sstream>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/ninja_toolchain_writer.h"
-#include "tools/gn/test_with_scope.h"
-
-TEST(NinjaToolchainWriter, WriteToolRule) {
- TestWithScope setup;
-
- std::ostringstream stream;
- NinjaToolchainWriter writer(setup.settings(), setup.toolchain(), stream);
- writer.WriteToolRule(Toolchain::TYPE_CC,
- setup.toolchain()->GetTool(Toolchain::TYPE_CC),
- std::string("prefix_"));
-
- EXPECT_EQ(
- "rule prefix_cc\n"
- " command = cc ${in} ${cflags} ${cflags_c} ${defines} ${include_dirs} "
- "-o ${out}\n",
- stream.str());
-}
diff --git a/chromium/tools/gn/ninja_utils.cc b/chromium/tools/gn/ninja_utils.cc
deleted file mode 100644
index 9e9039220af..00000000000
--- a/chromium/tools/gn/ninja_utils.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/ninja_utils.h"
-
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/target.h"
-
-SourceFile GetNinjaFileForTarget(const Target* target) {
- return SourceFile(
- GetBuildDirForTargetAsSourceDir(target, BuildDirType::OBJ).value() +
- target->label().name() + ".ninja");
-}
-
-SourceFile GetNinjaFileForToolchain(const Settings* settings) {
- return SourceFile(GetBuildDirAsSourceDir(
- BuildDirContext(settings), BuildDirType::TOOLCHAIN_ROOT).value() +
- "toolchain.ninja");
-}
-
-std::string GetNinjaRulePrefixForToolchain(const Settings* settings) {
- // Don't prefix the default toolchain so it looks prettier, prefix everything
- // else.
- if (settings->is_default())
- return std::string(); // Default toolchain has no prefix.
- return settings->toolchain_label().name() + "_";
-}
diff --git a/chromium/tools/gn/ninja_utils.h b/chromium/tools/gn/ninja_utils.h
deleted file mode 100644
index 60ae6b27a66..00000000000
--- a/chromium/tools/gn/ninja_utils.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_NINJA_UTILS_H_
-#define TOOLS_GN_NINJA_UTILS_H_
-
-#include <string>
-
-class Settings;
-class SourceFile;
-class Target;
-
-// Example: "base/base.ninja". The string version will not be escaped, and
-// will always have slashes for path separators.
-SourceFile GetNinjaFileForTarget(const Target* target);
-
-// Returns the name of the root .ninja file for the given toolchain.
-SourceFile GetNinjaFileForToolchain(const Settings* settings);
-
-// Returns the prefix applied to the Ninja rules in a given toolchain so they
-// don't collide with rules from other toolchains.
-std::string GetNinjaRulePrefixForToolchain(const Settings* settings);
-
-#endif // TOOLS_GN_NINJA_UTILS_H_
diff --git a/chromium/tools/gn/ninja_writer.cc b/chromium/tools/gn/ninja_writer.cc
deleted file mode 100644
index 3326f83a6c0..00000000000
--- a/chromium/tools/gn/ninja_writer.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/ninja_writer.h"
-
-#include "tools/gn/builder.h"
-#include "tools/gn/loader.h"
-#include "tools/gn/location.h"
-#include "tools/gn/ninja_build_writer.h"
-#include "tools/gn/ninja_toolchain_writer.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/target.h"
-
-NinjaWriter::NinjaWriter(const Builder& builder)
- : builder_(builder) {
-}
-
-NinjaWriter::~NinjaWriter() = default;
-
-// static
-bool NinjaWriter::RunAndWriteFiles(
- const BuildSettings* build_settings,
- const Builder& builder,
- const PerToolchainRules& per_toolchain_rules,
- Err* err) {
- NinjaWriter writer(builder);
-
- if (!writer.WriteToolchains(per_toolchain_rules, err))
- return false;
- return NinjaBuildWriter::RunAndWriteFile(build_settings, builder, err);
-}
-
-bool NinjaWriter::WriteToolchains(const PerToolchainRules& per_toolchain_rules,
- Err* err) {
- if (per_toolchain_rules.empty()) {
- Err(Location(), "No targets.",
- "I could not find any targets to write, so I'm doing nothing.")
- .PrintToStdout();
- return false;
- }
-
- for (const auto& i : per_toolchain_rules) {
- const Toolchain* toolchain = i.first;
- const Settings* settings =
- builder_.loader()->GetToolchainSettings(toolchain->label());
- if (!NinjaToolchainWriter::RunAndWriteFile(settings, toolchain, i.second)) {
- Err(Location(),
- "Couldn't open toolchain buildfile(s) for writing").PrintToStdout();
- return false;
- }
- }
-
- return true;
-}
diff --git a/chromium/tools/gn/ninja_writer.h b/chromium/tools/gn/ninja_writer.h
deleted file mode 100644
index 6372f0cf35d..00000000000
--- a/chromium/tools/gn/ninja_writer.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_NINJA_WRITER_H_
-#define TOOLS_GN_NINJA_WRITER_H_
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-
-class Builder;
-class BuildSettings;
-class Err;
-class Target;
-class Toolchain;
-
-class NinjaWriter {
- public:
- // Combines a target and the computed build rule for it.
- using TargetRulePair = std::pair<const Target*, std::string>;
-
- // Associates the build rules with each toolchain.
- using PerToolchainRules =
- std::map<const Toolchain*, std::vector<TargetRulePair>>;
-
- // On failure will populate |err| and will return false. The map contains
- // the per-toolchain set of rules collected to write to the toolchain build
- // files.
- static bool RunAndWriteFiles(
- const BuildSettings* build_settings,
- const Builder& builder,
- const PerToolchainRules& per_toolchain_rules,
- Err* err);
-
- private:
- NinjaWriter(const Builder& builder);
- ~NinjaWriter();
-
- bool WriteToolchains(const PerToolchainRules& per_toolchain_rules,
- Err* err);
-
- const Builder& builder_;
-
- DISALLOW_COPY_AND_ASSIGN(NinjaWriter);
-};
-
-#endif // TOOLS_GN_NINJA_WRITER_H_
diff --git a/chromium/tools/gn/operators.cc b/chromium/tools/gn/operators.cc
deleted file mode 100644
index 8bef028857f..00000000000
--- a/chromium/tools/gn/operators.cc
+++ /dev/null
@@ -1,783 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/operators.h"
-
-#include <stddef.h>
-#include <algorithm>
-
-#include "base/strings/string_number_conversions.h"
-#include "tools/gn/err.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/token.h"
-#include "tools/gn/value.h"
-
-namespace {
-
-const char kSourcesName[] = "sources";
-
-// Helper class used for assignment operations: =, +=, and -= to generalize
-// writing to various types of destinations.
-class ValueDestination {
- public:
- ValueDestination();
-
- bool Init(Scope* exec_scope,
- const ParseNode* dest,
- const BinaryOpNode* op_node,
- Err* err);
-
- // Returns the value in the destination scope if it already exists, or null
- // if it doesn't. This is for validation and does not count as a "use".
- // Other nested scopes will be searched.
- const Value* GetExistingValue() const;
-
- // Returns an existing version of the output if it can be modified. This will
- // not search nested scopes since writes only go into the current scope.
- // Returns null if the value does not exist, or is not in the current scope
- // (meaning assignments won't go to this value and it's not mutable). This
- // is for implementing += and -=.
- //
- // If it exists, this will mark the origin of the value to be the passed-in
- // node, and the value will be also marked unused (if possible) under the
- // assumption that it will be modified in-place.
- Value* GetExistingMutableValueIfExists(const ParseNode* origin);
-
- // Returns the sources assignment filter if it exists for the current
- // scope and it should be applied to this assignment. Otherwise returns null.
- const PatternList* GetAssignmentFilter(const Scope* exec_scope) const;
-
- // Returns a pointer to the value that was set.
- Value* SetValue(Value value, const ParseNode* set_node);
-
- // Fills the Err with an undefined value error appropriate for modification
- // operators: += and -= (where the source is also the dest).
- void MakeUndefinedIdentifierForModifyError(Err* err);
-
- private:
- enum Type { UNINITIALIZED, SCOPE, LIST };
-
- Type type_;
-
- // Valid when type_ == SCOPE.
- Scope* scope_;
- const Token* name_token_;
-
- // Valid when type_ == LIST.
- Value* list_;
- size_t index_; // Guaranteed in-range when Init() succeeds.
-};
-
-ValueDestination::ValueDestination()
- : type_(UNINITIALIZED),
- scope_(nullptr),
- name_token_(nullptr),
- list_(nullptr),
- index_(0) {
-}
-
-bool ValueDestination::Init(Scope* exec_scope,
- const ParseNode* dest,
- const BinaryOpNode* op_node,
- Err* err) {
- // Check for standard variable set.
- const IdentifierNode* dest_identifier = dest->AsIdentifier();
- if (dest_identifier) {
- type_ = SCOPE;
- scope_ = exec_scope;
- name_token_ = &dest_identifier->value();
- return true;
- }
-
- // Check for array and scope accesses. The base (array or scope variable
- // name) must always be defined ahead of time.
- const AccessorNode* dest_accessor = dest->AsAccessor();
- if (!dest_accessor) {
- *err = Err(op_node, "Assignment requires a lvalue.",
- "This thing on the left is not an identifier or accessor.");
- err->AppendRange(dest->GetRange());
- return false;
- }
-
- // Known to be an accessor.
- base::StringPiece base_str = dest_accessor->base().value();
- Value* base = exec_scope->GetMutableValue(
- base_str, Scope::SEARCH_CURRENT, false);
- if (!base) {
- // Base is either undefined or it's defined but not in the current scope.
- // Make a good error message.
- if (exec_scope->GetValue(base_str, false)) {
- *err = Err(dest_accessor->base(), "Suspicious in-place modification.",
- "This variable exists in a containing scope. Normally, writing to it "
- "would\nmake a copy of it into the current scope with the modified "
- "version. But\nhere you're modifying only an element of a scope or "
- "list object. It's unlikely\nyou meant to copy the entire thing just "
- "to modify this part of it.\n"
- "\n"
- "If you really wanted to do this, do:\n"
- " " + base_str.as_string() + " = " + base_str.as_string() + "\n"
- "to copy it into the current scope before doing this operation.");
- } else {
- *err = Err(dest_accessor->base(), "Undefined identifier.");
- }
- return false;
- }
-
- if (dest_accessor->index()) {
- // List access with an index.
- if (!base->VerifyTypeIs(Value::LIST, err)) {
- // Errors here will confusingly refer to the variable declaration (since
- // that's all Value knows) rather than the list access. So rewrite the
- // error location to refer to the base value's location.
- *err = Err(dest_accessor->base(), err->message(), err->help_text());
- return false;
- }
-
- type_ = LIST;
- list_ = base;
- return dest_accessor->ComputeAndValidateListIndex(
- exec_scope, base->list_value().size(), &index_, err);
- }
-
- // Scope access with a dot.
- if (!base->VerifyTypeIs(Value::SCOPE, err)) {
- // As the for the list index case above, rewrite the error location.
- *err = Err(dest_accessor->base(), err->message(), err->help_text());
- return false;
- }
- type_ = SCOPE;
- scope_ = base->scope_value();
- name_token_ = &dest_accessor->member()->value();
- return true;
-}
-
-const Value* ValueDestination::GetExistingValue() const {
- if (type_ == SCOPE)
- return scope_->GetValue(name_token_->value(), true);
- else if (type_ == LIST)
- return &list_->list_value()[index_];
- return nullptr;
-}
-
-Value* ValueDestination::GetExistingMutableValueIfExists(
- const ParseNode* origin) {
- if (type_ == SCOPE) {
- Value* value = scope_->GetMutableValue(
- name_token_->value(), Scope::SEARCH_CURRENT, false);
- if (value) {
- // The value will be written to, reset its tracking information.
- value->set_origin(origin);
- scope_->MarkUnused(name_token_->value());
- }
- }
- if (type_ == LIST)
- return &list_->list_value()[index_];
- return nullptr;
-}
-
-const PatternList* ValueDestination::GetAssignmentFilter(
- const Scope* exec_scope) const {
- if (type_ != SCOPE)
- return nullptr; // Destination can't be named, so no sources filtering.
- if (name_token_->value() != kSourcesName)
- return nullptr; // Destination not named "sources".
-
- const PatternList* filter = exec_scope->GetSourcesAssignmentFilter();
- if (!filter || filter->is_empty())
- return nullptr; // No filter or empty filter, don't need to do anything.
- return filter;
-}
-
-Value* ValueDestination::SetValue(Value value, const ParseNode* set_node) {
- if (type_ == SCOPE) {
- return scope_->SetValue(name_token_->value(), std::move(value), set_node);
- } else if (type_ == LIST) {
- Value* dest = &list_->list_value()[index_];
- *dest = std::move(value);
- return dest;
- }
- return nullptr;
-}
-
-void ValueDestination::MakeUndefinedIdentifierForModifyError(Err* err) {
- // When Init() succeeds, the base of any accessor has already been resolved
- // and that list indices are in-range. This means any undefined identifiers
- // are for scope accesses.
- DCHECK(type_ == SCOPE);
- *err = Err(*name_token_, "Undefined identifier.");
-}
-
-// Computes an error message for overwriting a nonempty list/scope with another.
-Err MakeOverwriteError(const BinaryOpNode* op_node,
- const Value& old_value) {
- std::string type_name;
- std::string empty_def;
-
- if (old_value.type() == Value::LIST) {
- type_name = "list";
- empty_def = "[]";
- } else if (old_value.type() == Value::SCOPE) {
- type_name = "scope";
- empty_def = "{}";
- } else {
- NOTREACHED();
- }
-
- Err result(op_node->left()->GetRange(),
- "Replacing nonempty " + type_name + ".",
- "This overwrites a previously-defined nonempty " + type_name +
- " with another nonempty " + type_name + ".");
- result.AppendSubErr(Err(old_value, "for previous definition",
- "Did you mean to append/modify instead? If you really want to overwrite, "
- "do:\n"
- " foo = " + empty_def + "\nbefore reassigning."));
- return result;
-}
-
-// -----------------------------------------------------------------------------
-
-Err MakeIncompatibleTypeError(const BinaryOpNode* op_node,
- const Value& left,
- const Value& right) {
- std::string msg =
- std::string("You can't do <") + Value::DescribeType(left.type()) + "> " +
- op_node->op().value().as_string() +
- " <" + Value::DescribeType(right.type()) + ">.";
- if (left.type() == Value::LIST) {
- // Append extra hint for list stuff.
- msg += "\n\nHint: If you're attempting to add or remove a single item from "
- " a list, use \"foo + [ bar ]\".";
- }
- return Err(op_node, "Incompatible types for binary operator.", msg);
-}
-
-Value GetValueOrFillError(const BinaryOpNode* op_node,
- const ParseNode* node,
- const char* name,
- Scope* scope,
- Err* err) {
- Value value = node->Execute(scope, err);
- if (err->has_error())
- return Value();
- if (value.type() == Value::NONE) {
- *err = Err(op_node->op(),
- "Operator requires a value.",
- "This thing on the " + std::string(name) +
- " does not evaluate to a value.");
- err->AppendRange(node->GetRange());
- return Value();
- }
- return value;
-}
-
-void RemoveMatchesFromList(const BinaryOpNode* op_node,
- Value* list,
- const Value& to_remove,
- Err* err) {
- std::vector<Value>& v = list->list_value();
- switch (to_remove.type()) {
- case Value::BOOLEAN:
- case Value::INTEGER: // Filter out the individual int/string.
- case Value::STRING: {
- bool found_match = false;
- for (size_t i = 0; i < v.size(); /* nothing */) {
- if (v[i] == to_remove) {
- found_match = true;
- v.erase(v.begin() + i);
- } else {
- i++;
- }
- }
- if (!found_match) {
- *err = Err(to_remove.origin()->GetRange(), "Item not found",
- "You were trying to remove " + to_remove.ToString(true) +
- "\nfrom the list but it wasn't there.");
- }
- break;
- }
-
- case Value::LIST: // Filter out each individual thing.
- for (const auto& elem : to_remove.list_value()) {
- // TODO(brettw) if the nested item is a list, we may want to search
- // for the literal list rather than remote the items in it.
- RemoveMatchesFromList(op_node, list, elem, err);
- if (err->has_error())
- return;
- }
- break;
-
- default:
- break;
- }
-}
-
-// Assignment -----------------------------------------------------------------
-
-// We return a null value from this rather than the result of doing the append.
-// See ValuePlusEquals for rationale.
-Value ExecuteEquals(Scope* exec_scope,
- const BinaryOpNode* op_node,
- ValueDestination* dest,
- Value right,
- Err* err) {
- const Value* old_value = dest->GetExistingValue();
- if (old_value) {
- // Check for overwriting nonempty scopes or lists with other nonempty
- // scopes or lists. This prevents mistakes that clobber a value rather than
- // appending to it. For cases where a user meant to clear a value, allow
- // overwriting a nonempty list/scope with an empty one, which can then be
- // modified.
- if (old_value->type() == Value::LIST && right.type() == Value::LIST &&
- !old_value->list_value().empty() && !right.list_value().empty()) {
- *err = MakeOverwriteError(op_node, *old_value);
- return Value();
- } else if (old_value->type() == Value::SCOPE &&
- right.type() == Value::SCOPE &&
- old_value->scope_value()->HasValues(Scope::SEARCH_CURRENT) &&
- right.scope_value()->HasValues(Scope::SEARCH_CURRENT)) {
- *err = MakeOverwriteError(op_node, *old_value);
- return Value();
- }
- }
-
- Value* written_value = dest->SetValue(std::move(right), op_node->right());
-
- // Optionally apply the assignment filter in-place.
- const PatternList* filter = dest->GetAssignmentFilter(exec_scope);
- if (filter) {
- std::vector<Value>& list_value = written_value->list_value();
- auto first_deleted = std::remove_if(
- list_value.begin(), list_value.end(),
- [filter](const Value& v) {
- return filter->MatchesValue(v);
- });
- list_value.erase(first_deleted, list_value.end());
- }
- return Value();
-}
-
-// Plus/minus ------------------------------------------------------------------
-
-// allow_left_type_conversion indicates if we're allowed to change the type of
-// the left value. This is set to true when doing +, and false when doing +=.
-Value ExecutePlus(const BinaryOpNode* op_node,
- Value left,
- Value right,
- bool allow_left_type_conversion,
- Err* err) {
- // Left-hand-side integer.
- if (left.type() == Value::INTEGER) {
- if (right.type() == Value::INTEGER) {
- // Int + int -> addition.
- return Value(op_node, left.int_value() + right.int_value());
- } else if (right.type() == Value::STRING && allow_left_type_conversion) {
- // Int + string -> string concat.
- return Value(
- op_node,
- base::Int64ToString(left.int_value()) + right.string_value());
- }
- *err = MakeIncompatibleTypeError(op_node, left, right);
- return Value();
- }
-
- // Left-hand-side string.
- if (left.type() == Value::STRING) {
- if (right.type() == Value::INTEGER) {
- // String + int -> string concat.
- return Value(op_node,
- left.string_value() + base::Int64ToString(right.int_value()));
- } else if (right.type() == Value::STRING) {
- // String + string -> string concat. Since the left is passed by copy
- // we can avoid realloc if there is enough buffer by appending to left
- // and assigning.
- left.string_value().append(right.string_value());
- return left; // FIXME(brettw) des this copy?
- }
- *err = MakeIncompatibleTypeError(op_node, left, right);
- return Value();
- }
-
- // Left-hand-side list. The only valid thing is to add another list.
- if (left.type() == Value::LIST && right.type() == Value::LIST) {
- // Since left was passed by copy, avoid realloc by destructively appending
- // to it and using that as the result.
- for (Value& value : right.list_value())
- left.list_value().push_back(std::move(value));
- return left; // FIXME(brettw) does this copy?
- }
-
- *err = MakeIncompatibleTypeError(op_node, left, right);
- return Value();
-}
-
-// Left is passed by value because it will be modified in-place and returned
-// for the list case.
-Value ExecuteMinus(const BinaryOpNode* op_node,
- Value left,
- const Value& right,
- Err* err) {
- // Left-hand-side int. The only thing to do is subtract another int.
- if (left.type() == Value::INTEGER && right.type() == Value::INTEGER) {
- // Int - int -> subtraction.
- return Value(op_node, left.int_value() - right.int_value());
- }
-
- // Left-hand-side list. The only thing to do is subtract another list.
- if (left.type() == Value::LIST && right.type() == Value::LIST) {
- // In-place modify left and return it.
- RemoveMatchesFromList(op_node, &left, right, err);
- return left;
- }
-
- *err = MakeIncompatibleTypeError(op_node, left, right);
- return Value();
-}
-
-// In-place plus/minus ---------------------------------------------------------
-
-void ExecutePlusEquals(Scope* exec_scope,
- const BinaryOpNode* op_node,
- ValueDestination* dest,
- Value right,
- Err* err) {
- // There are several cases. Some things we can convert "foo += bar" to
- // "foo = foo + bar". Some cases we can't (the 'sources' variable won't
- // get the right filtering on the list). Some cases we don't want to (lists
- // and strings will get unnecessary copying so we can to optimize these).
- //
- // - Value is already mutable in the current scope:
- // 1. List/string append: use it.
- // 2. Other types: fall back to "foo = foo + bar"
- //
- // - Value is not mutable in the current scope:
- // 3. List/string append: copy into current scope and append to that.
- // 4. Other types: fall back to "foo = foo + bar"
- //
- // The common case is to use += for list and string appends in the local
- // scope, so this is written to avoid multiple variable lookups in that case.
- Value* mutable_dest = dest->GetExistingMutableValueIfExists(op_node);
- if (!mutable_dest) {
- const Value* existing_value = dest->GetExistingValue();
- if (!existing_value) {
- // Undefined left-hand-size for +=.
- dest->MakeUndefinedIdentifierForModifyError(err);
- return;
- }
-
- if (existing_value->type() != Value::STRING &&
- existing_value->type() != Value::LIST) {
- // Case #4 above.
- dest->SetValue(ExecutePlus(op_node, *existing_value,
- std::move(right), false, err), op_node);
- return;
- }
-
- // Case #3 above, copy to current scope and fall-through to appending.
- mutable_dest = dest->SetValue(*existing_value, op_node);
- } else if (mutable_dest->type() != Value::STRING &&
- mutable_dest->type() != Value::LIST) {
- // Case #2 above.
- dest->SetValue(ExecutePlus(op_node, *mutable_dest,
- std::move(right), false, err), op_node);
- return;
- } // "else" is case #1 above.
-
- if (mutable_dest->type() == Value::STRING) {
- if (right.type() == Value::INTEGER) {
- // String + int -> string concat.
- mutable_dest->string_value().append(
- base::Int64ToString(right.int_value()));
- } else if (right.type() == Value::STRING) {
- // String + string -> string concat.
- mutable_dest->string_value().append(right.string_value());
- } else {
- *err = MakeIncompatibleTypeError(op_node, *mutable_dest, right);
- }
- } else if (mutable_dest->type() == Value::LIST) {
- // List concat.
- if (right.type() == Value::LIST) {
- // Note: don't reserve() the dest vector here since that actually hurts
- // the allocation pattern when the build script is doing multiple small
- // additions.
- const PatternList* filter = dest->GetAssignmentFilter(exec_scope);
- if (filter) {
- // Filtered list concat.
- for (Value& value : right.list_value()) {
- if (!filter->MatchesValue(value))
- mutable_dest->list_value().push_back(std::move(value));
- }
- } else {
- // Normal list concat. This is a destructive move.
- for (Value& value : right.list_value())
- mutable_dest->list_value().push_back(std::move(value));
- }
- } else {
- *err = Err(op_node->op(), "Incompatible types to add.",
- "To append a single item to a list do \"foo += [ bar ]\".");
- }
- }
-}
-
-void ExecuteMinusEquals(const BinaryOpNode* op_node,
- ValueDestination* dest,
- const Value& right,
- Err* err) {
- // Like the += case, we can convert "foo -= bar" to "foo = foo - bar". Since
- // there is no sources filtering, this is always semantically valid. The
- // only case we don't do it is for lists in the current scope which is the
- // most common case, and also the one that can be optimized the most by
- // doing it in-place.
- Value* mutable_dest = dest->GetExistingMutableValueIfExists(op_node);
- if (!mutable_dest ||
- (mutable_dest->type() != Value::LIST || right.type() != Value::LIST)) {
- const Value* existing_value = dest->GetExistingValue();
- if (!existing_value) {
- // Undefined left-hand-size for -=.
- dest->MakeUndefinedIdentifierForModifyError(err);
- return;
- }
- dest->SetValue(ExecuteMinus(op_node, *existing_value, right, err), op_node);
- return;
- }
-
- // In-place removal of items from "right".
- RemoveMatchesFromList(op_node, mutable_dest, right, err);
-}
-
-// Comparison -----------------------------------------------------------------
-
-Value ExecuteEqualsEquals(Scope* scope,
- const BinaryOpNode* op_node,
- const Value& left,
- const Value& right,
- Err* err) {
- if (left == right)
- return Value(op_node, true);
- return Value(op_node, false);
-}
-
-Value ExecuteNotEquals(Scope* scope,
- const BinaryOpNode* op_node,
- const Value& left,
- const Value& right,
- Err* err) {
- // Evaluate in terms of ==.
- Value result = ExecuteEqualsEquals(scope, op_node, left, right, err);
- result.boolean_value() = !result.boolean_value();
- return result;
-}
-
-Value FillNeedsTwoIntegersError(const BinaryOpNode* op_node,
- const Value& left,
- const Value& right,
- Err* err) {
- *err = Err(op_node, "Comparison requires two integers.",
- "This operator can only compare two integers.");
- err->AppendRange(left.origin()->GetRange());
- err->AppendRange(right.origin()->GetRange());
- return Value();
-}
-
-Value ExecuteLessEquals(Scope* scope,
- const BinaryOpNode* op_node,
- const Value& left,
- const Value& right,
- Err* err) {
- if (left.type() != Value::INTEGER || right.type() != Value::INTEGER)
- return FillNeedsTwoIntegersError(op_node, left, right, err);
- return Value(op_node, left.int_value() <= right.int_value());
-}
-
-Value ExecuteGreaterEquals(Scope* scope,
- const BinaryOpNode* op_node,
- const Value& left,
- const Value& right,
- Err* err) {
- if (left.type() != Value::INTEGER || right.type() != Value::INTEGER)
- return FillNeedsTwoIntegersError(op_node, left, right, err);
- return Value(op_node, left.int_value() >= right.int_value());
-}
-
-Value ExecuteGreater(Scope* scope,
- const BinaryOpNode* op_node,
- const Value& left,
- const Value& right,
- Err* err) {
- if (left.type() != Value::INTEGER || right.type() != Value::INTEGER)
- return FillNeedsTwoIntegersError(op_node, left, right, err);
- return Value(op_node, left.int_value() > right.int_value());
-}
-
-Value ExecuteLess(Scope* scope,
- const BinaryOpNode* op_node,
- const Value& left,
- const Value& right,
- Err* err) {
- if (left.type() != Value::INTEGER || right.type() != Value::INTEGER)
- return FillNeedsTwoIntegersError(op_node, left, right, err);
- return Value(op_node, left.int_value() < right.int_value());
-}
-
-// Binary ----------------------------------------------------------------------
-
-Value ExecuteOr(Scope* scope,
- const BinaryOpNode* op_node,
- const ParseNode* left_node,
- const ParseNode* right_node,
- Err* err) {
- Value left = GetValueOrFillError(op_node, left_node, "left", scope, err);
- if (err->has_error())
- return Value();
- if (left.type() != Value::BOOLEAN) {
- *err = Err(op_node->left(), "Left side of || operator is not a boolean.",
- "Type is \"" + std::string(Value::DescribeType(left.type())) +
- "\" instead.");
- return Value();
- }
- if (left.boolean_value())
- return Value(op_node, left.boolean_value());
-
- Value right = GetValueOrFillError(op_node, right_node, "right", scope, err);
- if (err->has_error())
- return Value();
- if (right.type() != Value::BOOLEAN) {
- *err = Err(op_node->right(), "Right side of || operator is not a boolean.",
- "Type is \"" + std::string(Value::DescribeType(right.type())) +
- "\" instead.");
- return Value();
- }
-
- return Value(op_node, left.boolean_value() || right.boolean_value());
-}
-
-Value ExecuteAnd(Scope* scope,
- const BinaryOpNode* op_node,
- const ParseNode* left_node,
- const ParseNode* right_node,
- Err* err) {
- Value left = GetValueOrFillError(op_node, left_node, "left", scope, err);
- if (err->has_error())
- return Value();
- if (left.type() != Value::BOOLEAN) {
- *err = Err(op_node->left(), "Left side of && operator is not a boolean.",
- "Type is \"" + std::string(Value::DescribeType(left.type())) +
- "\" instead.");
- return Value();
- }
- if (!left.boolean_value())
- return Value(op_node, left.boolean_value());
-
- Value right = GetValueOrFillError(op_node, right_node, "right", scope, err);
- if (err->has_error())
- return Value();
- if (right.type() != Value::BOOLEAN) {
- *err = Err(op_node->right(), "Right side of && operator is not a boolean.",
- "Type is \"" + std::string(Value::DescribeType(right.type())) +
- "\" instead.");
- return Value();
- }
- return Value(op_node, left.boolean_value() && right.boolean_value());
-}
-
-} // namespace
-
-// ----------------------------------------------------------------------------
-
-Value ExecuteUnaryOperator(Scope* scope,
- const UnaryOpNode* op_node,
- const Value& expr,
- Err* err) {
- DCHECK(op_node->op().type() == Token::BANG);
-
- if (expr.type() != Value::BOOLEAN) {
- *err = Err(op_node, "Operand of ! operator is not a boolean.",
- "Type is \"" + std::string(Value::DescribeType(expr.type())) +
- "\" instead.");
- return Value();
- }
- // TODO(scottmg): Why no unary minus?
- return Value(op_node, !expr.boolean_value());
-}
-
-Value ExecuteBinaryOperator(Scope* scope,
- const BinaryOpNode* op_node,
- const ParseNode* left,
- const ParseNode* right,
- Err* err) {
- const Token& op = op_node->op();
-
- // First handle the ones that take an lvalue.
- if (op.type() == Token::EQUAL ||
- op.type() == Token::PLUS_EQUALS ||
- op.type() == Token::MINUS_EQUALS) {
- // Compute the left side.
- ValueDestination dest;
- if (!dest.Init(scope, left, op_node, err))
- return Value();
-
- // Compute the right side.
- Value right_value = right->Execute(scope, err);
- if (err->has_error())
- return Value();
- if (right_value.type() == Value::NONE) {
- *err = Err(op, "Operator requires a rvalue.",
- "This thing on the right does not evaluate to a value.");
- err->AppendRange(right->GetRange());
- return Value();
- }
-
- // "foo += bar" (same for "-=") is converted to "foo = foo + bar" here, but
- // we pass the original value of "foo" by pointer to avoid a copy.
- if (op.type() == Token::EQUAL) {
- ExecuteEquals(scope, op_node, &dest, std::move(right_value), err);
- } else if (op.type() == Token::PLUS_EQUALS) {
- ExecutePlusEquals(scope, op_node, &dest, std::move(right_value), err);
- } else if (op.type() == Token::MINUS_EQUALS) {
- ExecuteMinusEquals(op_node, &dest, right_value, err);
- } else {
- NOTREACHED();
- }
- return Value();
- }
-
- // ||, &&. Passed the node instead of the value so that they can avoid
- // evaluating the RHS on early-out.
- if (op.type() == Token::BOOLEAN_OR)
- return ExecuteOr(scope, op_node, left, right, err);
- if (op.type() == Token::BOOLEAN_AND)
- return ExecuteAnd(scope, op_node, left, right, err);
-
- // Everything else works on the evaluated left and right values.
- Value left_value = GetValueOrFillError(op_node, left, "left", scope, err);
- if (err->has_error())
- return Value();
- Value right_value = GetValueOrFillError(op_node, right, "right", scope, err);
- if (err->has_error())
- return Value();
-
- // +, -.
- if (op.type() == Token::MINUS)
- return ExecuteMinus(op_node, std::move(left_value), right_value, err);
- if (op.type() == Token::PLUS) {
- return ExecutePlus(op_node, std::move(left_value), std::move(right_value),
- true, err);
- }
-
- // Comparisons.
- if (op.type() == Token::EQUAL_EQUAL)
- return ExecuteEqualsEquals(scope, op_node, left_value, right_value, err);
- if (op.type() == Token::NOT_EQUAL)
- return ExecuteNotEquals(scope, op_node, left_value, right_value, err);
- if (op.type() == Token::GREATER_EQUAL)
- return ExecuteGreaterEquals(scope, op_node, left_value, right_value, err);
- if (op.type() == Token::LESS_EQUAL)
- return ExecuteLessEquals(scope, op_node, left_value, right_value, err);
- if (op.type() == Token::GREATER_THAN)
- return ExecuteGreater(scope, op_node, left_value, right_value, err);
- if (op.type() == Token::LESS_THAN)
- return ExecuteLess(scope, op_node, left_value, right_value, err);
-
- return Value();
-}
diff --git a/chromium/tools/gn/operators.h b/chromium/tools/gn/operators.h
deleted file mode 100644
index 82ff68e7578..00000000000
--- a/chromium/tools/gn/operators.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_OPERATORS_H_
-#define TOOLS_GN_OPERATORS_H_
-
-class BinaryOpNode;
-class Err;
-class ParseNode;
-class Scope;
-class UnaryOpNode;
-class Value;
-
-Value ExecuteUnaryOperator(Scope* scope,
- const UnaryOpNode* op_node,
- const Value& value,
- Err* err);
-Value ExecuteBinaryOperator(Scope* scope,
- const BinaryOpNode* op_node,
- const ParseNode* left,
- const ParseNode* right,
- Err* err);
-
-#endif // TOOLS_GN_OPERATORS_H_
diff --git a/chromium/tools/gn/operators_unittest.cc b/chromium/tools/gn/operators_unittest.cc
deleted file mode 100644
index 4b8ab37b588..00000000000
--- a/chromium/tools/gn/operators_unittest.cc
+++ /dev/null
@@ -1,390 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/operators.h"
-
-#include <stdint.h>
-
-#include <memory>
-#include <utility>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/pattern.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-bool IsValueIntegerEqualing(const Value& v, int64_t i) {
- if (v.type() != Value::INTEGER)
- return false;
- return v.int_value() == i;
-}
-
-bool IsValueStringEqualing(const Value& v, const char* s) {
- if (v.type() != Value::STRING)
- return false;
- return v.string_value() == s;
-}
-
-// This parse node is for passing to tests. It returns a canned value for
-// Execute().
-class TestParseNode : public ParseNode {
- public:
- TestParseNode(const Value& v) : value_(v) {
- }
-
- Value Execute(Scope* scope, Err* err) const override {
- return value_;
- }
- LocationRange GetRange() const override {
- return LocationRange();
- }
- Err MakeErrorDescribing(const std::string& msg,
- const std::string& help) const override {
- return Err(this, msg);
- }
- void Print(std::ostream& out, int indent) const override {
- }
-
- private:
- Value value_;
-};
-
-// Sets up a BinaryOpNode for testing.
-class TestBinaryOpNode : public BinaryOpNode {
- public:
- // Input token value string must outlive class.
- TestBinaryOpNode(Token::Type op_token_type,
- const char* op_token_value)
- : BinaryOpNode(),
- op_token_ownership_(Location(), op_token_type, op_token_value) {
- set_op(op_token_ownership_);
- }
-
- void SetLeftToValue(const Value& value) {
- set_left(std::make_unique<TestParseNode>(value));
- }
-
- // Sets the left-hand side of the operator to an identifier node, this is
- // used for testing assignments. Input string must outlive class.
- void SetLeftToIdentifier(const char* identifier) {
- left_identifier_token_ownership_ =
- Token(Location(), Token::IDENTIFIER, identifier);
- set_left(
- std::make_unique<IdentifierNode>(left_identifier_token_ownership_));
- }
-
- void SetRightToValue(const Value& value) {
- set_right(std::make_unique<TestParseNode>(value));
- }
- void SetRightToListOfValue(const Value& value) {
- Value list(nullptr, Value::LIST);
- list.list_value().push_back(value);
- set_right(std::make_unique<TestParseNode>(list));
- }
- void SetRightToListOfValue(const Value& value1, const Value& value2) {
- Value list(nullptr, Value::LIST);
- list.list_value().push_back(value1);
- list.list_value().push_back(value2);
- set_right(std::make_unique<TestParseNode>(list));
- }
-
- private:
- // The base class takes the Token by reference, this manages the lifetime.
- Token op_token_ownership_;
-
- // When setting the left to an identifier, this manages the lifetime of
- // the identifier token.
- Token left_identifier_token_ownership_;
-};
-
-} // namespace
-
-TEST(Operators, SourcesAppend) {
- Err err;
- TestWithScope setup;
-
- // Set up "sources" with an empty list.
- const char sources[] = "sources";
- setup.scope()->SetValue(sources, Value(nullptr, Value::LIST), nullptr);
-
- // Set up the operator.
- TestBinaryOpNode node(Token::PLUS_EQUALS, "+=");
- node.SetLeftToIdentifier(sources);
-
- // Set up the filter on the scope to remove everything ending with "rm"
- std::unique_ptr<PatternList> pattern_list = std::make_unique<PatternList>();
- pattern_list->Append(Pattern("*rm"));
- setup.scope()->set_sources_assignment_filter(std::move(pattern_list));
-
- // Append an integer.
- node.SetRightToListOfValue(Value(nullptr, static_cast<int64_t>(5)));
- node.Execute(setup.scope(), &err);
- EXPECT_FALSE(err.has_error());
-
- // Append a string that doesn't match the pattern, it should get appended.
- const char string1[] = "good";
- node.SetRightToListOfValue(Value(nullptr, string1));
- node.Execute(setup.scope(), &err);
- EXPECT_FALSE(err.has_error());
-
- // Append a string that does match the pattern, it should be a no-op.
- const char string2[] = "foo-rm";
- node.SetRightToListOfValue(Value(nullptr, string2));
- node.Execute(setup.scope(), &err);
- EXPECT_FALSE(err.has_error());
-
- // Append a list with the two strings from above.
- node.SetRightToListOfValue(Value(nullptr, string1), Value(nullptr, string2));
- node.Execute(setup.scope(), &err);
- EXPECT_FALSE(err.has_error());
-
- // The sources variable in the scope should now have: [ 5, "good", "good" ]
- const Value* value = setup.scope()->GetValue(sources);
- ASSERT_TRUE(value);
- ASSERT_EQ(Value::LIST, value->type());
- ASSERT_EQ(3u, value->list_value().size());
- EXPECT_TRUE(IsValueIntegerEqualing(value->list_value()[0], 5));
- EXPECT_TRUE(IsValueStringEqualing(value->list_value()[1], "good"));
- EXPECT_TRUE(IsValueStringEqualing(value->list_value()[2], "good"));
-}
-
-// Note that the SourcesAppend test above tests the basic list + list features,
-// this test handles the other cases.
-TEST(Operators, ListAppend) {
- Err err;
- TestWithScope setup;
-
- // Set up "foo" with an empty list.
- const char foo[] = "foo";
- setup.scope()->SetValue(foo, Value(nullptr, Value::LIST), nullptr);
-
- // Set up the operator to append to "foo".
- TestBinaryOpNode node(Token::PLUS_EQUALS, "+=");
- node.SetLeftToIdentifier(foo);
-
- // Append a list with a list, the result should be a nested list.
- Value inner_list(nullptr, Value::LIST);
- inner_list.list_value().push_back(Value(nullptr, static_cast<int64_t>(12)));
- node.SetRightToListOfValue(inner_list);
-
- Value ret = ExecuteBinaryOperator(setup.scope(), &node, node.left(),
- node.right(), &err);
- EXPECT_FALSE(err.has_error());
-
- // Return from the operator should always be "none", it should update the
- // value only.
- EXPECT_EQ(Value::NONE, ret.type());
-
- // The value should be updated with "[ [ 12 ] ]"
- Value result = *setup.scope()->GetValue(foo);
- ASSERT_EQ(Value::LIST, result.type());
- ASSERT_EQ(1u, result.list_value().size());
- ASSERT_EQ(Value::LIST, result.list_value()[0].type());
- ASSERT_EQ(1u, result.list_value()[0].list_value().size());
- ASSERT_EQ(Value::INTEGER, result.list_value()[0].list_value()[0].type());
- ASSERT_EQ(12, result.list_value()[0].list_value()[0].int_value());
-
- // Try to append an integer and a string directly (e.g. foo += "hi").
- // This should fail.
- const char str_str[] = "\"hi\"";
- Token str(Location(), Token::STRING, str_str);
- node.set_right(std::make_unique<LiteralNode>(str));
- ExecuteBinaryOperator(setup.scope(), &node, node.left(), node.right(), &err);
- EXPECT_TRUE(err.has_error());
- err = Err();
-
- node.SetRightToValue(Value(nullptr, static_cast<int64_t>(12)));
- ExecuteBinaryOperator(setup.scope(), &node, node.left(), node.right(), &err);
- EXPECT_TRUE(err.has_error());
-}
-
-TEST(Operators, ListRemove) {
- Err err;
- TestWithScope setup;
-
- const char foo_str[] = "foo";
- const char bar_str[] = "bar";
- Value test_list(nullptr, Value::LIST);
- test_list.list_value().push_back(Value(nullptr, foo_str));
- test_list.list_value().push_back(Value(nullptr, bar_str));
- test_list.list_value().push_back(Value(nullptr, foo_str));
-
- // Set up "var" with an the test list.
- const char var[] = "var";
- setup.scope()->SetValue(var, test_list, nullptr);
-
- TestBinaryOpNode node(Token::MINUS_EQUALS, "-=");
- node.SetLeftToIdentifier(var);
-
- // Subtract a list consisting of "foo".
- node.SetRightToListOfValue(Value(nullptr, foo_str));
- Value result = ExecuteBinaryOperator(
- setup.scope(), &node, node.left(), node.right(), &err);
- EXPECT_FALSE(err.has_error());
-
- // -= returns an empty value to reduce the possibility of writing confusing
- // cases like foo = bar += 1.
- EXPECT_EQ(Value::NONE, result.type());
-
- // The "var" variable should have been updated. Both instances of "foo" are
- // deleted.
- const Value* new_value = setup.scope()->GetValue(var);
- ASSERT_TRUE(new_value);
- ASSERT_EQ(Value::LIST, new_value->type());
- ASSERT_EQ(1u, new_value->list_value().size());
- ASSERT_EQ(Value::STRING, new_value->list_value()[0].type());
- EXPECT_EQ("bar", new_value->list_value()[0].string_value());
-}
-
-TEST(Operators, IntegerAdd) {
- Err err;
- TestWithScope setup;
-
- TestBinaryOpNode node(Token::PLUS, "+");
- node.SetLeftToValue(Value(nullptr, static_cast<int64_t>(123)));
- node.SetRightToValue(Value(nullptr, static_cast<int64_t>(456)));
- Value ret = ExecuteBinaryOperator(setup.scope(), &node, node.left(),
- node.right(), &err);
- ASSERT_FALSE(err.has_error());
- ASSERT_EQ(Value::INTEGER, ret.type());
- EXPECT_EQ(579, ret.int_value());
-}
-
-TEST(Operators, IntegerSubtract) {
- Err err;
- TestWithScope setup;
-
- TestBinaryOpNode node(Token::MINUS, "-");
- node.SetLeftToValue(Value(nullptr, static_cast<int64_t>(123)));
- node.SetRightToValue(Value(nullptr, static_cast<int64_t>(456)));
- Value ret = ExecuteBinaryOperator(setup.scope(), &node, node.left(),
- node.right(), &err);
- ASSERT_FALSE(err.has_error());
- ASSERT_EQ(Value::INTEGER, ret.type());
- EXPECT_EQ(-333, ret.int_value());
-}
-
-TEST(Operators, ShortCircuitAnd) {
- Err err;
- TestWithScope setup;
-
- // Set a && operator with the left to false.
- TestBinaryOpNode node(Token::BOOLEAN_AND, "&&");
- node.SetLeftToValue(Value(nullptr, false));
-
- // Set right as foo, but don't define a value for it.
- const char foo[] = "foo";
- Token identifier_token(Location(), Token::IDENTIFIER, foo);
- node.set_right(std::make_unique<IdentifierNode>(identifier_token));
-
- Value ret = ExecuteBinaryOperator(setup.scope(), &node, node.left(),
- node.right(), &err);
- EXPECT_FALSE(err.has_error());
-}
-
-TEST(Operators, ShortCircuitOr) {
- Err err;
- TestWithScope setup;
-
- // Set a || operator with the left to true.
- TestBinaryOpNode node(Token::BOOLEAN_OR, "||");
- node.SetLeftToValue(Value(nullptr, true));
-
- // Set right as foo, but don't define a value for it.
- const char foo[] = "foo";
- Token identifier_token(Location(), Token::IDENTIFIER, foo);
- node.set_right(std::make_unique<IdentifierNode>(identifier_token));
-
- Value ret = ExecuteBinaryOperator(setup.scope(), &node, node.left(),
- node.right(), &err);
- EXPECT_FALSE(err.has_error());
-}
-
-// Overwriting nonempty lists and scopes with other nonempty lists and scopes
-// should be disallowed.
-TEST(Operators, NonemptyOverwriting) {
- Err err;
- TestWithScope setup;
-
- // Set up "foo" with a nonempty list.
- const char foo[] = "foo";
- Value old_value(nullptr, Value::LIST);
- old_value.list_value().push_back(Value(nullptr, "string"));
- setup.scope()->SetValue(foo, old_value, nullptr);
-
- TestBinaryOpNode node(Token::EQUAL, "=");
- node.SetLeftToIdentifier(foo);
-
- // Assigning a nonempty list should fail.
- node.SetRightToListOfValue(Value(nullptr, "string"));
- node.Execute(setup.scope(), &err);
- ASSERT_TRUE(err.has_error());
- EXPECT_EQ("Replacing nonempty list.", err.message());
- err = Err();
-
- // Assigning an empty list should succeed.
- node.SetRightToValue(Value(nullptr, Value::LIST));
- node.Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error());
- const Value* new_value = setup.scope()->GetValue(foo);
- ASSERT_TRUE(new_value);
- ASSERT_EQ(Value::LIST, new_value->type());
- ASSERT_TRUE(new_value->list_value().empty());
-
- // Set up "foo" with a nonempty scope.
- const char bar[] = "bar";
- old_value = Value(nullptr, std::make_unique<Scope>(setup.settings()));
- old_value.scope_value()->SetValue(bar, Value(nullptr, "bar"), nullptr);
- setup.scope()->SetValue(foo, old_value, nullptr);
-
- // Assigning a nonempty scope should fail (re-use old_value copy).
- node.SetRightToValue(old_value);
- node.Execute(setup.scope(), &err);
- ASSERT_TRUE(err.has_error());
- EXPECT_EQ("Replacing nonempty scope.", err.message());
- err = Err();
-
- // Assigning an empty list should succeed.
- node.SetRightToValue(
- Value(nullptr, std::make_unique<Scope>(setup.settings())));
- node.Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error());
- new_value = setup.scope()->GetValue(foo);
- ASSERT_TRUE(new_value);
- ASSERT_EQ(Value::SCOPE, new_value->type());
- ASSERT_FALSE(new_value->scope_value()->HasValues(Scope::SEARCH_CURRENT));
-}
-
-// Tests this case:
-// foo = 1
-// target(...) {
-// foo += 1
-//
-// This should mark the outer "foo" as used, and the inner "foo" as unused.
-TEST(Operators, PlusEqualsUsed) {
- Err err;
- TestWithScope setup;
-
- // Outer "foo" definition, it should be unused.
- const char foo[] = "foo";
- Value old_value(nullptr, static_cast<int64_t>(1));
- setup.scope()->SetValue(foo, old_value, nullptr);
- EXPECT_TRUE(setup.scope()->IsSetButUnused(foo));
-
- // Nested scope.
- Scope nested(setup.scope());
-
- // Run "foo += 1".
- TestBinaryOpNode node(Token::PLUS_EQUALS, "+=");
- node.SetLeftToIdentifier(foo);
- node.SetRightToValue(Value(nullptr, static_cast<int64_t>(1)));
- node.Execute(&nested, &err);
- ASSERT_FALSE(err.has_error());
-
- // Outer foo should be used, inner foo should not be.
- EXPECT_FALSE(setup.scope()->IsSetButUnused(foo));
- EXPECT_TRUE(nested.IsSetButUnused(foo));
-}
diff --git a/chromium/tools/gn/ordered_set.h b/chromium/tools/gn/ordered_set.h
deleted file mode 100644
index c67439b74de..00000000000
--- a/chromium/tools/gn/ordered_set.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_ORDERED_SET_H_
-#define TOOLS_GN_ORDERED_SET_H_
-
-#include <stddef.h>
-
-#include <set>
-
-// An ordered set of items. Only appending is supported. Iteration is designed
-// to be by index.
-template<typename T>
-class OrderedSet {
- private:
- typedef std::set<T> set_type;
- typedef typename set_type::const_iterator set_iterator;
- typedef std::vector<set_iterator> vector_type;
-
- public:
- static const size_t npos = static_cast<size_t>(-1);
-
- OrderedSet() {}
- ~OrderedSet() {}
-
- const T& operator[](size_t index) const {
- return *ordering_[index];
- }
- size_t size() const {
- return ordering_.size();
- }
- bool empty() const {
- return ordering_.empty();
- }
-
- bool has_item(const T& t) const {
- return set_.find(t) != set_.end();
- }
-
- // Returns true if the item was inserted. False if it was already in the
- // set.
- bool push_back(const T& t) {
- std::pair<set_iterator, bool> result = set_.insert(t);
- if (result.second)
- ordering_.push_back(result.first);
- return true;
- }
-
- // Appends a range of items, skipping ones that already exist.
- template<class InputIterator>
- void append(const InputIterator& insert_begin,
- const InputIterator& insert_end) {
- for (InputIterator i = insert_begin; i != insert_end; ++i) {
- const T& t = *i;
- push_back(t);
- }
- }
-
- // Appends all items from the given other set.
- void append(const OrderedSet<T>& other) {
- for (size_t i = 0; i < other.size(); i++)
- push_back(other[i]);
- }
-
- private:
- set_type set_;
- vector_type ordering_;
-};
-
-#endif // TOOLS_GN_ORDERED_SET_H_
diff --git a/chromium/tools/gn/output_file.cc b/chromium/tools/gn/output_file.cc
deleted file mode 100644
index a70bae96ce3..00000000000
--- a/chromium/tools/gn/output_file.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/output_file.h"
-
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/source_file.h"
-
-OutputFile::OutputFile() : value_() {
-}
-
-OutputFile::OutputFile(std::string&& v)
- : value_(v) {
-}
-
-OutputFile::OutputFile(const std::string& v)
- : value_(v) {
-}
-
-OutputFile::OutputFile(const BuildSettings* build_settings,
- const SourceFile& source_file)
- : value_(RebasePath(source_file.value(),
- build_settings->build_dir(),
- build_settings->root_path_utf8())) {
-}
-
-OutputFile::~OutputFile() = default;
-
-SourceFile OutputFile::AsSourceFile(const BuildSettings* build_settings) const {
- DCHECK(!value_.empty());
- DCHECK(value_[value_.size() - 1] != '/');
-
- std::string path = build_settings->build_dir().value();
- path.append(value_);
- NormalizePath(&path);
- return SourceFile(path);
-}
-
-SourceDir OutputFile::AsSourceDir(const BuildSettings* build_settings) const {
- if (!value_.empty()) {
- // Empty means the root build dir. Otherwise, we expect it to end in a
- // slash.
- DCHECK(value_[value_.size() - 1] == '/');
- }
- std::string path = build_settings->build_dir().value();
- path.append(value_);
- NormalizePath(&path);
- return SourceDir(path);
-}
diff --git a/chromium/tools/gn/output_file.h b/chromium/tools/gn/output_file.h
deleted file mode 100644
index a7882fd34f8..00000000000
--- a/chromium/tools/gn/output_file.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_OUTPUT_FILE_H_
-#define TOOLS_GN_OUTPUT_FILE_H_
-
-#include <stddef.h>
-
-#include <string>
-
-#include "base/containers/hash_tables.h"
-#include "tools/gn/build_settings.h"
-
-class SourceFile;
-
-// A simple wrapper around a string that indicates the string is a path
-// relative to the output directory.
-class OutputFile {
- public:
- OutputFile();
- explicit OutputFile(std::string&& v);
- explicit OutputFile(const std::string& v);
- OutputFile(const BuildSettings* build_settings,
- const SourceFile& source_file);
- ~OutputFile();
-
- std::string& value() { return value_; }
- const std::string& value() const { return value_; }
-
- // Converts to a SourceFile by prepending the build directory to the file.
- // The *Dir version requires that the current OutputFile ends in a slash, and
- // the *File version is the opposite.
- SourceFile AsSourceFile(const BuildSettings* build_settings) const;
- SourceDir AsSourceDir(const BuildSettings* build_settings) const;
-
- bool operator==(const OutputFile& other) const {
- return value_ == other.value_;
- }
- bool operator!=(const OutputFile& other) const {
- return value_ != other.value_;
- }
- bool operator<(const OutputFile& other) const {
- return value_ < other.value_;
- }
-
- private:
- std::string value_;
-};
-
-namespace BASE_HASH_NAMESPACE {
-
-template<> struct hash<OutputFile> {
- std::size_t operator()(const OutputFile& v) const {
- hash<std::string> h;
- return h(v.value());
- }
-};
-
-} // namespace BASE_HASH_NAMESPACE
-
-inline void swap(OutputFile& lhs, OutputFile& rhs) {
- lhs.value().swap(rhs.value());
-}
-
-#endif // TOOLS_GN_OUTPUT_FILE_H_
diff --git a/chromium/tools/gn/parse_node_value_adapter.cc b/chromium/tools/gn/parse_node_value_adapter.cc
deleted file mode 100644
index 70c78e5b794..00000000000
--- a/chromium/tools/gn/parse_node_value_adapter.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/parse_node_value_adapter.h"
-
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-
-ParseNodeValueAdapter::ParseNodeValueAdapter() : ref_(nullptr) {
-}
-
-ParseNodeValueAdapter::~ParseNodeValueAdapter() = default;
-
-bool ParseNodeValueAdapter::Init(Scope* scope,
- const ParseNode* node,
- Err* err) {
- const IdentifierNode* identifier = node->AsIdentifier();
- if (identifier) {
- ref_ = scope->GetValue(identifier->value().value(), true);
- if (!ref_) {
- identifier->MakeErrorDescribing("Undefined identifier");
- return false;
- }
- return true;
- }
-
- temporary_ = node->Execute(scope, err);
- return !err->has_error();
-}
-
-bool ParseNodeValueAdapter::InitForType(Scope* scope,
- const ParseNode* node,
- Value::Type type,
- Err* err) {
- if (!Init(scope, node, err))
- return false;
- if (get().VerifyTypeIs(type, err))
- return true;
-
- // Fix up the error range (see class comment in the header file) to be the
- // identifier node rather than the original value.
- *err = Err(node, err->message(), err->help_text());
- return false;
-}
diff --git a/chromium/tools/gn/parse_node_value_adapter.h b/chromium/tools/gn/parse_node_value_adapter.h
deleted file mode 100644
index db34e24b12d..00000000000
--- a/chromium/tools/gn/parse_node_value_adapter.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_PARSE_NODE_VALUE_ADAPTER_H_
-#define TOOLS_GN_PARSE_NODE_VALUE_ADAPTER_H_
-
-#include "base/macros.h"
-#include "tools/gn/value.h"
-
-class ParseNode;
-
-// Provides a means to convert a parse node to a value without causing a copy
-// in the common case of an "Identifier" node. Normally to get a value from a
-// parse node you have to call Execute(), and when an identifier is executed
-// it just returns the current value of itself as a copy. But some variables
-// are very large (lists of many strings for example).
-//
-// The reason you might not want to do this is that in the case of an
-// identifier where the copy is optimized away, the origin will still be the
-// original value. The result can be confusing because it will reference the
-// original value rather than the place where the value was dereferenced, e.g.
-// for a function call. The InitForType() function will verify type information
-// and will fix up the origin so it's not confusing.
-class ParseNodeValueAdapter {
- public:
- ParseNodeValueAdapter();
- ~ParseNodeValueAdapter();
-
- const Value& get() {
- if (ref_)
- return *ref_;
- return temporary_;
- }
-
- // Initializes the adapter for the result of the given expression. Returns
- // truen on success.
- bool Init(Scope* scope, const ParseNode* node, Err* err);
-
- // Like Init() but additionally verifies that the type of the result matches.
- bool InitForType(Scope* scope,
- const ParseNode* node,
- Value::Type type,
- Err* err);
-
- private:
- // Holds either a reference to an existing item, or a temporary as a copy.
- // If ref is non-null, it's valid, otherwise the temporary is used.
- const Value* ref_;
- Value temporary_;
-
- DISALLOW_COPY_AND_ASSIGN(ParseNodeValueAdapter);
-};
-
-#endif // TOOLS_GN_PARSE_NODE_VALUE_ADAPTER_H_
diff --git a/chromium/tools/gn/parse_tree.cc b/chromium/tools/gn/parse_tree.cc
deleted file mode 100644
index df95bf56ab2..00000000000
--- a/chromium/tools/gn/parse_tree.cc
+++ /dev/null
@@ -1,859 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/parse_tree.h"
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <tuple>
-
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/operators.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/string_utils.h"
-
-namespace {
-
-enum DepsCategory {
- DEPS_CATEGORY_LOCAL,
- DEPS_CATEGORY_RELATIVE,
- DEPS_CATEGORY_ABSOLUTE,
- DEPS_CATEGORY_OTHER,
-};
-
-DepsCategory GetDepsCategory(base::StringPiece deps) {
- if (deps.length() < 2 || deps[0] != '"' || deps[deps.size() - 1] != '"')
- return DEPS_CATEGORY_OTHER;
-
- if (deps[1] == ':')
- return DEPS_CATEGORY_LOCAL;
-
- if (deps[1] == '/')
- return DEPS_CATEGORY_ABSOLUTE;
-
- return DEPS_CATEGORY_RELATIVE;
-}
-
-std::tuple<base::StringPiece, base::StringPiece> SplitAtFirst(
- base::StringPiece str,
- char c) {
- if (!str.starts_with("\"") || !str.ends_with("\""))
- return std::make_tuple(str, base::StringPiece());
-
- str = str.substr(1, str.length() - 2);
- size_t index_of_first = str.find(c);
- return std::make_tuple(str.substr(0, index_of_first),
- index_of_first != base::StringPiece::npos
- ? str.substr(index_of_first + 1)
- : base::StringPiece());
-}
-
-std::string IndentFor(int value) {
- return std::string(value, ' ');
-}
-
-bool IsSortRangeSeparator(const ParseNode* node, const ParseNode* prev) {
- // If it's a block comment, or has an attached comment with a blank line
- // before it, then we break the range at this point.
- return node->AsBlockComment() != nullptr ||
- (prev && node->comments() && !node->comments()->before().empty() &&
- (node->GetRange().begin().line_number() >
- prev->GetRange().end().line_number() +
- static_cast<int>(node->comments()->before().size() + 1)));
-}
-
-base::StringPiece GetStringRepresentation(const ParseNode* node) {
- DCHECK(node->AsLiteral() || node->AsIdentifier() || node->AsAccessor());
- if (node->AsLiteral())
- return node->AsLiteral()->value().value();
- else if (node->AsIdentifier())
- return node->AsIdentifier()->value().value();
- else if (node->AsAccessor())
- return node->AsAccessor()->base().value();
- return base::StringPiece();
-}
-
-} // namespace
-
-Comments::Comments() = default;
-
-Comments::~Comments() = default;
-
-void Comments::ReverseSuffix() {
- for (int i = 0, j = static_cast<int>(suffix_.size() - 1); i < j; ++i, --j)
- std::swap(suffix_[i], suffix_[j]);
-}
-
-ParseNode::ParseNode() = default;
-
-ParseNode::~ParseNode() = default;
-
-const AccessorNode* ParseNode::AsAccessor() const { return nullptr; }
-const BinaryOpNode* ParseNode::AsBinaryOp() const { return nullptr; }
-const BlockCommentNode* ParseNode::AsBlockComment() const { return nullptr; }
-const BlockNode* ParseNode::AsBlock() const { return nullptr; }
-const ConditionNode* ParseNode::AsConditionNode() const { return nullptr; }
-const EndNode* ParseNode::AsEnd() const { return nullptr; }
-const FunctionCallNode* ParseNode::AsFunctionCall() const { return nullptr; }
-const IdentifierNode* ParseNode::AsIdentifier() const { return nullptr; }
-const ListNode* ParseNode::AsList() const { return nullptr; }
-const LiteralNode* ParseNode::AsLiteral() const { return nullptr; }
-const UnaryOpNode* ParseNode::AsUnaryOp() const { return nullptr; }
-
-Comments* ParseNode::comments_mutable() {
- if (!comments_)
- comments_ = std::make_unique<Comments>();
- return comments_.get();
-}
-
-void ParseNode::PrintComments(std::ostream& out, int indent) const {
- if (comments_) {
- std::string ind = IndentFor(indent + 1);
- for (const auto& token : comments_->before())
- out << ind << "+BEFORE_COMMENT(\"" << token.value() << "\")\n";
- for (const auto& token : comments_->suffix())
- out << ind << "+SUFFIX_COMMENT(\"" << token.value() << "\")\n";
- for (const auto& token : comments_->after())
- out << ind << "+AFTER_COMMENT(\"" << token.value() << "\")\n";
- }
-}
-
-// AccessorNode ---------------------------------------------------------------
-
-AccessorNode::AccessorNode() = default;
-
-AccessorNode::~AccessorNode() = default;
-
-const AccessorNode* AccessorNode::AsAccessor() const {
- return this;
-}
-
-Value AccessorNode::Execute(Scope* scope, Err* err) const {
- if (index_)
- return ExecuteArrayAccess(scope, err);
- else if (member_)
- return ExecuteScopeAccess(scope, err);
- NOTREACHED();
- return Value();
-}
-
-LocationRange AccessorNode::GetRange() const {
- if (index_)
- return LocationRange(base_.location(), index_->GetRange().end());
- else if (member_)
- return LocationRange(base_.location(), member_->GetRange().end());
- NOTREACHED();
- return LocationRange();
-}
-
-Err AccessorNode::MakeErrorDescribing(const std::string& msg,
- const std::string& help) const {
- return Err(GetRange(), msg, help);
-}
-
-void AccessorNode::Print(std::ostream& out, int indent) const {
- out << IndentFor(indent) << "ACCESSOR\n";
- PrintComments(out, indent);
- out << IndentFor(indent + 1) << base_.value() << "\n";
- if (index_)
- index_->Print(out, indent + 1);
- else if (member_)
- member_->Print(out, indent + 1);
-}
-
-Value AccessorNode::ExecuteArrayAccess(Scope* scope, Err* err) const {
- const Value* base_value = scope->GetValue(base_.value(), true);
- if (!base_value) {
- *err = MakeErrorDescribing("Undefined identifier.");
- return Value();
- }
- if (!base_value->VerifyTypeIs(Value::LIST, err))
- return Value();
-
- size_t index = 0;
- if (!ComputeAndValidateListIndex(scope, base_value->list_value().size(),
- &index, err))
- return Value();
- return base_value->list_value()[index];
-}
-
-Value AccessorNode::ExecuteScopeAccess(Scope* scope, Err* err) const {
- // We jump through some hoops here since ideally a.b will count "b" as
- // accessed in the given scope. The value "a" might be in some normal nested
- // scope and we can modify it, but it might also be inherited from the
- // readonly root scope and we can't do used variable tracking on it. (It's
- // not legal to const cast it away since the root scope will be in readonly
- // mode and being accessed from multiple threads without locking.) So this
- // code handles both cases.
- const Value* result = nullptr;
-
- // Look up the value in the scope named by "base_".
- Value* mutable_base_value = scope->GetMutableValue(
- base_.value(), Scope::SEARCH_NESTED, true);
- if (mutable_base_value) {
- // Common case: base value is mutable so we can track variable accesses
- // for unused value warnings.
- if (!mutable_base_value->VerifyTypeIs(Value::SCOPE, err))
- return Value();
- result = mutable_base_value->scope_value()->GetValue(
- member_->value().value(), true);
- } else {
- // Fall back to see if the value is on a read-only scope.
- const Value* const_base_value = scope->GetValue(base_.value(), true);
- if (const_base_value) {
- // Read only value, don't try to mark the value access as a "used" one.
- if (!const_base_value->VerifyTypeIs(Value::SCOPE, err))
- return Value();
- result =
- const_base_value->scope_value()->GetValue(member_->value().value());
- } else {
- *err = Err(base_, "Undefined identifier.");
- return Value();
- }
- }
-
- if (!result) {
- *err = Err(member_.get(), "No value named \"" +
- member_->value().value() + "\" in scope \"" + base_.value() + "\"");
- return Value();
- }
- return *result;
-}
-
-void AccessorNode::SetNewLocation(int line_number) {
- Location old = base_.location();
- base_.set_location(
- Location(old.file(), line_number, old.column_number(), old.byte()));
-}
-
-bool AccessorNode::ComputeAndValidateListIndex(Scope* scope,
- size_t max_len,
- size_t* computed_index,
- Err* err) const {
- Value index_value = index_->Execute(scope, err);
- if (err->has_error())
- return false;
- if (!index_value.VerifyTypeIs(Value::INTEGER, err))
- return false;
-
- int64_t index_int = index_value.int_value();
- if (index_int < 0) {
- *err = Err(index_->GetRange(), "Negative array subscript.",
- "You gave me " + base::Int64ToString(index_int) + ".");
- return false;
- }
- size_t index_sizet = static_cast<size_t>(index_int);
- if (index_sizet >= max_len) {
- *err = Err(index_->GetRange(), "Array subscript out of range.",
- "You gave me " + base::Int64ToString(index_int) +
- " but I was expecting something from 0 to " +
- base::NumberToString(max_len) + ", inclusive.");
- return false;
- }
-
- *computed_index = index_sizet;
- return true;
-}
-
-// BinaryOpNode ---------------------------------------------------------------
-
-BinaryOpNode::BinaryOpNode() = default;
-
-BinaryOpNode::~BinaryOpNode() = default;
-
-const BinaryOpNode* BinaryOpNode::AsBinaryOp() const {
- return this;
-}
-
-Value BinaryOpNode::Execute(Scope* scope, Err* err) const {
- return ExecuteBinaryOperator(scope, this, left_.get(), right_.get(), err);
-}
-
-LocationRange BinaryOpNode::GetRange() const {
- return left_->GetRange().Union(right_->GetRange());
-}
-
-Err BinaryOpNode::MakeErrorDescribing(const std::string& msg,
- const std::string& help) const {
- return Err(op_, msg, help);
-}
-
-void BinaryOpNode::Print(std::ostream& out, int indent) const {
- out << IndentFor(indent) << "BINARY(" << op_.value() << ")\n";
- PrintComments(out, indent);
- left_->Print(out, indent + 1);
- right_->Print(out, indent + 1);
-}
-
-// BlockNode ------------------------------------------------------------------
-
-BlockNode::BlockNode(ResultMode result_mode) : result_mode_(result_mode) {
-}
-
-BlockNode::~BlockNode() = default;
-
-const BlockNode* BlockNode::AsBlock() const {
- return this;
-}
-
-Value BlockNode::Execute(Scope* enclosing_scope, Err* err) const {
- std::unique_ptr<Scope> nested_scope; // May be null.
-
- Scope* execution_scope; // Either the enclosing_scope or nested_scope.
- if (result_mode_ == RETURNS_SCOPE) {
- // Create a nested scope to save the values for returning.
- nested_scope = std::make_unique<Scope>(enclosing_scope);
- execution_scope = nested_scope.get();
- } else {
- // Use the enclosing scope. Modifications will go into this also (for
- // example, if conditions and loops).
- execution_scope = enclosing_scope;
- }
-
- for (size_t i = 0; i < statements_.size() && !err->has_error(); i++) {
- // Check for trying to execute things with no side effects in a block.
- //
- // A BlockNode here means that somebody has a free-floating { }.
- // Technically this can have side effects since it could generated targets,
- // but we don't want to allow this since it creates ambiguity when
- // immediately following a function call that takes no block. By not
- // allowing free-floating blocks that aren't passed anywhere or assigned to
- // anything, this ambiguity is resolved.
- const ParseNode* cur = statements_[i].get();
- if (cur->AsList() || cur->AsLiteral() || cur->AsUnaryOp() ||
- cur->AsIdentifier() || cur->AsBlock()) {
- *err = cur->MakeErrorDescribing(
- "This statement has no effect.",
- "Either delete it or do something with the result.");
- return Value();
- }
- cur->Execute(execution_scope, err);
- }
-
- if (result_mode_ == RETURNS_SCOPE) {
- // Clear the reference to the containing scope. This will be passed in
- // a value whose lifetime will not be related to the enclosing_scope passed
- // to this function.
- nested_scope->DetachFromContaining();
- return Value(this, std::move(nested_scope));
- }
- return Value();
-}
-
-LocationRange BlockNode::GetRange() const {
- if (begin_token_.type() != Token::INVALID &&
- end_->value().type() != Token::INVALID) {
- return begin_token_.range().Union(end_->value().range());
- } else if (!statements_.empty()) {
- return statements_[0]->GetRange().Union(
- statements_[statements_.size() - 1]->GetRange());
- }
- return LocationRange();
-}
-
-Err BlockNode::MakeErrorDescribing(const std::string& msg,
- const std::string& help) const {
- return Err(GetRange(), msg, help);
-}
-
-void BlockNode::Print(std::ostream& out, int indent) const {
- out << IndentFor(indent) << "BLOCK\n";
- PrintComments(out, indent);
- for (const auto& statement : statements_)
- statement->Print(out, indent + 1);
- if (end_ && end_->comments())
- end_->Print(out, indent + 1);
-}
-
-// ConditionNode --------------------------------------------------------------
-
-ConditionNode::ConditionNode() = default;
-
-ConditionNode::~ConditionNode() = default;
-
-const ConditionNode* ConditionNode::AsConditionNode() const {
- return this;
-}
-
-Value ConditionNode::Execute(Scope* scope, Err* err) const {
- Value condition_result = condition_->Execute(scope, err);
- if (err->has_error())
- return Value();
- if (condition_result.type() != Value::BOOLEAN) {
- *err = condition_->MakeErrorDescribing(
- "Condition does not evaluate to a boolean value.",
- std::string("This is a value of type \"") +
- Value::DescribeType(condition_result.type()) +
- "\" instead.");
- err->AppendRange(if_token_.range());
- return Value();
- }
-
- if (condition_result.boolean_value()) {
- if_true_->Execute(scope, err);
- } else if (if_false_) {
- // The else block is optional.
- if_false_->Execute(scope, err);
- }
-
- return Value();
-}
-
-LocationRange ConditionNode::GetRange() const {
- if (if_false_)
- return if_token_.range().Union(if_false_->GetRange());
- return if_token_.range().Union(if_true_->GetRange());
-}
-
-Err ConditionNode::MakeErrorDescribing(const std::string& msg,
- const std::string& help) const {
- return Err(if_token_, msg, help);
-}
-
-void ConditionNode::Print(std::ostream& out, int indent) const {
- out << IndentFor(indent) << "CONDITION\n";
- PrintComments(out, indent);
- condition_->Print(out, indent + 1);
- if_true_->Print(out, indent + 1);
- if (if_false_)
- if_false_->Print(out, indent + 1);
-}
-
-// FunctionCallNode -----------------------------------------------------------
-
-FunctionCallNode::FunctionCallNode() = default;
-
-FunctionCallNode::~FunctionCallNode() = default;
-
-const FunctionCallNode* FunctionCallNode::AsFunctionCall() const {
- return this;
-}
-
-Value FunctionCallNode::Execute(Scope* scope, Err* err) const {
- return functions::RunFunction(scope, this, args_.get(), block_.get(), err);
-}
-
-LocationRange FunctionCallNode::GetRange() const {
- if (function_.type() == Token::INVALID)
- return LocationRange(); // This will be null in some tests.
- if (block_)
- return function_.range().Union(block_->GetRange());
- return function_.range().Union(args_->GetRange());
-}
-
-Err FunctionCallNode::MakeErrorDescribing(const std::string& msg,
- const std::string& help) const {
- return Err(function_, msg, help);
-}
-
-void FunctionCallNode::Print(std::ostream& out, int indent) const {
- out << IndentFor(indent) << "FUNCTION(" << function_.value() << ")\n";
- PrintComments(out, indent);
- args_->Print(out, indent + 1);
- if (block_)
- block_->Print(out, indent + 1);
-}
-
-// IdentifierNode --------------------------------------------------------------
-
-IdentifierNode::IdentifierNode() = default;
-
-IdentifierNode::IdentifierNode(const Token& token) : value_(token) {
-}
-
-IdentifierNode::~IdentifierNode() = default;
-
-const IdentifierNode* IdentifierNode::AsIdentifier() const {
- return this;
-}
-
-Value IdentifierNode::Execute(Scope* scope, Err* err) const {
- const Scope* found_in_scope = nullptr;
- const Value* value = scope->GetValueWithScope(value_.value(), true,
- &found_in_scope);
- Value result;
- if (!value) {
- *err = MakeErrorDescribing("Undefined identifier");
- return result;
- }
-
- if (!EnsureNotReadingFromSameDeclareArgs(this, scope, found_in_scope, err))
- return result;
-
- result = *value;
- result.set_origin(this);
- return result;
-}
-
-LocationRange IdentifierNode::GetRange() const {
- return value_.range();
-}
-
-Err IdentifierNode::MakeErrorDescribing(const std::string& msg,
- const std::string& help) const {
- return Err(value_, msg, help);
-}
-
-void IdentifierNode::Print(std::ostream& out, int indent) const {
- out << IndentFor(indent) << "IDENTIFIER(" << value_.value() << ")\n";
- PrintComments(out, indent);
-}
-
-void IdentifierNode::SetNewLocation(int line_number) {
- Location old = value_.location();
- value_.set_location(
- Location(old.file(), line_number, old.column_number(), old.byte()));
-}
-
-// ListNode -------------------------------------------------------------------
-
-ListNode::ListNode() : prefer_multiline_(false) {
-}
-
-ListNode::~ListNode() = default;
-
-const ListNode* ListNode::AsList() const {
- return this;
-}
-
-Value ListNode::Execute(Scope* scope, Err* err) const {
- Value result_value(this, Value::LIST);
- std::vector<Value>& results = result_value.list_value();
- results.reserve(contents_.size());
-
- for (const auto& cur : contents_) {
- if (cur->AsBlockComment())
- continue;
- results.push_back(cur->Execute(scope, err));
- if (err->has_error())
- return Value();
- if (results.back().type() == Value::NONE) {
- *err = cur->MakeErrorDescribing(
- "This does not evaluate to a value.",
- "I can't do something with nothing.");
- return Value();
- }
- }
- return result_value;
-}
-
-LocationRange ListNode::GetRange() const {
- return LocationRange(begin_token_.location(),
- end_->value().location());
-}
-
-Err ListNode::MakeErrorDescribing(const std::string& msg,
- const std::string& help) const {
- return Err(begin_token_, msg, help);
-}
-
-void ListNode::Print(std::ostream& out, int indent) const {
- out << IndentFor(indent) << "LIST" << (prefer_multiline_ ? " multiline" : "")
- << "\n";
- PrintComments(out, indent);
- for (const auto& cur : contents_)
- cur->Print(out, indent + 1);
- if (end_ && end_->comments())
- end_->Print(out, indent + 1);
-}
-
-template <typename Comparator>
-void ListNode::SortList(Comparator comparator) {
- // Partitions first on BlockCommentNodes and sorts each partition separately.
- for (auto sr : GetSortRanges()) {
- bool skip = false;
- for (size_t i = sr.begin; i != sr.end; ++i) {
- // Bails out if any of the nodes are unsupported.
- const ParseNode* node = contents_[i].get();
- if (!node->AsLiteral() && !node->AsIdentifier() && !node->AsAccessor()) {
- skip = true;
- continue;
- }
- }
- if (skip)
- continue;
- // Save the original line number so that we can re-assign ranges. We assume
- // they're contiguous lines because GetSortRanges() does so above. We need
- // to re-assign these line numbers primiarily because `gn format` uses them
- // to determine whether two nodes were initially separated by a blank line
- // or not.
- int start_line = contents_[sr.begin]->GetRange().begin().line_number();
- const ParseNode* original_first = contents_[sr.begin].get();
- std::sort(contents_.begin() + sr.begin, contents_.begin() + sr.end,
- [&comparator](const std::unique_ptr<const ParseNode>& a,
- const std::unique_ptr<const ParseNode>& b) {
- return comparator(a.get(), b.get());
- });
- // If the beginning of the range had before comments, and the first node
- // moved during the sort, then move its comments to the new head of the
- // range.
- if (original_first->comments() &&
- contents_[sr.begin].get() != original_first) {
- for (const auto& hc : original_first->comments()->before()) {
- const_cast<ParseNode*>(contents_[sr.begin].get())
- ->comments_mutable()
- ->append_before(hc);
- }
- const_cast<ParseNode*>(original_first)
- ->comments_mutable()
- ->clear_before();
- }
- const ParseNode* prev = nullptr;
- for (size_t i = sr.begin; i != sr.end; ++i) {
- const ParseNode* node = contents_[i].get();
- DCHECK(node->AsLiteral() || node->AsIdentifier() || node->AsAccessor());
- int line_number =
- prev ? prev->GetRange().end().line_number() + 1 : start_line;
- if (node->AsLiteral()) {
- const_cast<LiteralNode*>(node->AsLiteral())
- ->SetNewLocation(line_number);
- } else if (node->AsIdentifier()) {
- const_cast<IdentifierNode*>(node->AsIdentifier())
- ->SetNewLocation(line_number);
- } else if (node->AsAccessor()) {
- const_cast<AccessorNode*>(node->AsAccessor())
- ->SetNewLocation(line_number);
- }
- prev = node;
- }
- }
-}
-
-void ListNode::SortAsStringsList() {
- // Sorts alphabetically.
- SortList([](const ParseNode* a, const ParseNode* b) {
- base::StringPiece astr = GetStringRepresentation(a);
- base::StringPiece bstr = GetStringRepresentation(b);
- return astr < bstr;
- });
-}
-
-void ListNode::SortAsDepsList() {
- // Sorts first relative targets, then absolute, each group is sorted
- // alphabetically.
- SortList([](const ParseNode* a, const ParseNode* b) {
- base::StringPiece astr = GetStringRepresentation(a);
- base::StringPiece bstr = GetStringRepresentation(b);
- return std::make_pair(GetDepsCategory(astr), SplitAtFirst(astr, ':')) <
- std::make_pair(GetDepsCategory(bstr), SplitAtFirst(bstr, ':'));
- });
-}
-
-// Breaks the ParseNodes of |contents| up by ranges that should be separately
-// sorted. In particular, we break at a block comment, or an item that has an
-// attached "before" comment and is separated by a blank line from the item
-// before it. The assumption is that both of these indicate a separate 'section'
-// of a sources block across which items should not be inter-sorted.
-std::vector<ListNode::SortRange> ListNode::GetSortRanges() const {
- std::vector<SortRange> ranges;
- const ParseNode* prev = nullptr;
- size_t begin = 0;
- for (size_t i = begin; i < contents_.size(); prev = contents_[i++].get()) {
- if (IsSortRangeSeparator(contents_[i].get(), prev)) {
- if (i > begin) {
- ranges.push_back(SortRange(begin, i));
- // If |i| is an item with an attached comment, then we start the next
- // range at that point, because we want to include it in the sort.
- // Otherwise, it's a block comment which we skip over entirely because
- // we don't want to move or include it in the sort. The two cases are:
- //
- // sources = [
- // "a",
- // "b",
- //
- // #
- // # This is a block comment.
- // #
- //
- // "c",
- // "d",
- // ]
- //
- // which contains 5 elements, and for which the ranges would be { [0,
- // 2), [3, 5) } (notably excluding 2, the block comment), and:
- //
- // sources = [
- // "a",
- // "b",
- //
- // # This is a header comment.
- // "c",
- // "d",
- // ]
- //
- // which contains 4 elements, index 2 containing an attached 'before'
- // comments, and the ranges should be { [0, 2), [2, 4) }.
- if (!contents_[i]->AsBlockComment())
- begin = i;
- else
- begin = i + 1;
- } else {
- // If it was a one item range, just skip over it.
- begin = i + 1;
- }
- }
- }
- if (begin != contents_.size())
- ranges.push_back(SortRange(begin, contents_.size()));
- return ranges;
-}
-
-// LiteralNode -----------------------------------------------------------------
-
-LiteralNode::LiteralNode() = default;
-
-LiteralNode::LiteralNode(const Token& token) : value_(token) {
-}
-
-LiteralNode::~LiteralNode() = default;
-
-const LiteralNode* LiteralNode::AsLiteral() const {
- return this;
-}
-
-Value LiteralNode::Execute(Scope* scope, Err* err) const {
- switch (value_.type()) {
- case Token::TRUE_TOKEN:
- return Value(this, true);
- case Token::FALSE_TOKEN:
- return Value(this, false);
- case Token::INTEGER: {
- base::StringPiece s = value_.value();
- if ((s.starts_with("0") && s.size() > 1) || s.starts_with("-0")) {
- if (s == "-0")
- *err = MakeErrorDescribing("Negative zero doesn't make sense");
- else
- *err = MakeErrorDescribing("Leading zeros not allowed");
- return Value();
- }
- int64_t result_int;
- if (!base::StringToInt64(s, &result_int)) {
- *err = MakeErrorDescribing("This does not look like an integer");
- return Value();
- }
- return Value(this, result_int);
- }
- case Token::STRING: {
- Value v(this, Value::STRING);
- ExpandStringLiteral(scope, value_, &v, err);
- return v;
- }
- default:
- NOTREACHED();
- return Value();
- }
-}
-
-LocationRange LiteralNode::GetRange() const {
- return value_.range();
-}
-
-Err LiteralNode::MakeErrorDescribing(const std::string& msg,
- const std::string& help) const {
- return Err(value_, msg, help);
-}
-
-void LiteralNode::Print(std::ostream& out, int indent) const {
- out << IndentFor(indent) << "LITERAL(" << value_.value() << ")\n";
- PrintComments(out, indent);
-}
-
-void LiteralNode::SetNewLocation(int line_number) {
- Location old = value_.location();
- value_.set_location(
- Location(old.file(), line_number, old.column_number(), old.byte()));
-}
-
-// UnaryOpNode ----------------------------------------------------------------
-
-UnaryOpNode::UnaryOpNode() = default;
-
-UnaryOpNode::~UnaryOpNode() = default;
-
-const UnaryOpNode* UnaryOpNode::AsUnaryOp() const {
- return this;
-}
-
-Value UnaryOpNode::Execute(Scope* scope, Err* err) const {
- Value operand_value = operand_->Execute(scope, err);
- if (err->has_error())
- return Value();
- return ExecuteUnaryOperator(scope, this, operand_value, err);
-}
-
-LocationRange UnaryOpNode::GetRange() const {
- return op_.range().Union(operand_->GetRange());
-}
-
-Err UnaryOpNode::MakeErrorDescribing(const std::string& msg,
- const std::string& help) const {
- return Err(op_, msg, help);
-}
-
-void UnaryOpNode::Print(std::ostream& out, int indent) const {
- out << IndentFor(indent) << "UNARY(" << op_.value() << ")\n";
- PrintComments(out, indent);
- operand_->Print(out, indent + 1);
-}
-
-// BlockCommentNode ------------------------------------------------------------
-
-BlockCommentNode::BlockCommentNode() = default;
-
-BlockCommentNode::~BlockCommentNode() = default;
-
-const BlockCommentNode* BlockCommentNode::AsBlockComment() const {
- return this;
-}
-
-Value BlockCommentNode::Execute(Scope* scope, Err* err) const {
- return Value();
-}
-
-LocationRange BlockCommentNode::GetRange() const {
- return comment_.range();
-}
-
-Err BlockCommentNode::MakeErrorDescribing(const std::string& msg,
- const std::string& help) const {
- return Err(comment_, msg, help);
-}
-
-void BlockCommentNode::Print(std::ostream& out, int indent) const {
- out << IndentFor(indent) << "BLOCK_COMMENT(" << comment_.value() << ")\n";
- PrintComments(out, indent);
-}
-
-// EndNode ---------------------------------------------------------------------
-
-EndNode::EndNode(const Token& token) : value_(token) {
-}
-
-EndNode::~EndNode() = default;
-
-const EndNode* EndNode::AsEnd() const {
- return this;
-}
-
-Value EndNode::Execute(Scope* scope, Err* err) const {
- return Value();
-}
-
-LocationRange EndNode::GetRange() const {
- return value_.range();
-}
-
-Err EndNode::MakeErrorDescribing(const std::string& msg,
- const std::string& help) const {
- return Err(value_, msg, help);
-}
-
-void EndNode::Print(std::ostream& out, int indent) const {
- out << IndentFor(indent) << "END(" << value_.value() << ")\n";
- PrintComments(out, indent);
-}
diff --git a/chromium/tools/gn/parse_tree.h b/chromium/tools/gn/parse_tree.h
deleted file mode 100644
index 415041eebca..00000000000
--- a/chromium/tools/gn/parse_tree.h
+++ /dev/null
@@ -1,546 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_PARSE_TREE_H_
-#define TOOLS_GN_PARSE_TREE_H_
-
-#include <stddef.h>
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/macros.h"
-#include "tools/gn/err.h"
-#include "tools/gn/token.h"
-#include "tools/gn/value.h"
-
-class AccessorNode;
-class BinaryOpNode;
-class BlockCommentNode;
-class BlockNode;
-class ConditionNode;
-class EndNode;
-class FunctionCallNode;
-class IdentifierNode;
-class ListNode;
-class LiteralNode;
-class Scope;
-class UnaryOpNode;
-
-class Comments {
- public:
- Comments();
- virtual ~Comments();
-
- const std::vector<Token>& before() const { return before_; }
- void append_before(Token c) { before_.push_back(c); }
- void clear_before() { before_.clear(); }
-
- const std::vector<Token>& suffix() const { return suffix_; }
- void append_suffix(Token c) { suffix_.push_back(c); }
- // Reverse the order of the suffix comments. When walking the tree in
- // post-order we append suffix comments in reverse order, so this fixes them
- // up.
- void ReverseSuffix();
-
- const std::vector<Token>& after() const { return after_; }
- void append_after(Token c) { after_.push_back(c); }
-
- private:
- // Whole line comments before the expression.
- std::vector<Token> before_;
-
- // End-of-line comments after this expression.
- std::vector<Token> suffix_;
-
- // For top-level expressions only, after_ lists whole-line comments
- // following the expression.
- std::vector<Token> after_;
-
- DISALLOW_COPY_AND_ASSIGN(Comments);
-};
-
-// ParseNode -------------------------------------------------------------------
-
-// A node in the AST.
-class ParseNode {
- public:
- ParseNode();
- virtual ~ParseNode();
-
- virtual const AccessorNode* AsAccessor() const;
- virtual const BinaryOpNode* AsBinaryOp() const;
- virtual const BlockCommentNode* AsBlockComment() const;
- virtual const BlockNode* AsBlock() const;
- virtual const ConditionNode* AsConditionNode() const;
- virtual const EndNode* AsEnd() const;
- virtual const FunctionCallNode* AsFunctionCall() const;
- virtual const IdentifierNode* AsIdentifier() const;
- virtual const ListNode* AsList() const;
- virtual const LiteralNode* AsLiteral() const;
- virtual const UnaryOpNode* AsUnaryOp() const;
-
- virtual Value Execute(Scope* scope, Err* err) const = 0;
-
- virtual LocationRange GetRange() const = 0;
-
- // Returns an error with the given messages and the range set to something
- // that indicates this node.
- virtual Err MakeErrorDescribing(
- const std::string& msg,
- const std::string& help = std::string()) const = 0;
-
- // Prints a representation of this node to the given string, indenting
- // by the given number of spaces.
- virtual void Print(std::ostream& out, int indent) const = 0;
-
- const Comments* comments() const { return comments_.get(); }
- Comments* comments_mutable();
- void PrintComments(std::ostream& out, int indent) const;
-
- private:
- std::unique_ptr<Comments> comments_;
-
- DISALLOW_COPY_AND_ASSIGN(ParseNode);
-};
-
-// AccessorNode ----------------------------------------------------------------
-
-// Access an array or scope element.
-//
-// Currently, such values are only read-only. In that you can do:
-// a = obj1.a
-// b = obj2[0]
-// But not
-// obj1.a = 5
-// obj2[0] = 6
-//
-// In the current design where the dot operator is used only for templates, we
-// explicitly don't want to allow you to do "invoker.foo = 5", so if we added
-// support for accessors to be lvalues, we would also need to add some concept
-// of a constant scope. Supporting this would also add a lot of complications
-// to the operator= implementation, since some accessors might return values
-// in the const root scope that shouldn't be modified. Without a strong
-// use-case for this, it seems simpler to just disallow it.
-//
-// Additionally, the left-hand-side of the accessor must currently be an
-// identifier. So you can't do things like:
-// function_call()[1]
-// a = b.c.d
-// These are easier to implement if we needed them but given the very limited
-// use cases for this, it hasn't seemed worth the bother.
-class AccessorNode : public ParseNode {
- public:
- AccessorNode();
- ~AccessorNode() override;
-
- const AccessorNode* AsAccessor() const override;
- Value Execute(Scope* scope, Err* err) const override;
- LocationRange GetRange() const override;
- Err MakeErrorDescribing(
- const std::string& msg,
- const std::string& help = std::string()) const override;
- void Print(std::ostream& out, int indent) const override;
-
- // Base is the thing on the left of the [] or dot, currently always required
- // to be an identifier token.
- const Token& base() const { return base_; }
- void set_base(const Token& b) { base_ = b; }
-
- // Index is the expression inside the []. Will be null if member is set.
- const ParseNode* index() const { return index_.get(); }
- void set_index(std::unique_ptr<ParseNode> i) { index_ = std::move(i); }
-
- // The member is the identifier on the right hand side of the dot. Will be
- // null if the index is set.
- const IdentifierNode* member() const { return member_.get(); }
- void set_member(std::unique_ptr<IdentifierNode> i) { member_ = std::move(i); }
-
- void SetNewLocation(int line_number);
-
- // Evaluates the index for list accessor operations and range checks it
- // against the max length of the list. If the index is OK, sets
- // |*computed_index| and returns true. Otherwise sets the |*err| and returns
- // false.
- bool ComputeAndValidateListIndex(Scope* scope,
- size_t max_len,
- size_t* computed_index,
- Err* err) const;
-
- private:
- Value ExecuteArrayAccess(Scope* scope, Err* err) const;
- Value ExecuteScopeAccess(Scope* scope, Err* err) const;
-
- Token base_;
-
- // Either index or member will be set according to what type of access this
- // is.
- std::unique_ptr<ParseNode> index_;
- std::unique_ptr<IdentifierNode> member_;
-
- DISALLOW_COPY_AND_ASSIGN(AccessorNode);
-};
-
-// BinaryOpNode ----------------------------------------------------------------
-
-class BinaryOpNode : public ParseNode {
- public:
- BinaryOpNode();
- ~BinaryOpNode() override;
-
- const BinaryOpNode* AsBinaryOp() const override;
- Value Execute(Scope* scope, Err* err) const override;
- LocationRange GetRange() const override;
- Err MakeErrorDescribing(
- const std::string& msg,
- const std::string& help = std::string()) const override;
- void Print(std::ostream& out, int indent) const override;
-
- const Token& op() const { return op_; }
- void set_op(const Token& t) { op_ = t; }
-
- const ParseNode* left() const { return left_.get(); }
- void set_left(std::unique_ptr<ParseNode> left) { left_ = std::move(left); }
-
- const ParseNode* right() const { return right_.get(); }
- void set_right(std::unique_ptr<ParseNode> right) {
- right_ = std::move(right);
- }
-
- private:
- std::unique_ptr<ParseNode> left_;
- Token op_;
- std::unique_ptr<ParseNode> right_;
-
- DISALLOW_COPY_AND_ASSIGN(BinaryOpNode);
-};
-
-// BlockNode -------------------------------------------------------------------
-
-class BlockNode : public ParseNode {
- public:
- // How Execute manages the scopes and results.
- enum ResultMode {
- // Creates a new scope for the execution of this block and returns it as
- // a Value from Execute().
- RETURNS_SCOPE,
-
- // Executes in the context of the calling scope (variables set will go
- // into the invoking scope) and Execute will return an empty Value.
- DISCARDS_RESULT
- };
-
- BlockNode(ResultMode result_mode);
- ~BlockNode() override;
-
- const BlockNode* AsBlock() const override;
- Value Execute(Scope* scope, Err* err) const override;
- LocationRange GetRange() const override;
- Err MakeErrorDescribing(
- const std::string& msg,
- const std::string& help = std::string()) const override;
- void Print(std::ostream& out, int indent) const override;
-
- void set_begin_token(const Token& t) { begin_token_ = t; }
- void set_end(std::unique_ptr<EndNode> e) { end_ = std::move(e); }
- const EndNode* End() const { return end_.get(); }
-
- ResultMode result_mode() const { return result_mode_; }
-
- const std::vector<std::unique_ptr<ParseNode>>& statements() const {
- return statements_;
- }
- void append_statement(std::unique_ptr<ParseNode> s) {
- statements_.push_back(std::move(s));
- }
-
- private:
- const ResultMode result_mode_;
-
- // Tokens corresponding to { and }, if any (may be NULL). The end is stored
- // in a custom parse node so that it can have comments hung off of it.
- Token begin_token_;
- std::unique_ptr<EndNode> end_;
-
- std::vector<std::unique_ptr<ParseNode>> statements_;
-
- DISALLOW_COPY_AND_ASSIGN(BlockNode);
-};
-
-// ConditionNode ---------------------------------------------------------------
-
-class ConditionNode : public ParseNode {
- public:
- ConditionNode();
- ~ConditionNode() override;
-
- const ConditionNode* AsConditionNode() const override;
- Value Execute(Scope* scope, Err* err) const override;
- LocationRange GetRange() const override;
- Err MakeErrorDescribing(
- const std::string& msg,
- const std::string& help = std::string()) const override;
- void Print(std::ostream& out, int indent) const override;
-
- void set_if_token(const Token& token) { if_token_ = token; }
-
- const ParseNode* condition() const { return condition_.get(); }
- void set_condition(std::unique_ptr<ParseNode> c) {
- condition_ = std::move(c);
- }
-
- const BlockNode* if_true() const { return if_true_.get(); }
- void set_if_true(std::unique_ptr<BlockNode> t) { if_true_ = std::move(t); }
-
- // This is either empty, a block (for the else clause), or another
- // condition.
- const ParseNode* if_false() const { return if_false_.get(); }
- void set_if_false(std::unique_ptr<ParseNode> f) { if_false_ = std::move(f); }
-
- private:
- // Token corresponding to the "if" string.
- Token if_token_;
-
- std::unique_ptr<ParseNode> condition_; // Always non-null.
- std::unique_ptr<BlockNode> if_true_; // Always non-null.
- std::unique_ptr<ParseNode> if_false_; // May be null.
-
- DISALLOW_COPY_AND_ASSIGN(ConditionNode);
-};
-
-// FunctionCallNode ------------------------------------------------------------
-
-class FunctionCallNode : public ParseNode {
- public:
- FunctionCallNode();
- ~FunctionCallNode() override;
-
- const FunctionCallNode* AsFunctionCall() const override;
- Value Execute(Scope* scope, Err* err) const override;
- LocationRange GetRange() const override;
- Err MakeErrorDescribing(
- const std::string& msg,
- const std::string& help = std::string()) const override;
- void Print(std::ostream& out, int indent) const override;
-
- const Token& function() const { return function_; }
- void set_function(Token t) { function_ = t; }
-
- const ListNode* args() const { return args_.get(); }
- void set_args(std::unique_ptr<ListNode> a) { args_ = std::move(a); }
-
- const BlockNode* block() const { return block_.get(); }
- void set_block(std::unique_ptr<BlockNode> b) { block_ = std::move(b); }
-
- private:
- Token function_;
- std::unique_ptr<ListNode> args_;
- std::unique_ptr<BlockNode> block_; // May be null.
-
- DISALLOW_COPY_AND_ASSIGN(FunctionCallNode);
-};
-
-// IdentifierNode --------------------------------------------------------------
-
-class IdentifierNode : public ParseNode {
- public:
- IdentifierNode();
- explicit IdentifierNode(const Token& token);
- ~IdentifierNode() override;
-
- const IdentifierNode* AsIdentifier() const override;
- Value Execute(Scope* scope, Err* err) const override;
- LocationRange GetRange() const override;
- Err MakeErrorDescribing(
- const std::string& msg,
- const std::string& help = std::string()) const override;
- void Print(std::ostream& out, int indent) const override;
-
- const Token& value() const { return value_; }
- void set_value(const Token& t) { value_ = t; }
-
- void SetNewLocation(int line_number);
-
- private:
- Token value_;
-
- DISALLOW_COPY_AND_ASSIGN(IdentifierNode);
-};
-
-// ListNode --------------------------------------------------------------------
-
-class ListNode : public ParseNode {
- public:
- ListNode();
- ~ListNode() override;
-
- const ListNode* AsList() const override;
- Value Execute(Scope* scope, Err* err) const override;
- LocationRange GetRange() const override;
- Err MakeErrorDescribing(
- const std::string& msg,
- const std::string& help = std::string()) const override;
- void Print(std::ostream& out, int indent) const override;
-
- void set_begin_token(const Token& t) { begin_token_ = t; }
- void set_end(std::unique_ptr<EndNode> e) { end_ = std::move(e); }
- const EndNode* End() const { return end_.get(); }
-
- void append_item(std::unique_ptr<ParseNode> s) {
- contents_.push_back(std::move(s));
- }
- const std::vector<std::unique_ptr<const ParseNode>>& contents() const {
- return contents_;
- }
-
- void SortAsStringsList();
- void SortAsDepsList();
-
- // During formatting, do we want this list to always be multliline? This is
- // used to make assignments to deps, sources, etc. always be multiline lists,
- // rather than collapsed to a single line when they're one element.
- bool prefer_multiline() const { return prefer_multiline_; }
- void set_prefer_multiline(bool prefer_multiline) {
- prefer_multiline_ = prefer_multiline;
- }
-
- struct SortRange {
- size_t begin;
- size_t end;
- SortRange(size_t begin, size_t end) : begin(begin), end(end) {}
- };
- // Only public for testing.
- std::vector<SortRange> GetSortRanges() const;
-
- private:
- template <typename Comparator>
- void SortList(Comparator comparator);
-
- // Tokens corresponding to the [ and ]. The end token is stored in inside an
- // custom parse node so that it can have comments hung off of it.
- Token begin_token_;
- std::unique_ptr<EndNode> end_;
- bool prefer_multiline_;
-
- std::vector<std::unique_ptr<const ParseNode>> contents_;
-
- DISALLOW_COPY_AND_ASSIGN(ListNode);
-};
-
-// LiteralNode -----------------------------------------------------------------
-
-class LiteralNode : public ParseNode {
- public:
- LiteralNode();
- explicit LiteralNode(const Token& token);
- ~LiteralNode() override;
-
- const LiteralNode* AsLiteral() const override;
- Value Execute(Scope* scope, Err* err) const override;
- LocationRange GetRange() const override;
- Err MakeErrorDescribing(
- const std::string& msg,
- const std::string& help = std::string()) const override;
- void Print(std::ostream& out, int indent) const override;
-
- const Token& value() const { return value_; }
- void set_value(const Token& t) { value_ = t; }
-
- void SetNewLocation(int line_number);
-
- private:
- Token value_;
-
- DISALLOW_COPY_AND_ASSIGN(LiteralNode);
-};
-
-// UnaryOpNode -----------------------------------------------------------------
-
-class UnaryOpNode : public ParseNode {
- public:
- UnaryOpNode();
- ~UnaryOpNode() override;
-
- const UnaryOpNode* AsUnaryOp() const override;
- Value Execute(Scope* scope, Err* err) const override;
- LocationRange GetRange() const override;
- Err MakeErrorDescribing(
- const std::string& msg,
- const std::string& help = std::string()) const override;
- void Print(std::ostream& out, int indent) const override;
-
- const Token& op() const { return op_; }
- void set_op(const Token& t) { op_ = t; }
-
- const ParseNode* operand() const { return operand_.get(); }
- void set_operand(std::unique_ptr<ParseNode> operand) {
- operand_ = std::move(operand);
- }
-
- private:
- Token op_;
- std::unique_ptr<ParseNode> operand_;
-
- DISALLOW_COPY_AND_ASSIGN(UnaryOpNode);
-};
-
-// BlockCommentNode ------------------------------------------------------------
-
-// This node type is only used for standalone comments (that is, those not
-// specifically attached to another syntax element. The most common of these
-// is a standard header block. This node contains only the last line of such
-// a comment block as the anchor, and other lines of the block comment are
-// hung off of it as Before comments, similar to other syntax elements.
-class BlockCommentNode : public ParseNode {
- public:
- BlockCommentNode();
- ~BlockCommentNode() override;
-
- const BlockCommentNode* AsBlockComment() const override;
- Value Execute(Scope* scope, Err* err) const override;
- LocationRange GetRange() const override;
- Err MakeErrorDescribing(
- const std::string& msg,
- const std::string& help = std::string()) const override;
- void Print(std::ostream& out, int indent) const override;
-
- const Token& comment() const { return comment_; }
- void set_comment(const Token& t) { comment_ = t; }
-
- private:
- Token comment_;
-
- DISALLOW_COPY_AND_ASSIGN(BlockCommentNode);
-};
-
-// EndNode ---------------------------------------------------------------------
-
-// This node type is used as the end_ object for lists and blocks (rather than
-// just the end ']', '}', or ')' token). This is so that during formatting
-// traversal there is a node that appears at the end of the block to which
-// comments can be attached.
-class EndNode : public ParseNode {
- public:
- explicit EndNode(const Token& token);
- ~EndNode() override;
-
- const EndNode* AsEnd() const override;
- Value Execute(Scope* scope, Err* err) const override;
- LocationRange GetRange() const override;
- Err MakeErrorDescribing(
- const std::string& msg,
- const std::string& help = std::string()) const override;
- void Print(std::ostream& out, int indent) const override;
-
- const Token& value() const { return value_; }
- void set_value(const Token& t) { value_ = t; }
-
- private:
- Token value_;
-
- DISALLOW_COPY_AND_ASSIGN(EndNode);
-};
-
-#endif // TOOLS_GN_PARSE_TREE_H_
diff --git a/chromium/tools/gn/parse_tree_unittest.cc b/chromium/tools/gn/parse_tree_unittest.cc
deleted file mode 100644
index a786925b465..00000000000
--- a/chromium/tools/gn/parse_tree_unittest.cc
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/parse_tree.h"
-
-#include <stdint.h>
-
-#include <memory>
-#include <utility>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/test_with_scope.h"
-
-TEST(ParseTree, Accessor) {
- TestWithScope setup;
-
- // Make a pretend parse node with proper tracking that we can blame for the
- // given value.
- InputFile input_file(SourceFile("//foo"));
- Token base_token(Location(&input_file, 1, 1, 1), Token::IDENTIFIER, "a");
- Token member_token(Location(&input_file, 1, 1, 1), Token::IDENTIFIER, "b");
-
- AccessorNode accessor;
- accessor.set_base(base_token);
-
- std::unique_ptr<IdentifierNode> member_identifier =
- std::make_unique<IdentifierNode>(member_token);
- accessor.set_member(std::move(member_identifier));
-
- // The access should fail because a is not defined.
- Err err;
- Value result = accessor.Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
- EXPECT_EQ(Value::NONE, result.type());
-
- // Define a as a Scope. It should still fail because b isn't defined.
- err = Err();
- setup.scope()->SetValue(
- "a", Value(nullptr, std::make_unique<Scope>(setup.scope())), nullptr);
- result = accessor.Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
- EXPECT_EQ(Value::NONE, result.type());
-
- // Define b, accessor should succeed now.
- const int64_t kBValue = 42;
- err = Err();
- setup.scope()
- ->GetMutableValue("a", Scope::SEARCH_NESTED, false)
- ->scope_value()
- ->SetValue("b", Value(nullptr, kBValue), nullptr);
- result = accessor.Execute(setup.scope(), &err);
- EXPECT_FALSE(err.has_error());
- ASSERT_EQ(Value::INTEGER, result.type());
- EXPECT_EQ(kBValue, result.int_value());
-}
-
-TEST(ParseTree, BlockUnusedVars) {
- TestWithScope setup;
-
- // Printing both values should be OK.
- //
- // The crazy template definition here is a way to execute a block without
- // defining a target. Templates require that both the target_name and the
- // invoker be used, which is what the assertion statement inside the template
- // does.
- TestParseInput input_all_used(
- "template(\"foo\") { assert(target_name != 0 && invoker != 0) }\n"
- "foo(\"a\") {\n"
- " a = 12\n"
- " b = 13\n"
- " print(\"$a $b\")\n"
- "}");
- EXPECT_FALSE(input_all_used.has_error());
-
- Err err;
- input_all_used.parsed()->Execute(setup.scope(), &err);
- EXPECT_FALSE(err.has_error());
-
- // Skipping one should throw an unused var error.
- TestParseInput input_unused(
- "foo(\"a\") {\n"
- " a = 12\n"
- " b = 13\n"
- " print(\"$a\")\n"
- "}");
- EXPECT_FALSE(input_unused.has_error());
-
- input_unused.parsed()->Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
-
- // Also verify that the unused variable has the correct origin set. The
- // origin will point to the value assigned to the variable (in this case, the
- // "13" assigned to "b".
- EXPECT_EQ(3, err.location().line_number());
- EXPECT_EQ(7, err.location().column_number());
-}
-
-TEST(ParseTree, OriginForDereference) {
- TestWithScope setup;
- TestParseInput input(
- "a = 6\n"
- "get_target_outputs(a)");
- EXPECT_FALSE(input.has_error());
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
-
- // The origin for the "not a string" error message should be where the value
- // was dereferenced (the "a" on the second line).
- EXPECT_EQ(2, err.location().line_number());
- EXPECT_EQ(20, err.location().column_number());
-}
-
-TEST(ParseTree, SortRangeExtraction) {
- TestWithScope setup;
-
- // Ranges are [begin, end).
-
- {
- TestParseInput input(
- "sources = [\n"
- " \"a\",\n"
- " \"b\",\n"
- " \n"
- " #\n"
- " # Block\n"
- " #\n"
- " \n"
- " \"c\","
- " \"d\","
- "]\n");
- EXPECT_FALSE(input.has_error());
- ASSERT_TRUE(input.parsed()->AsBlock());
- ASSERT_TRUE(input.parsed()->AsBlock()->statements()[0]->AsBinaryOp());
- const BinaryOpNode* binop =
- input.parsed()->AsBlock()->statements()[0]->AsBinaryOp();
- ASSERT_TRUE(binop->right()->AsList());
- const ListNode* list = binop->right()->AsList();
- EXPECT_EQ(5u, list->contents().size());
- auto ranges = list->GetSortRanges();
- ASSERT_EQ(2u, ranges.size());
- EXPECT_EQ(0u, ranges[0].begin);
- EXPECT_EQ(2u, ranges[0].end);
- EXPECT_EQ(3u, ranges[1].begin);
- EXPECT_EQ(5u, ranges[1].end);
- }
-
- {
- TestParseInput input(
- "sources = [\n"
- " \"a\",\n"
- " \"b\",\n"
- " \n"
- " # Attached comment.\n"
- " \"c\","
- " \"d\","
- "]\n");
- EXPECT_FALSE(input.has_error());
- ASSERT_TRUE(input.parsed()->AsBlock());
- ASSERT_TRUE(input.parsed()->AsBlock()->statements()[0]->AsBinaryOp());
- const BinaryOpNode* binop =
- input.parsed()->AsBlock()->statements()[0]->AsBinaryOp();
- ASSERT_TRUE(binop->right()->AsList());
- const ListNode* list = binop->right()->AsList();
- EXPECT_EQ(4u, list->contents().size());
- auto ranges = list->GetSortRanges();
- ASSERT_EQ(2u, ranges.size());
- EXPECT_EQ(0u, ranges[0].begin);
- EXPECT_EQ(2u, ranges[0].end);
- EXPECT_EQ(2u, ranges[1].begin);
- EXPECT_EQ(4u, ranges[1].end);
- }
-
- {
- TestParseInput input(
- "sources = [\n"
- " # At end of list.\n"
- " \"zzzzzzzzzzz.cc\","
- "]\n");
- EXPECT_FALSE(input.has_error());
- ASSERT_TRUE(input.parsed()->AsBlock());
- ASSERT_TRUE(input.parsed()->AsBlock()->statements()[0]->AsBinaryOp());
- const BinaryOpNode* binop =
- input.parsed()->AsBlock()->statements()[0]->AsBinaryOp();
- ASSERT_TRUE(binop->right()->AsList());
- const ListNode* list = binop->right()->AsList();
- EXPECT_EQ(1u, list->contents().size());
- auto ranges = list->GetSortRanges();
- ASSERT_EQ(1u, ranges.size());
- EXPECT_EQ(0u, ranges[0].begin);
- EXPECT_EQ(1u, ranges[0].end);
- }
-
- {
- TestParseInput input(
- "sources = [\n"
- " # Block at start.\n"
- " \n"
- " \"z.cc\","
- " \"y.cc\","
- "]\n");
- EXPECT_FALSE(input.has_error());
- ASSERT_TRUE(input.parsed()->AsBlock());
- ASSERT_TRUE(input.parsed()->AsBlock()->statements()[0]->AsBinaryOp());
- const BinaryOpNode* binop =
- input.parsed()->AsBlock()->statements()[0]->AsBinaryOp();
- ASSERT_TRUE(binop->right()->AsList());
- const ListNode* list = binop->right()->AsList();
- EXPECT_EQ(3u, list->contents().size());
- auto ranges = list->GetSortRanges();
- ASSERT_EQ(1u, ranges.size());
- EXPECT_EQ(1u, ranges[0].begin);
- EXPECT_EQ(3u, ranges[0].end);
- }
-}
-
-TEST(ParseTree, Integers) {
- static const char* const kGood[] = {
- "0",
- "10",
- "-54321",
- "9223372036854775807", // INT64_MAX
- "-9223372036854775808", // INT64_MIN
- };
- for (auto* s : kGood) {
- TestParseInput input(std::string("x = ") + s);
- EXPECT_FALSE(input.has_error());
-
- TestWithScope setup;
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- EXPECT_FALSE(err.has_error());
- }
-
- static const char* const kBad[] = {
- "-0",
- "010",
- "-010",
- "9223372036854775808", // INT64_MAX + 1
- "-9223372036854775809", // INT64_MIN - 1
- };
- for (auto* s : kBad) {
- TestParseInput input(std::string("x = ") + s);
- EXPECT_FALSE(input.has_error());
-
- TestWithScope setup;
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
- }
-}
diff --git a/chromium/tools/gn/parser.cc b/chromium/tools/gn/parser.cc
deleted file mode 100644
index c8dd6547dc4..00000000000
--- a/chromium/tools/gn/parser.cc
+++ /dev/null
@@ -1,884 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/parser.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/logging.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/operators.h"
-#include "tools/gn/token.h"
-
-const char kGrammar_Help[] =
- R"*(Language and grammar for GN build files
-
-Tokens
-
- GN build files are read as sequences of tokens. While splitting the file
- into tokens, the next token is the longest sequence of characters that form a
- valid token.
-
-White space and comments
-
- White space is comprised of spaces (U+0020), horizontal tabs (U+0009),
- carriage returns (U+000D), and newlines (U+000A).
-
- Comments start at the character "#" and stop at the next newline.
-
- White space and comments are ignored except that they may separate tokens
- that would otherwise combine into a single token.
-
-Identifiers
-
- Identifiers name variables and functions.
-
- identifier = letter { letter | digit } .
- letter = "A" ... "Z" | "a" ... "z" | "_" .
- digit = "0" ... "9" .
-
-Keywords
-
- The following keywords are reserved and may not be used as identifiers:
-
- else false if true
-
-Integer literals
-
- An integer literal represents a decimal integer value.
-
- integer = [ "-" ] digit { digit } .
-
- Leading zeros and negative zero are disallowed.
-
-String literals
-
- A string literal represents a string value consisting of the quoted
- characters with possible escape sequences and variable expansions.
-
- string = `"` { char | escape | expansion } `"` .
- escape = `\` ( "$" | `"` | char ) .
- BracketExpansion = "{" ( identifier | ArrayAccess | ScopeAccess "
- ") "}" .
- Hex = "0x" [0-9A-Fa-f][0-9A-Fa-f]
- expansion = "$" ( identifier | BracketExpansion | Hex ) .
- char = /* any character except "$", `"`, or newline "
- "*/ .
-
- After a backslash, certain sequences represent special characters:
-
- \" U+0022 quotation mark
- \$ U+0024 dollar sign
- \\ U+005C backslash
-
- All other backslashes represent themselves.
-
- To insert an arbitrary byte value, use $0xFF. For example, to insert a
- newline character: "Line one$0x0ALine two".
-
- An expansion will evaluate the variable following the '$' and insert a
- stringified version of it into the result. For example, to concat two path
- components with a slash separating them:
- "$var_one/$var_two"
- Use the "${var_one}" format to be explicitly deliniate the variable for
- otherwise-ambiguous cases.
-
-Punctuation
-
- The following character sequences represent punctuation:
-
- + += == != ( )
- - -= < <= [ ]
- ! = > >= { }
- && || . ,
-
-Grammar
-
- The input tokens form a syntax tree following a context-free grammar:
-
- File = StatementList .
-
- Statement = Assignment | Call | Condition .
- LValue = identifier | ArrayAccess | ScopeAccess .
- Assignment = LValue AssignOp Expr .
- Call = identifier "(" [ ExprList ] ")" [ Block ] .
- Condition = "if" "(" Expr ")" Block
- [ "else" ( Condition | Block ) ] .
- Block = "{" StatementList "}" .
- StatementList = { Statement } .
-
- ArrayAccess = identifier "[" Expr "]" .
- ScopeAccess = identifier "." identifier .
- Expr = UnaryExpr | Expr BinaryOp Expr .
- UnaryExpr = PrimaryExpr | UnaryOp UnaryExpr .
- PrimaryExpr = identifier | integer | string | Call
- | ArrayAccess | ScopeAccess | Block
- | "(" Expr ")"
- | "[" [ ExprList [ "," ] ] "]" .
- ExprList = Expr { "," Expr } .
-
- AssignOp = "=" | "+=" | "-=" .
- UnaryOp = "!" .
- BinaryOp = "+" | "-" // highest priority
- | "<" | "<=" | ">" | ">="
- | "==" | "!="
- | "&&"
- | "||" . // lowest priority
-
- All binary operators are left-associative.
-
-Types
-
- The GN language is dynamically typed. The following types are used:
-
- - Boolean: Uses the keywords "true" and "false". There is no implicit
- conversion between booleans and integers.
-
- - Integers: All numbers in GN are signed 64-bit integers.
-
- - Strings: Strings are 8-bit with no enforced encoding. When a string is
- used to interact with other systems with particular encodings (like the
- Windows and Mac filesystems) it is assumed to be UTF-8. See "String
- literals" above for more.
-
- - Lists: Lists are arbitrary-length ordered lists of values. See "Lists"
- below for more.
-
- - Scopes: Scopes are like dictionaries that use variable names for keys. See
- "Scopes" below for more.
-
-Lists
-
- Lists are created with [] and using commas to separate items:
-
- mylist = [ 0, 1, 2, "some string" ]
-
- A comma after the last item is optional. Lists are dereferenced using 0-based
- indexing:
-
- mylist[0] += 1
- var = mylist[2]
-
- Lists can be concatenated using the '+' and '+=' operators. Bare values can
- not be concatenated with lists, to add a single item, it must be put into a
- list of length one.
-
- Items can be removed from lists using the '-' and '-=' operators. This will
- remove all occurrences of every item in the right-hand list from the
- left-hand list. It is an error to remove an item not in the list. This is to
- prevent common typos and to detect dead code that is removing things that no
- longer apply.
-
- It is an error to use '=' to replace a nonempty list with another nonempty
- list. This is to prevent accidentally overwriting data when in most cases
- '+=' was intended. To overwrite a list on purpose, first assign it to the
- empty list:
-
- mylist = []
- mylist = otherlist
-
- When assigning to a list named 'sources' using '=' or '+=', list items may be
- automatically filtered out. See "gn help set_sources_assignment_filter" for
- more.
-
-Scopes
-
- All execution happens in the context of a scope which holds the current state
- (like variables). With the exception of loops and conditions, '{' introduces
- a new scope that has a parent reference to the old scope.
-
- Variable reads recursively search all nested scopes until the variable is
- found or there are no more scopes. Variable writes always go into the current
- scope. This means that after the closing '}' (again excepting loops and
- conditions), all local variables will be restored to the previous values.
- This also means that "foo = foo" can do useful work by copying a variable
- into the current scope that was defined in a containing scope.
-
- Scopes can also be assigned to variables. Such scopes can be created by
- functions like exec_script, when invoking a template (the template code
- refers to the variables set by the invoking code by the implicitly-created
- "invoker" scope), or explicitly like:
-
- empty_scope = {}
- myvalues = {
- foo = 21
- bar = "something"
- }
-
- Inside such a scope definition can be any GN code including conditionals and
- function calls. After the close of the scope, it will contain all variables
- explicitly set by the code contained inside it. After this, the values can be
- read, modified, or added to:
-
- myvalues.foo += 2
- empty_scope.new_thing = [ 1, 2, 3 ]
-)*";
-
-enum Precedence {
- PRECEDENCE_ASSIGNMENT = 1, // Lowest precedence.
- PRECEDENCE_OR = 2,
- PRECEDENCE_AND = 3,
- PRECEDENCE_EQUALITY = 4,
- PRECEDENCE_RELATION = 5,
- PRECEDENCE_SUM = 6,
- PRECEDENCE_PREFIX = 7,
- PRECEDENCE_CALL = 8,
- PRECEDENCE_DOT = 9, // Highest precedence.
-};
-
-// The top-level for blocks/ifs is recursive descent, the expression parser is
-// a Pratt parser. The basic idea there is to have the precedences (and
-// associativities) encoded relative to each other and only parse up until you
-// hit something of that precedence. There's a dispatch table in expressions_
-// at the top of parser.cc that describes how each token dispatches if it's
-// seen as either a prefix or infix operator, and if it's infix, what its
-// precedence is.
-//
-// Refs:
-// - http://javascript.crockford.com/tdop/tdop.html
-// - http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
-
-// Indexed by Token::Type.
-ParserHelper Parser::expressions_[] = {
- {nullptr, nullptr, -1}, // INVALID
- {&Parser::Literal, nullptr, -1}, // INTEGER
- {&Parser::Literal, nullptr, -1}, // STRING
- {&Parser::Literal, nullptr, -1}, // TRUE_TOKEN
- {&Parser::Literal, nullptr, -1}, // FALSE_TOKEN
- {nullptr, &Parser::Assignment, PRECEDENCE_ASSIGNMENT}, // EQUAL
- {nullptr, &Parser::BinaryOperator, PRECEDENCE_SUM}, // PLUS
- {nullptr, &Parser::BinaryOperator, PRECEDENCE_SUM}, // MINUS
- {nullptr, &Parser::Assignment, PRECEDENCE_ASSIGNMENT}, // PLUS_EQUALS
- {nullptr, &Parser::Assignment, PRECEDENCE_ASSIGNMENT}, // MINUS_EQUALS
- {nullptr, &Parser::BinaryOperator, PRECEDENCE_EQUALITY}, // EQUAL_EQUAL
- {nullptr, &Parser::BinaryOperator, PRECEDENCE_EQUALITY}, // NOT_EQUAL
- {nullptr, &Parser::BinaryOperator, PRECEDENCE_RELATION}, // LESS_EQUAL
- {nullptr, &Parser::BinaryOperator, PRECEDENCE_RELATION}, // GREATER_EQUAL
- {nullptr, &Parser::BinaryOperator, PRECEDENCE_RELATION}, // LESS_THAN
- {nullptr, &Parser::BinaryOperator, PRECEDENCE_RELATION}, // GREATER_THAN
- {nullptr, &Parser::BinaryOperator, PRECEDENCE_AND}, // BOOLEAN_AND
- {nullptr, &Parser::BinaryOperator, PRECEDENCE_OR}, // BOOLEAN_OR
- {&Parser::Not, nullptr, -1}, // BANG
- {nullptr, &Parser::DotOperator, PRECEDENCE_DOT}, // DOT
- {&Parser::Group, nullptr, -1}, // LEFT_PAREN
- {nullptr, nullptr, -1}, // RIGHT_PAREN
- {&Parser::List, &Parser::Subscript, PRECEDENCE_CALL}, // LEFT_BRACKET
- {nullptr, nullptr, -1}, // RIGHT_BRACKET
- {&Parser::Block, nullptr, -1}, // LEFT_BRACE
- {nullptr, nullptr, -1}, // RIGHT_BRACE
- {nullptr, nullptr, -1}, // IF
- {nullptr, nullptr, -1}, // ELSE
- {&Parser::Name, &Parser::IdentifierOrCall, PRECEDENCE_CALL}, // IDENTIFIER
- {nullptr, nullptr, -1}, // COMMA
- {nullptr, nullptr, -1}, // UNCLASSIFIED_COMMENT
- {nullptr, nullptr, -1}, // LINE_COMMENT
- {nullptr, nullptr, -1}, // SUFFIX_COMMENT
- {&Parser::BlockComment, nullptr, -1}, // BLOCK_COMMENT
-};
-
-Parser::Parser(const std::vector<Token>& tokens, Err* err)
- : invalid_token_(Location(), Token::INVALID, base::StringPiece()),
- err_(err),
- cur_(0) {
- for (const auto& token : tokens) {
- switch (token.type()) {
- case Token::LINE_COMMENT:
- line_comment_tokens_.push_back(token);
- break;
- case Token::SUFFIX_COMMENT:
- suffix_comment_tokens_.push_back(token);
- break;
- default:
- // Note that BLOCK_COMMENTs (top-level standalone comments) are passed
- // through the real parser.
- tokens_.push_back(token);
- break;
- }
- }
-}
-
-Parser::~Parser() = default;
-
-// static
-std::unique_ptr<ParseNode> Parser::Parse(const std::vector<Token>& tokens,
- Err* err) {
- Parser p(tokens, err);
- return p.ParseFile();
-}
-
-// static
-std::unique_ptr<ParseNode> Parser::ParseExpression(
- const std::vector<Token>& tokens,
- Err* err) {
- Parser p(tokens, err);
- std::unique_ptr<ParseNode> expr = p.ParseExpression();
- if (!p.at_end() && !err->has_error()) {
- *err = Err(p.cur_token(), "Trailing garbage");
- return nullptr;
- }
- return expr;
-}
-
-// static
-std::unique_ptr<ParseNode> Parser::ParseValue(const std::vector<Token>& tokens,
- Err* err) {
- for (const Token& token : tokens) {
- switch (token.type()) {
- case Token::INTEGER:
- case Token::STRING:
- case Token::TRUE_TOKEN:
- case Token::FALSE_TOKEN:
- case Token::LEFT_BRACKET:
- case Token::RIGHT_BRACKET:
- case Token::COMMA:
- continue;
- default:
- *err = Err(token, "Invalid token in literal value");
- return nullptr;
- }
- }
-
- return ParseExpression(tokens, err);
-}
-
-bool Parser::IsAssignment(const ParseNode* node) const {
- return node && node->AsBinaryOp() &&
- (node->AsBinaryOp()->op().type() == Token::EQUAL ||
- node->AsBinaryOp()->op().type() == Token::PLUS_EQUALS ||
- node->AsBinaryOp()->op().type() == Token::MINUS_EQUALS);
-}
-
-bool Parser::IsStatementBreak(Token::Type token_type) const {
- switch (token_type) {
- case Token::IDENTIFIER:
- case Token::LEFT_BRACE:
- case Token::RIGHT_BRACE:
- case Token::IF:
- case Token::ELSE:
- return true;
- default:
- return false;
- }
-}
-
-bool Parser::LookAhead(Token::Type type) {
- if (at_end())
- return false;
- return cur_token().type() == type;
-}
-
-bool Parser::Match(Token::Type type) {
- if (!LookAhead(type))
- return false;
- Consume();
- return true;
-}
-
-const Token& Parser::Consume(Token::Type type, const char* error_message) {
- Token::Type types[1] = { type };
- return Consume(types, 1, error_message);
-}
-
-const Token& Parser::Consume(Token::Type* types,
- size_t num_types,
- const char* error_message) {
- if (has_error()) {
- // Don't overwrite current error, but make progress through tokens so that
- // a loop that's expecting a particular token will still terminate.
- if (!at_end())
- cur_++;
- return invalid_token_;
- }
- if (at_end()) {
- const char kEOFMsg[] = "I hit EOF instead.";
- if (tokens_.empty())
- *err_ = Err(Location(), error_message, kEOFMsg);
- else
- *err_ = Err(tokens_[tokens_.size() - 1], error_message, kEOFMsg);
- return invalid_token_;
- }
-
- for (size_t i = 0; i < num_types; ++i) {
- if (cur_token().type() == types[i])
- return Consume();
- }
- *err_ = Err(cur_token(), error_message);
- return invalid_token_;
-}
-
-const Token& Parser::Consume() {
- return tokens_[cur_++];
-}
-
-std::unique_ptr<ParseNode> Parser::ParseExpression() {
- return ParseExpression(0);
-}
-
-std::unique_ptr<ParseNode> Parser::ParseExpression(int precedence) {
- if (at_end())
- return std::unique_ptr<ParseNode>();
-
- const Token& token = Consume();
- PrefixFunc prefix = expressions_[token.type()].prefix;
-
- if (prefix == nullptr) {
- *err_ = Err(token,
- std::string("Unexpected token '") + token.value().as_string() +
- std::string("'"));
- return std::unique_ptr<ParseNode>();
- }
-
- std::unique_ptr<ParseNode> left = (this->*prefix)(token);
- if (has_error())
- return left;
-
- while (!at_end() && !IsStatementBreak(cur_token().type()) &&
- precedence <= expressions_[cur_token().type()].precedence) {
- const Token& next_token = Consume();
- InfixFunc infix = expressions_[next_token.type()].infix;
- if (infix == nullptr) {
- *err_ = Err(next_token, std::string("Unexpected token '") +
- next_token.value().as_string() +
- std::string("'"));
- return std::unique_ptr<ParseNode>();
- }
- left = (this->*infix)(std::move(left), next_token);
- if (has_error())
- return std::unique_ptr<ParseNode>();
- }
-
- return left;
-}
-
-std::unique_ptr<ParseNode> Parser::Block(const Token& token) {
- // This entrypoint into ParseBlock means it's part of an expression and we
- // always want the result.
- return ParseBlock(token, BlockNode::RETURNS_SCOPE);
-}
-
-std::unique_ptr<ParseNode> Parser::Literal(const Token& token) {
- return std::make_unique<LiteralNode>(token);
-}
-
-std::unique_ptr<ParseNode> Parser::Name(const Token& token) {
- return IdentifierOrCall(std::unique_ptr<ParseNode>(), token);
-}
-
-std::unique_ptr<ParseNode> Parser::BlockComment(const Token& token) {
- std::unique_ptr<BlockCommentNode> comment =
- std::make_unique<BlockCommentNode>();
- comment->set_comment(token);
- return std::move(comment);
-}
-
-std::unique_ptr<ParseNode> Parser::Group(const Token& token) {
- std::unique_ptr<ParseNode> expr = ParseExpression();
- if (has_error())
- return std::unique_ptr<ParseNode>();
- Consume(Token::RIGHT_PAREN, "Expected ')'");
- return expr;
-}
-
-std::unique_ptr<ParseNode> Parser::Not(const Token& token) {
- std::unique_ptr<ParseNode> expr = ParseExpression(PRECEDENCE_PREFIX + 1);
- if (has_error())
- return std::unique_ptr<ParseNode>();
- if (!expr) {
- if (!has_error())
- *err_ = Err(token, "Expected right-hand side for '!'.");
- return std::unique_ptr<ParseNode>();
- }
- std::unique_ptr<UnaryOpNode> unary_op = std::make_unique<UnaryOpNode>();
- unary_op->set_op(token);
- unary_op->set_operand(std::move(expr));
- return std::move(unary_op);
-}
-
-std::unique_ptr<ParseNode> Parser::List(const Token& node) {
- std::unique_ptr<ParseNode> list(ParseList(node, Token::RIGHT_BRACKET, true));
- if (!has_error() && !at_end())
- Consume(Token::RIGHT_BRACKET, "Expected ']'");
- return list;
-}
-
-std::unique_ptr<ParseNode> Parser::BinaryOperator(
- std::unique_ptr<ParseNode> left,
- const Token& token) {
- std::unique_ptr<ParseNode> right =
- ParseExpression(expressions_[token.type()].precedence + 1);
- if (!right) {
- if (!has_error()) {
- *err_ = Err(token, "Expected right-hand side for '" +
- token.value().as_string() + "'");
- }
- return std::unique_ptr<ParseNode>();
- }
- std::unique_ptr<BinaryOpNode> binary_op = std::make_unique<BinaryOpNode>();
- binary_op->set_op(token);
- binary_op->set_left(std::move(left));
- binary_op->set_right(std::move(right));
- return std::move(binary_op);
-}
-
-std::unique_ptr<ParseNode> Parser::IdentifierOrCall(
- std::unique_ptr<ParseNode> left,
- const Token& token) {
- std::unique_ptr<ListNode> list = std::make_unique<ListNode>();
- list->set_begin_token(token);
- list->set_end(std::make_unique<EndNode>(token));
- std::unique_ptr<BlockNode> block;
- bool has_arg = false;
- if (LookAhead(Token::LEFT_PAREN)) {
- const Token& start_token = Consume();
- // Parsing a function call.
- has_arg = true;
- if (Match(Token::RIGHT_PAREN)) {
- // Nothing, just an empty call.
- } else {
- list = ParseList(start_token, Token::RIGHT_PAREN, false);
- if (has_error())
- return std::unique_ptr<ParseNode>();
- Consume(Token::RIGHT_PAREN, "Expected ')' after call");
- }
- // Optionally with a scope.
- if (LookAhead(Token::LEFT_BRACE)) {
- block = ParseBlock(Consume(), BlockNode::DISCARDS_RESULT);
- if (has_error())
- return std::unique_ptr<ParseNode>();
- }
- }
-
- if (!left && !has_arg) {
- // Not a function call, just a standalone identifier.
- return std::make_unique<IdentifierNode>(token);
- }
- std::unique_ptr<FunctionCallNode> func_call =
- std::make_unique<FunctionCallNode>();
- func_call->set_function(token);
- func_call->set_args(std::move(list));
- if (block)
- func_call->set_block(std::move(block));
- return std::move(func_call);
-}
-
-std::unique_ptr<ParseNode> Parser::Assignment(std::unique_ptr<ParseNode> left,
- const Token& token) {
- if (left->AsIdentifier() == nullptr && left->AsAccessor() == nullptr) {
- *err_ = Err(left.get(),
- "The left-hand side of an assignment must be an identifier, "
- "scope access, or array access.");
- return std::unique_ptr<ParseNode>();
- }
- std::unique_ptr<ParseNode> value = ParseExpression(PRECEDENCE_ASSIGNMENT);
- if (!value) {
- if (!has_error())
- *err_ = Err(token, "Expected right-hand side for assignment.");
- return std::unique_ptr<ParseNode>();
- }
- std::unique_ptr<BinaryOpNode> assign = std::make_unique<BinaryOpNode>();
- assign->set_op(token);
- assign->set_left(std::move(left));
- assign->set_right(std::move(value));
- return std::move(assign);
-}
-
-std::unique_ptr<ParseNode> Parser::Subscript(std::unique_ptr<ParseNode> left,
- const Token& token) {
- // TODO: Maybe support more complex expressions like a[0][0]. This would
- // require work on the evaluator too.
- if (left->AsIdentifier() == nullptr) {
- *err_ = Err(left.get(), "May only subscript identifiers.",
- "The thing on the left hand side of the [] must be an identifier\n"
- "and not an expression. If you need this, you'll have to assign the\n"
- "value to a temporary before subscripting. Sorry.");
- return std::unique_ptr<ParseNode>();
- }
- std::unique_ptr<ParseNode> value = ParseExpression();
- Consume(Token::RIGHT_BRACKET, "Expecting ']' after subscript.");
- std::unique_ptr<AccessorNode> accessor = std::make_unique<AccessorNode>();
- accessor->set_base(left->AsIdentifier()->value());
- accessor->set_index(std::move(value));
- return std::move(accessor);
-}
-
-std::unique_ptr<ParseNode> Parser::DotOperator(std::unique_ptr<ParseNode> left,
- const Token& token) {
- if (left->AsIdentifier() == nullptr) {
- *err_ = Err(left.get(), "May only use \".\" for identifiers.",
- "The thing on the left hand side of the dot must be an identifier\n"
- "and not an expression. If you need this, you'll have to assign the\n"
- "value to a temporary first. Sorry.");
- return std::unique_ptr<ParseNode>();
- }
-
- std::unique_ptr<ParseNode> right = ParseExpression(PRECEDENCE_DOT);
- if (!right || !right->AsIdentifier()) {
- *err_ = Err(token, "Expected identifier for right-hand-side of \".\"",
- "Good: a.cookies\nBad: a.42\nLooks good but still bad: a.cookies()");
- return std::unique_ptr<ParseNode>();
- }
-
- std::unique_ptr<AccessorNode> accessor = std::make_unique<AccessorNode>();
- accessor->set_base(left->AsIdentifier()->value());
- accessor->set_member(std::unique_ptr<IdentifierNode>(
- static_cast<IdentifierNode*>(right.release())));
- return std::move(accessor);
-}
-
-// Does not Consume the start or end token.
-std::unique_ptr<ListNode> Parser::ParseList(const Token& start_token,
- Token::Type stop_before,
- bool allow_trailing_comma) {
- std::unique_ptr<ListNode> list = std::make_unique<ListNode>();
- list->set_begin_token(start_token);
- bool just_got_comma = false;
- bool first_time = true;
- while (!LookAhead(stop_before)) {
- if (!first_time) {
- if (!just_got_comma) {
- // Require commas separate things in lists.
- *err_ = Err(cur_token(), "Expected comma between items.");
- return std::unique_ptr<ListNode>();
- }
- }
- first_time = false;
-
- // Why _OR? We're parsing things that are higher precedence than the ,
- // that separates the items of the list. , should appear lower than
- // boolean expressions (the lowest of which is OR), but above assignments.
- list->append_item(ParseExpression(PRECEDENCE_OR));
- if (has_error())
- return std::unique_ptr<ListNode>();
- if (at_end()) {
- *err_ =
- Err(tokens_[tokens_.size() - 1], "Unexpected end of file in list.");
- return std::unique_ptr<ListNode>();
- }
- if (list->contents().back()->AsBlockComment()) {
- // If there was a comment inside the list, we don't need a comma to the
- // next item, so pretend we got one, if we're expecting one.
- just_got_comma = allow_trailing_comma;
- } else {
- just_got_comma = Match(Token::COMMA);
- }
- }
- if (just_got_comma && !allow_trailing_comma) {
- *err_ = Err(cur_token(), "Trailing comma");
- return std::unique_ptr<ListNode>();
- }
- list->set_end(std::make_unique<EndNode>(cur_token()));
- return list;
-}
-
-std::unique_ptr<ParseNode> Parser::ParseFile() {
- std::unique_ptr<BlockNode> file =
- std::make_unique<BlockNode>(BlockNode::DISCARDS_RESULT);
- for (;;) {
- if (at_end())
- break;
- std::unique_ptr<ParseNode> statement = ParseStatement();
- if (!statement)
- break;
- file->append_statement(std::move(statement));
- }
- if (!at_end() && !has_error())
- *err_ = Err(cur_token(), "Unexpected here, should be newline.");
- if (has_error())
- return std::unique_ptr<ParseNode>();
-
- // TODO(scottmg): If this is measurably expensive, it could be done only
- // when necessary (when reformatting, or during tests). Comments are
- // separate from the parse tree at this point, so downstream code can remain
- // ignorant of them.
- AssignComments(file.get());
-
- return std::move(file);
-}
-
-std::unique_ptr<ParseNode> Parser::ParseStatement() {
- if (LookAhead(Token::IF)) {
- return ParseCondition();
- } else if (LookAhead(Token::BLOCK_COMMENT)) {
- return BlockComment(Consume());
- } else {
- // TODO(scottmg): Is this too strict? Just drop all the testing if we want
- // to allow "pointless" expressions and return ParseExpression() directly.
- std::unique_ptr<ParseNode> stmt = ParseExpression();
- if (stmt) {
- if (stmt->AsFunctionCall() || IsAssignment(stmt.get()))
- return stmt;
- }
- if (!has_error()) {
- const Token& token = cur_or_last_token();
- *err_ = Err(token, "Expecting assignment or function call.");
- }
- return std::unique_ptr<ParseNode>();
- }
-}
-
-std::unique_ptr<BlockNode> Parser::ParseBlock(
- const Token& begin_brace,
- BlockNode::ResultMode result_mode) {
- if (has_error())
- return std::unique_ptr<BlockNode>();
- std::unique_ptr<BlockNode> block = std::make_unique<BlockNode>(result_mode);
- block->set_begin_token(begin_brace);
-
- for (;;) {
- if (LookAhead(Token::RIGHT_BRACE)) {
- block->set_end(std::make_unique<EndNode>(Consume()));
- break;
- }
-
- std::unique_ptr<ParseNode> statement = ParseStatement();
- if (!statement)
- return std::unique_ptr<BlockNode>();
- block->append_statement(std::move(statement));
- }
- return block;
-}
-
-std::unique_ptr<ParseNode> Parser::ParseCondition() {
- std::unique_ptr<ConditionNode> condition = std::make_unique<ConditionNode>();
- condition->set_if_token(Consume(Token::IF, "Expected 'if'"));
- Consume(Token::LEFT_PAREN, "Expected '(' after 'if'.");
- condition->set_condition(ParseExpression());
- if (IsAssignment(condition->condition()))
- *err_ = Err(condition->condition(), "Assignment not allowed in 'if'.");
- Consume(Token::RIGHT_PAREN, "Expected ')' after condition of 'if'.");
- condition->set_if_true(ParseBlock(
- Consume(Token::LEFT_BRACE, "Expected '{' to start 'if' block."),
- BlockNode::DISCARDS_RESULT));
- if (Match(Token::ELSE)) {
- if (LookAhead(Token::LEFT_BRACE)) {
- condition->set_if_false(ParseBlock(Consume(),
- BlockNode::DISCARDS_RESULT));
- } else if (LookAhead(Token::IF)) {
- condition->set_if_false(ParseStatement());
- } else {
- *err_ = Err(cur_or_last_token(), "Expected '{' or 'if' after 'else'.");
- return std::unique_ptr<ParseNode>();
- }
- }
- if (has_error())
- return std::unique_ptr<ParseNode>();
- return std::move(condition);
-}
-
-void Parser::TraverseOrder(const ParseNode* root,
- std::vector<const ParseNode*>* pre,
- std::vector<const ParseNode*>* post) {
- if (root) {
- pre->push_back(root);
-
- if (const AccessorNode* accessor = root->AsAccessor()) {
- TraverseOrder(accessor->index(), pre, post);
- TraverseOrder(accessor->member(), pre, post);
- } else if (const BinaryOpNode* binop = root->AsBinaryOp()) {
- TraverseOrder(binop->left(), pre, post);
- TraverseOrder(binop->right(), pre, post);
- } else if (const BlockNode* block = root->AsBlock()) {
- for (const auto& statement : block->statements())
- TraverseOrder(statement.get(), pre, post);
- TraverseOrder(block->End(), pre, post);
- } else if (const ConditionNode* condition = root->AsConditionNode()) {
- TraverseOrder(condition->condition(), pre, post);
- TraverseOrder(condition->if_true(), pre, post);
- TraverseOrder(condition->if_false(), pre, post);
- } else if (const FunctionCallNode* func_call = root->AsFunctionCall()) {
- TraverseOrder(func_call->args(), pre, post);
- TraverseOrder(func_call->block(), pre, post);
- } else if (root->AsIdentifier()) {
- // Nothing.
- } else if (const ListNode* list = root->AsList()) {
- for (const auto& node : list->contents())
- TraverseOrder(node.get(), pre, post);
- TraverseOrder(list->End(), pre, post);
- } else if (root->AsLiteral()) {
- // Nothing.
- } else if (const UnaryOpNode* unaryop = root->AsUnaryOp()) {
- TraverseOrder(unaryop->operand(), pre, post);
- } else if (root->AsBlockComment()) {
- // Nothing.
- } else if (root->AsEnd()) {
- // Nothing.
- } else {
- CHECK(false) << "Unhandled case in TraverseOrder.";
- }
-
- post->push_back(root);
- }
-}
-
-void Parser::AssignComments(ParseNode* file) {
- // Start by generating a pre- and post- order traversal of the tree so we
- // can determine what's before and after comments.
- std::vector<const ParseNode*> pre;
- std::vector<const ParseNode*> post;
- TraverseOrder(file, &pre, &post);
-
- // Assign line comments to syntax immediately following.
- int cur_comment = 0;
- for (auto* node : pre) {
- if (node->GetRange().is_null()) {
- CHECK_EQ(node, file) << "Only expected on top file node";
- continue;
- }
- const Location start = node->GetRange().begin();
- while (cur_comment < static_cast<int>(line_comment_tokens_.size())) {
- if (start.byte() >= line_comment_tokens_[cur_comment].location().byte()) {
- const_cast<ParseNode*>(node)->comments_mutable()->append_before(
- line_comment_tokens_[cur_comment]);
- ++cur_comment;
- } else {
- break;
- }
- }
- }
-
- // Remaining line comments go at end of file.
- for (; cur_comment < static_cast<int>(line_comment_tokens_.size());
- ++cur_comment)
- file->comments_mutable()->append_after(line_comment_tokens_[cur_comment]);
-
- // Assign suffix to syntax immediately before.
- cur_comment = static_cast<int>(suffix_comment_tokens_.size() - 1);
- for (std::vector<const ParseNode*>::const_reverse_iterator i = post.rbegin();
- i != post.rend();
- ++i) {
- // Don't assign suffix comments to the function, list, or block, but instead
- // to the last thing inside.
- if ((*i)->AsFunctionCall() || (*i)->AsList() || (*i)->AsBlock())
- continue;
-
- Location start = (*i)->GetRange().begin();
- Location end = (*i)->GetRange().end();
-
- // Don't assign suffix comments to something that starts on an earlier
- // line, so that in:
- //
- // sources = [ "a",
- // "b" ] # comment
- //
- // it's attached to "b", not sources = [ ... ].
- if (start.line_number() != end.line_number())
- continue;
-
- while (cur_comment >= 0) {
- if (end.byte() <= suffix_comment_tokens_[cur_comment].location().byte()) {
- const_cast<ParseNode*>(*i)->comments_mutable()->append_suffix(
- suffix_comment_tokens_[cur_comment]);
- --cur_comment;
- } else {
- break;
- }
- }
-
- // Suffix comments were assigned in reverse, so if there were multiple on
- // the same node, they need to be reversed.
- if ((*i)->comments() && !(*i)->comments()->suffix().empty())
- const_cast<ParseNode*>(*i)->comments_mutable()->ReverseSuffix();
- }
-}
diff --git a/chromium/tools/gn/parser.h b/chromium/tools/gn/parser.h
deleted file mode 100644
index 69dc8cf604e..00000000000
--- a/chromium/tools/gn/parser.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_PARSER_H_
-#define TOOLS_GN_PARSER_H_
-
-#include <stddef.h>
-
-#include <map>
-#include <memory>
-#include <vector>
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "tools/gn/err.h"
-#include "tools/gn/parse_tree.h"
-
-class Parser;
-typedef std::unique_ptr<ParseNode> (Parser::*PrefixFunc)(const Token& token);
-typedef std::unique_ptr<ParseNode> (
- Parser::*InfixFunc)(std::unique_ptr<ParseNode> left, const Token& token);
-
-extern const char kGrammar_Help[];
-
-struct ParserHelper {
- PrefixFunc prefix;
- InfixFunc infix;
- int precedence;
-};
-
-// Parses a series of tokens. The resulting AST will refer to the tokens passed
-// to the input, so the tokens an the file data they refer to must outlive your
-// use of the ParseNode.
-class Parser {
- public:
- // Will return a null pointer and set the err on error.
- static std::unique_ptr<ParseNode> Parse(const std::vector<Token>& tokens,
- Err* err);
-
- // Alternative to parsing that assumes the input is an expression.
- static std::unique_ptr<ParseNode> ParseExpression(
- const std::vector<Token>& tokens,
- Err* err);
-
- // Alternative to parsing that assumes the input is a literal value.
- static std::unique_ptr<ParseNode> ParseValue(const std::vector<Token>& tokens,
- Err* err);
-
- private:
- // Vector must be valid for lifetime of call.
- Parser(const std::vector<Token>& tokens, Err* err);
- ~Parser();
-
- std::unique_ptr<ParseNode> ParseExpression();
-
- // Parses an expression with the given precedence or higher.
- std::unique_ptr<ParseNode> ParseExpression(int precedence);
-
- // |PrefixFunc|s used in parsing expressions.
- std::unique_ptr<ParseNode> Block(const Token& token);
- std::unique_ptr<ParseNode> Literal(const Token& token);
- std::unique_ptr<ParseNode> Name(const Token& token);
- std::unique_ptr<ParseNode> Group(const Token& token);
- std::unique_ptr<ParseNode> Not(const Token& token);
- std::unique_ptr<ParseNode> List(const Token& token);
- std::unique_ptr<ParseNode> BlockComment(const Token& token);
-
- // |InfixFunc|s used in parsing expressions.
- std::unique_ptr<ParseNode> BinaryOperator(std::unique_ptr<ParseNode> left,
- const Token& token);
- std::unique_ptr<ParseNode> IdentifierOrCall(std::unique_ptr<ParseNode> left,
- const Token& token);
- std::unique_ptr<ParseNode> Assignment(std::unique_ptr<ParseNode> left,
- const Token& token);
- std::unique_ptr<ParseNode> Subscript(std::unique_ptr<ParseNode> left,
- const Token& token);
- std::unique_ptr<ParseNode> DotOperator(std::unique_ptr<ParseNode> left,
- const Token& token);
-
- // Helper to parse a comma separated list, optionally allowing trailing
- // commas (allowed in [] lists, not in function calls).
- std::unique_ptr<ListNode> ParseList(const Token& start_token,
- Token::Type stop_before,
- bool allow_trailing_comma);
-
- std::unique_ptr<ParseNode> ParseFile();
- std::unique_ptr<ParseNode> ParseStatement();
- // Expects to be passed the token corresponding to the '{' and that the
- // current token is the one following the '{'.
- std::unique_ptr<BlockNode> ParseBlock(const Token& begin_brace,
- BlockNode::ResultMode result_mode);
- std::unique_ptr<ParseNode> ParseCondition();
-
- // Generates a pre- and post-order traversal of the tree.
- void TraverseOrder(const ParseNode* root,
- std::vector<const ParseNode*>* pre,
- std::vector<const ParseNode*>* post);
-
- // Attach comments to nearby syntax.
- void AssignComments(ParseNode* file);
-
- bool IsAssignment(const ParseNode* node) const;
- bool IsStatementBreak(Token::Type token_type) const;
-
- bool LookAhead(Token::Type type);
- bool Match(Token::Type type);
- const Token& Consume(Token::Type type, const char* error_message);
- const Token& Consume(Token::Type* types,
- size_t num_types,
- const char* error_message);
- const Token& Consume();
-
- // Call this only if !at_end().
- const Token& cur_token() const { return tokens_[cur_]; }
-
- const Token& cur_or_last_token() const {
- return at_end() ? tokens_[tokens_.size() - 1] : cur_token();
- }
-
- bool done() const { return at_end() || has_error(); }
- bool at_end() const { return cur_ >= tokens_.size(); }
- bool has_error() const { return err_->has_error(); }
-
- std::vector<Token> tokens_;
- std::vector<Token> line_comment_tokens_;
- std::vector<Token> suffix_comment_tokens_;
-
- static ParserHelper expressions_[Token::NUM_TYPES];
-
- Token invalid_token_;
- Err* err_;
-
- // Current index into the tokens.
- size_t cur_;
-
- FRIEND_TEST_ALL_PREFIXES(Parser, BinaryOp);
- FRIEND_TEST_ALL_PREFIXES(Parser, Block);
- FRIEND_TEST_ALL_PREFIXES(Parser, Condition);
- FRIEND_TEST_ALL_PREFIXES(Parser, Expression);
- FRIEND_TEST_ALL_PREFIXES(Parser, FunctionCall);
- FRIEND_TEST_ALL_PREFIXES(Parser, List);
- FRIEND_TEST_ALL_PREFIXES(Parser, ParenExpression);
- FRIEND_TEST_ALL_PREFIXES(Parser, UnaryOp);
-
- DISALLOW_COPY_AND_ASSIGN(Parser);
-};
-
-#endif // TOOLS_GN_PARSER_H_
diff --git a/chromium/tools/gn/parser_fuzzer.cc b/chromium/tools/gn/parser_fuzzer.cc
deleted file mode 100644
index e40da783fe1..00000000000
--- a/chromium/tools/gn/parser_fuzzer.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-
-#include "tools/gn/input_file.h"
-#include "tools/gn/parser.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/tokenizer.h"
-
-namespace {
-
-enum { kMaxContentDepth = 256, kMaxDodgy = 256 };
-
-// Some auto generated input is too unreasonable for fuzzing GN.
-// We see stack overflow when the parser hits really deeply "nested" input.
-// (I.E.: certain input that causes nested parsing function calls).
-//
-// Abstract max limits are undesirable in the release GN code, so some sanity
-// checks in the fuzzer to prevent stack overflow are done here.
-// - 1) Too many opening bracket, paren, or brace in a row.
-// - 2) Too many '!', '<' or '>' operators in a row.
-bool SanityCheckContent(const std::vector<Token>& tokens) {
- int depth = 0;
- int dodgy_count = 0;
- for (const auto& token : tokens) {
- switch (token.type()) {
- case Token::LEFT_PAREN:
- case Token::LEFT_BRACKET:
- case Token::LEFT_BRACE:
- ++depth;
- break;
- case Token::RIGHT_PAREN:
- case Token::RIGHT_BRACKET:
- case Token::RIGHT_BRACE:
- --depth;
- break;
- case Token::BANG:
- case Token::LESS_THAN:
- case Token::GREATER_THAN:
- ++dodgy_count;
- break;
- default:
- break;
- }
- // Bail out as soon as a boundary is hit, inside the loop.
- if (depth >= kMaxContentDepth || dodgy_count >= kMaxDodgy)
- return false;
- }
-
- return true;
-}
-
-} // namespace
-
-extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) {
- SourceFile source;
- InputFile input(source);
- input.SetContents(std::string(reinterpret_cast<const char*>(data), size));
-
- Err err;
- std::vector<Token> tokens = Tokenizer::Tokenize(&input, &err);
- if (!SanityCheckContent(tokens))
- return 0;
-
- if (!err.has_error())
- Parser::Parse(tokens, &err);
-
- return 0;
-}
diff --git a/chromium/tools/gn/parser_unittest.cc b/chromium/tools/gn/parser_unittest.cc
deleted file mode 100644
index 6caeeb40794..00000000000
--- a/chromium/tools/gn/parser_unittest.cc
+++ /dev/null
@@ -1,744 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <iostream>
-#include <sstream>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parser.h"
-#include "tools/gn/tokenizer.h"
-
-namespace {
-
-bool GetTokens(const InputFile* input, std::vector<Token>* result) {
- result->clear();
- Err err;
- *result = Tokenizer::Tokenize(input, &err);
- return !err.has_error();
-}
-
-void DoParserPrintTest(const char* input, const char* expected) {
- std::vector<Token> tokens;
- InputFile input_file(SourceFile("/test"));
- input_file.SetContents(input);
- ASSERT_TRUE(GetTokens(&input_file, &tokens));
-
- Err err;
- std::unique_ptr<ParseNode> result = Parser::Parse(tokens, &err);
- if (!result)
- err.PrintToStdout();
- ASSERT_TRUE(result);
-
- std::ostringstream collector;
- result->Print(collector, 0);
-
- EXPECT_EQ(expected, collector.str());
-}
-
-void DoExpressionPrintTest(const char* input, const char* expected) {
- std::vector<Token> tokens;
- InputFile input_file(SourceFile("/test"));
- input_file.SetContents(input);
- ASSERT_TRUE(GetTokens(&input_file, &tokens));
-
- Err err;
- std::unique_ptr<ParseNode> result = Parser::ParseExpression(tokens, &err);
- ASSERT_TRUE(result);
-
- std::ostringstream collector;
- result->Print(collector, 0);
-
- EXPECT_EQ(expected, collector.str());
-}
-
-// Expects the tokenizer or parser to identify an error at the given line and
-// character.
-void DoParserErrorTest(const char* input, int err_line, int err_char) {
- InputFile input_file(SourceFile("/test"));
- input_file.SetContents(input);
-
- Err err;
- std::vector<Token> tokens = Tokenizer::Tokenize(&input_file, &err);
- if (!err.has_error()) {
- std::unique_ptr<ParseNode> result = Parser::Parse(tokens, &err);
- ASSERT_FALSE(result);
- ASSERT_TRUE(err.has_error());
- }
-
- EXPECT_EQ(err_line, err.location().line_number());
- EXPECT_EQ(err_char, err.location().column_number());
-}
-
-// Expects the tokenizer or parser to identify an error at the given line and
-// character.
-void DoExpressionErrorTest(const char* input, int err_line, int err_char) {
- InputFile input_file(SourceFile("/test"));
- input_file.SetContents(input);
-
- Err err;
- std::vector<Token> tokens = Tokenizer::Tokenize(&input_file, &err);
- if (!err.has_error()) {
- std::unique_ptr<ParseNode> result = Parser::ParseExpression(tokens, &err);
- ASSERT_FALSE(result);
- ASSERT_TRUE(err.has_error());
- }
-
- EXPECT_EQ(err_line, err.location().line_number());
- EXPECT_EQ(err_char, err.location().column_number());
-}
-
-} // namespace
-
-TEST(Parser, Literal) {
- DoExpressionPrintTest("5", "LITERAL(5)\n");
- DoExpressionPrintTest("\"stuff\"", "LITERAL(\"stuff\")\n");
-}
-
-TEST(Parser, BinaryOp) {
- // TODO(scottmg): The tokenizer is dumb, and treats "5-1" as two integers,
- // not a binary operator between two positive integers.
- DoExpressionPrintTest("5 - 1",
- "BINARY(-)\n"
- " LITERAL(5)\n"
- " LITERAL(1)\n");
- DoExpressionPrintTest("5+1",
- "BINARY(+)\n"
- " LITERAL(5)\n"
- " LITERAL(1)\n");
- DoExpressionPrintTest("5 - 1 - 2",
- "BINARY(-)\n"
- " BINARY(-)\n"
- " LITERAL(5)\n"
- " LITERAL(1)\n"
- " LITERAL(2)\n");
-}
-
-TEST(Parser, FunctionCall) {
- DoExpressionPrintTest("foo()",
- "FUNCTION(foo)\n"
- " LIST\n");
- DoExpressionPrintTest("blah(1, 2)",
- "FUNCTION(blah)\n"
- " LIST\n"
- " LITERAL(1)\n"
- " LITERAL(2)\n");
- DoExpressionErrorTest("foo(1, 2,)", 1, 10);
- DoExpressionErrorTest("foo(1 2)", 1, 7);
-}
-
-TEST(Parser, ParenExpression) {
- const char* input = "(foo(1)) + (a + (b - c) + d)";
- const char* expected =
- "BINARY(+)\n"
- " FUNCTION(foo)\n"
- " LIST\n"
- " LITERAL(1)\n"
- " BINARY(+)\n"
- " BINARY(+)\n"
- " IDENTIFIER(a)\n"
- " BINARY(-)\n"
- " IDENTIFIER(b)\n"
- " IDENTIFIER(c)\n"
- " IDENTIFIER(d)\n";
- DoExpressionPrintTest(input, expected);
- DoExpressionErrorTest("(a +", 1, 4);
-}
-
-TEST(Parser, OrderOfOperationsLeftAssociative) {
- const char* input = "5 - 1 - 2\n";
- const char* expected =
- "BINARY(-)\n"
- " BINARY(-)\n"
- " LITERAL(5)\n"
- " LITERAL(1)\n"
- " LITERAL(2)\n";
- DoExpressionPrintTest(input, expected);
-}
-
-TEST(Parser, OrderOfOperationsEqualityBoolean) {
- const char* input =
- "if (a == \"b\" && is_stuff) {\n"
- " print(\"hai\")\n"
- "}\n";
- const char* expected =
- "BLOCK\n"
- " CONDITION\n"
- " BINARY(&&)\n"
- " BINARY(==)\n"
- " IDENTIFIER(a)\n"
- " LITERAL(\"b\")\n"
- " IDENTIFIER(is_stuff)\n"
- " BLOCK\n"
- " FUNCTION(print)\n"
- " LIST\n"
- " LITERAL(\"hai\")\n";
- DoParserPrintTest(input, expected);
-}
-
-TEST(Parser, UnaryOp) {
- DoExpressionPrintTest("!foo",
- "UNARY(!)\n"
- " IDENTIFIER(foo)\n");
-
- // No contents for binary operator.
- DoExpressionErrorTest("a = !", 1, 5);
-}
-
-TEST(Parser, List) {
- DoExpressionPrintTest("[]", "LIST\n");
- DoExpressionPrintTest("[1,asd,]",
- "LIST\n"
- " LITERAL(1)\n"
- " IDENTIFIER(asd)\n");
- DoExpressionPrintTest("[1, 2+3 - foo]",
- "LIST\n"
- " LITERAL(1)\n"
- " BINARY(-)\n"
- " BINARY(+)\n"
- " LITERAL(2)\n"
- " LITERAL(3)\n"
- " IDENTIFIER(foo)\n");
- DoExpressionPrintTest("[1,\n2,\n 3,\n 4]",
- "LIST\n"
- " LITERAL(1)\n"
- " LITERAL(2)\n"
- " LITERAL(3)\n"
- " LITERAL(4)\n");
-
- DoExpressionErrorTest("[a, 2+,]", 1, 7);
- DoExpressionErrorTest("[,]", 1, 2);
- DoExpressionErrorTest("[a,,]", 1, 4);
-}
-
-TEST(Parser, Assignment) {
- DoParserPrintTest("a=2",
- "BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(a)\n"
- " LITERAL(2)\n");
-
- DoExpressionErrorTest("a = ", 1, 3);
-}
-
-TEST(Parser, Accessor) {
- // Accessor indexing.
- DoParserPrintTest("a=b[c+2]",
- "BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(a)\n"
- " ACCESSOR\n"
- " b\n" // AccessorNode is a bit weird in that it holds
- // a Token, not a ParseNode for the base.
- " BINARY(+)\n"
- " IDENTIFIER(c)\n"
- " LITERAL(2)\n");
- DoParserErrorTest("a = b[1][0]", 1, 5);
-
- // Member accessors.
- DoParserPrintTest("a=b.c+2",
- "BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(a)\n"
- " BINARY(+)\n"
- " ACCESSOR\n"
- " b\n"
- " IDENTIFIER(c)\n"
- " LITERAL(2)\n");
- DoParserPrintTest("a.b = 5",
- "BLOCK\n"
- " BINARY(=)\n"
- " ACCESSOR\n"
- " a\n"
- " IDENTIFIER(b)\n"
- " LITERAL(5)\n");
- DoParserErrorTest("a = b.c.d", 1, 6); // Can't nest accessors (currently).
-
- // Error at the bad dot in the RHS, not the + operator (crbug.com/472038).
- DoParserErrorTest("foo(a + b.c.d)", 1, 10);
-}
-
-TEST(Parser, Condition) {
- DoParserPrintTest("if(1) { a = 2 }",
- "BLOCK\n"
- " CONDITION\n"
- " LITERAL(1)\n"
- " BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(a)\n"
- " LITERAL(2)\n");
-
- DoParserPrintTest("if(1) { a = 2 } else if (0) { a = 3 } else { a = 4 }",
- "BLOCK\n"
- " CONDITION\n"
- " LITERAL(1)\n"
- " BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(a)\n"
- " LITERAL(2)\n"
- " CONDITION\n"
- " LITERAL(0)\n"
- " BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(a)\n"
- " LITERAL(3)\n"
- " BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(a)\n"
- " LITERAL(4)\n");
-}
-
-TEST(Parser, OnlyCallAndAssignInBody) {
- DoParserErrorTest("[]", 1, 2);
- DoParserErrorTest("3 + 4", 1, 5);
- DoParserErrorTest("6 - 7", 1, 5);
- DoParserErrorTest("if (1) { 5 } else { print(4) }", 1, 12);
-}
-
-TEST(Parser, NoAssignmentInCondition) {
- DoParserErrorTest("if (a=2) {}", 1, 5);
-}
-
-TEST(Parser, CompleteFunction) {
- const char* input =
- "cc_test(\"foo\") {\n"
- " sources = [\n"
- " \"foo.cc\",\n"
- " \"foo.h\"\n"
- " ]\n"
- " dependencies = [\n"
- " \"base\"\n"
- " ]\n"
- "}\n";
- const char* expected =
- "BLOCK\n"
- " FUNCTION(cc_test)\n"
- " LIST\n"
- " LITERAL(\"foo\")\n"
- " BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(sources)\n"
- " LIST\n"
- " LITERAL(\"foo.cc\")\n"
- " LITERAL(\"foo.h\")\n"
- " BINARY(=)\n"
- " IDENTIFIER(dependencies)\n"
- " LIST\n"
- " LITERAL(\"base\")\n";
- DoParserPrintTest(input, expected);
-}
-
-TEST(Parser, FunctionWithConditional) {
- const char* input =
- "cc_test(\"foo\") {\n"
- " sources = [\"foo.cc\"]\n"
- " if (OS == \"mac\") {\n"
- " sources += \"bar.cc\"\n"
- " } else if (OS == \"win\") {\n"
- " sources -= [\"asd.cc\", \"foo.cc\"]\n"
- " } else {\n"
- " dependencies += [\"bar.cc\"]\n"
- " }\n"
- "}\n";
- const char* expected =
- "BLOCK\n"
- " FUNCTION(cc_test)\n"
- " LIST\n"
- " LITERAL(\"foo\")\n"
- " BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(sources)\n"
- " LIST\n"
- " LITERAL(\"foo.cc\")\n"
- " CONDITION\n"
- " BINARY(==)\n"
- " IDENTIFIER(OS)\n"
- " LITERAL(\"mac\")\n"
- " BLOCK\n"
- " BINARY(+=)\n"
- " IDENTIFIER(sources)\n"
- " LITERAL(\"bar.cc\")\n"
- " CONDITION\n"
- " BINARY(==)\n"
- " IDENTIFIER(OS)\n"
- " LITERAL(\"win\")\n"
- " BLOCK\n"
- " BINARY(-=)\n"
- " IDENTIFIER(sources)\n"
- " LIST\n"
- " LITERAL(\"asd.cc\")\n"
- " LITERAL(\"foo.cc\")\n"
- " BLOCK\n"
- " BINARY(+=)\n"
- " IDENTIFIER(dependencies)\n"
- " LIST\n"
- " LITERAL(\"bar.cc\")\n";
- DoParserPrintTest(input, expected);
-}
-
-TEST(Parser, UnterminatedBlock) {
- DoParserErrorTest("stuff() {", 1, 9);
-}
-
-TEST(Parser, BadlyTerminatedNumber) {
- DoParserErrorTest("1234z", 1, 5);
-}
-
-TEST(Parser, NewlinesInUnusualPlaces) {
- DoParserPrintTest(
- "if\n"
- "(\n"
- "a\n"
- ")\n"
- "{\n"
- "}\n",
- "BLOCK\n"
- " CONDITION\n"
- " IDENTIFIER(a)\n"
- " BLOCK\n");
-}
-
-TEST(Parser, NewlinesInUnusualPlaces2) {
- DoParserPrintTest(
- "a\n=\n2\n",
- "BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(a)\n"
- " LITERAL(2)\n");
- DoParserPrintTest(
- "x =\ny if\n(1\n) {}",
- "BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(x)\n"
- " IDENTIFIER(y)\n"
- " CONDITION\n"
- " LITERAL(1)\n"
- " BLOCK\n");
- DoParserPrintTest(
- "x = 3\n+2",
- "BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(x)\n"
- " BINARY(+)\n"
- " LITERAL(3)\n"
- " LITERAL(2)\n"
- );
-}
-
-TEST(Parser, NewlineBeforeSubscript) {
- const char* input = "a = b[1]";
- const char* input_with_newline = "a = b\n[1]";
- const char* expected =
- "BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(a)\n"
- " ACCESSOR\n"
- " b\n"
- " LITERAL(1)\n";
- DoParserPrintTest(
- input,
- expected);
- DoParserPrintTest(
- input_with_newline,
- expected);
-}
-
-TEST(Parser, SequenceOfExpressions) {
- DoParserPrintTest(
- "a = 1 b = 2",
- "BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(a)\n"
- " LITERAL(1)\n"
- " BINARY(=)\n"
- " IDENTIFIER(b)\n"
- " LITERAL(2)\n");
-}
-
-TEST(Parser, BlockAfterFunction) {
- const char* input = "func(\"stuff\") {\n}";
- // TODO(scottmg): Do we really want these to mean different things?
- const char* input_with_newline = "func(\"stuff\")\n{\n}";
- const char* expected =
- "BLOCK\n"
- " FUNCTION(func)\n"
- " LIST\n"
- " LITERAL(\"stuff\")\n"
- " BLOCK\n";
- DoParserPrintTest(input, expected);
- DoParserPrintTest(input_with_newline, expected);
-}
-
-TEST(Parser, LongExpression) {
- const char* input = "a = b + c && d || e";
- const char* expected =
- "BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(a)\n"
- " BINARY(||)\n"
- " BINARY(&&)\n"
- " BINARY(+)\n"
- " IDENTIFIER(b)\n"
- " IDENTIFIER(c)\n"
- " IDENTIFIER(d)\n"
- " IDENTIFIER(e)\n";
- DoParserPrintTest(input, expected);
-}
-
-TEST(Parser, CommentsStandalone) {
- const char* input =
- "# Toplevel comment.\n"
- "\n"
- "executable(\"wee\") {}\n";
- const char* expected =
- "BLOCK\n"
- " BLOCK_COMMENT(# Toplevel comment.)\n"
- " FUNCTION(executable)\n"
- " LIST\n"
- " LITERAL(\"wee\")\n"
- " BLOCK\n";
- DoParserPrintTest(input, expected);
-}
-
-TEST(Parser, CommentsStandaloneEof) {
- const char* input =
- "executable(\"wee\") {}\n"
- "# EOF comment.\n";
- const char* expected =
- "BLOCK\n"
- " +AFTER_COMMENT(\"# EOF comment.\")\n"
- " FUNCTION(executable)\n"
- " LIST\n"
- " LITERAL(\"wee\")\n"
- " BLOCK\n";
- DoParserPrintTest(input, expected);
-}
-
-TEST(Parser, CommentsLineAttached) {
- const char* input =
- "executable(\"wee\") {\n"
- " # Some sources.\n"
- " sources = [\n"
- " \"stuff.cc\",\n"
- " \"things.cc\",\n"
- " # This file is special or something.\n"
- " \"another.cc\",\n"
- " ]\n"
- "}\n";
- const char* expected =
- "BLOCK\n"
- " FUNCTION(executable)\n"
- " LIST\n"
- " LITERAL(\"wee\")\n"
- " BLOCK\n"
- " BINARY(=)\n"
- " +BEFORE_COMMENT(\"# Some sources.\")\n"
- " IDENTIFIER(sources)\n"
- " LIST\n"
- " LITERAL(\"stuff.cc\")\n"
- " LITERAL(\"things.cc\")\n"
- " LITERAL(\"another.cc\")\n"
- " +BEFORE_COMMENT(\"# This file is special or something.\")\n";
- DoParserPrintTest(input, expected);
-}
-
-TEST(Parser, CommentsSuffix) {
- const char* input =
- "executable(\"wee\") { # This is some stuff.\n"
- "sources = [ \"a.cc\" # And another comment here.\n"
- "] }";
- const char* expected =
- "BLOCK\n"
- " FUNCTION(executable)\n"
- " LIST\n"
- " LITERAL(\"wee\")\n"
- " END())\n"
- " +SUFFIX_COMMENT(\"# This is some stuff.\")\n"
- " BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(sources)\n"
- " LIST\n"
- " LITERAL(\"a.cc\")\n"
- " +SUFFIX_COMMENT(\"# And another comment here.\")\n";
- DoParserPrintTest(input, expected);
-}
-
-TEST(Parser, CommentsSuffixDifferentLine) {
- const char* input =
- "executable(\"wee\") {\n"
- " sources = [ \"a\",\n"
- " \"b\" ] # Comment\n"
- "}\n";
- const char* expected =
- "BLOCK\n"
- " FUNCTION(executable)\n"
- " LIST\n"
- " LITERAL(\"wee\")\n"
- " BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(sources)\n"
- " LIST\n"
- " LITERAL(\"a\")\n"
- " LITERAL(\"b\")\n"
- " END(])\n"
- " +SUFFIX_COMMENT(\"# Comment\")\n";
- DoParserPrintTest(input, expected);
-}
-
-TEST(Parser, CommentsSuffixMultiple) {
- const char* input =
- "executable(\"wee\") {\n"
- " sources = [\n"
- " \"a\", # This is a comment,\n"
- " # and some more,\n" // Note that this is aligned with above.
- " # then the end.\n"
- " ]\n"
- "}\n";
- const char* expected =
- "BLOCK\n"
- " FUNCTION(executable)\n"
- " LIST\n"
- " LITERAL(\"wee\")\n"
- " BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(sources)\n"
- " LIST\n"
- " LITERAL(\"a\")\n"
- " +SUFFIX_COMMENT(\"# This is a comment,\")\n"
- " +SUFFIX_COMMENT(\"# and some more,\")\n"
- " +SUFFIX_COMMENT(\"# then the end.\")\n";
- DoParserPrintTest(input, expected);
-}
-
-TEST(Parser, CommentsConnectedInList) {
- const char* input =
- "defines = [\n"
- "\n"
- " # Connected comment.\n"
- " \"WEE\",\n"
- " \"BLORPY\",\n"
- "]\n";
- const char* expected =
- "BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(defines)\n"
- " LIST\n"
- " LITERAL(\"WEE\")\n"
- " +BEFORE_COMMENT(\"# Connected comment.\")\n"
- " LITERAL(\"BLORPY\")\n";
- DoParserPrintTest(input, expected);
-}
-
-TEST(Parser, CommentsAtEndOfBlock) {
- const char* input =
- "if (is_win) {\n"
- " sources = [\"a.cc\"]\n"
- " # Some comment at end.\n"
- "}\n";
- const char* expected =
- "BLOCK\n"
- " CONDITION\n"
- " IDENTIFIER(is_win)\n"
- " BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(sources)\n"
- " LIST\n"
- " LITERAL(\"a.cc\")\n"
- " END(})\n"
- " +BEFORE_COMMENT(\"# Some comment at end.\")\n";
- DoParserPrintTest(input, expected);
-}
-
-// TODO(scottmg): I could be convinced this is incorrect. It's not clear to me
-// which thing this comment is intended to be attached to.
-TEST(Parser, CommentsEndOfBlockSingleLine) {
- const char* input =
- "defines = [ # EOL defines.\n"
- "]\n";
- const char* expected =
- "BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(defines)\n"
- " +SUFFIX_COMMENT(\"# EOL defines.\")\n"
- " LIST\n";
- DoParserPrintTest(input, expected);
-}
-
-TEST(Parser, HangingIf) {
- DoParserErrorTest("if", 1, 1);
-}
-
-TEST(Parser, NegatingList) {
- DoParserErrorTest("executable(\"wee\") { sources =- [ \"foo.cc\" ] }", 1, 30);
-}
-
-TEST(Parser, ConditionNoBracesIf) {
- DoParserErrorTest(
- "if (true)\n"
- " foreach(foo, []) {}\n"
- "else {\n"
- " foreach(bar, []) {}\n"
- "}\n",
- 2, 3);
-}
-
-TEST(Parser, ConditionNoBracesElse) {
- DoParserErrorTest(
- "if (true) {\n"
- " foreach(foo, []) {}\n"
- "} else\n"
- " foreach(bar, []) {}\n",
- 4, 3);
-}
-
-TEST(Parser, ConditionNoBracesElseIf) {
- DoParserErrorTest(
- "if (true) {\n"
- " foreach(foo, []) {}\n"
- "} else if (true)\n"
- " foreach(bar, []) {}\n",
- 4, 3);
-}
-
-// Disallow standalone {} for introducing new scopes. These are ambiguous with
-// target declarations (e.g. is:
-// foo("bar") {}
-// a function with an associated block, or a standalone function with a
-// freestanding block.
-TEST(Parser, StandaloneBlock) {
- // The error is reported at the end of the block when nothing is done
- // with it. If we had said "a = { ..." then it would have been OK.
- DoParserErrorTest(
- "if (true) {\n"
- "}\n"
- "{\n"
- " assert(false)\n"
- "}\n",
- 5, 1);
-}
-
-TEST(Parser, BlockValues) {
- const char* input =
- "print({a = 1 b = 2}, 3)\n"
- "a = { b = \"asd\" }";
- const char* expected =
- "BLOCK\n"
- " FUNCTION(print)\n"
- " LIST\n"
- " BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(a)\n"
- " LITERAL(1)\n"
- " BINARY(=)\n"
- " IDENTIFIER(b)\n"
- " LITERAL(2)\n"
- " LITERAL(3)\n"
- " BINARY(=)\n"
- " IDENTIFIER(a)\n"
- " BLOCK\n"
- " BINARY(=)\n"
- " IDENTIFIER(b)\n"
- " LITERAL(\"asd\")\n";
- DoParserPrintTest(input, expected);
-}
diff --git a/chromium/tools/gn/path_output.cc b/chromium/tools/gn/path_output.cc
deleted file mode 100644
index 61c4ee0a297..00000000000
--- a/chromium/tools/gn/path_output.cc
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/path_output.h"
-
-#include "base/strings/string_util.h"
-#include "build/build_config.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/output_file.h"
-#include "tools/gn/string_utils.h"
-
-PathOutput::PathOutput(const SourceDir& current_dir,
- const base::StringPiece& source_root,
- EscapingMode escaping)
- : current_dir_(current_dir) {
- inverse_current_dir_ = RebasePath("//", current_dir, source_root);
- if (!EndsWithSlash(inverse_current_dir_))
- inverse_current_dir_.push_back('/');
- options_.mode = escaping;
-}
-
-PathOutput::~PathOutput() = default;
-
-void PathOutput::WriteFile(std::ostream& out, const SourceFile& file) const {
- WritePathStr(out, file.value());
-}
-
-void PathOutput::WriteDir(std::ostream& out,
- const SourceDir& dir,
- DirSlashEnding slash_ending) const {
- if (dir.value() == "/") {
- // Writing system root is always a slash (this will normally only come up
- // on Posix systems).
- if (slash_ending == DIR_NO_LAST_SLASH)
- out << "/.";
- else
- out << "/";
- } else if (dir.value() == "//") {
- // Writing out the source root.
- if (slash_ending == DIR_NO_LAST_SLASH) {
- // The inverse_current_dir_ will contain a [back]slash at the end, so we
- // can't just write it out.
- if (inverse_current_dir_.empty()) {
- out << ".";
- } else {
- out.write(inverse_current_dir_.c_str(),
- inverse_current_dir_.size() - 1);
- }
- } else {
- if (inverse_current_dir_.empty())
- out << "./";
- else
- out << inverse_current_dir_;
- }
- } else if (dir == current_dir_) {
- // Writing the same directory. This needs special handling here since
- // we need to output something else other than the input.
- if (slash_ending == DIR_INCLUDE_LAST_SLASH)
- out << "./";
- else
- out << ".";
- } else if (slash_ending == DIR_INCLUDE_LAST_SLASH) {
- WritePathStr(out, dir.value());
- } else {
- // DIR_NO_LAST_SLASH mode, just trim the last char.
- WritePathStr(out, base::StringPiece(dir.value().data(),
- dir.value().size() - 1));
- }
-}
-
-void PathOutput::WriteFile(std::ostream& out, const OutputFile& file) const {
- // Here we assume that the path is already preprocessed.
- EscapeStringToStream(out, file.value(), options_);
-}
-
-void PathOutput::WriteFiles(std::ostream& out,
- const std::vector<OutputFile>& files) const {
- for (const auto& file : files) {
- out << " ";
- WriteFile(out, file);
- }
-}
-
-void PathOutput::WriteFiles(std::ostream& out,
- const UniqueVector<OutputFile>& files) const {
- for (const auto& file : files) {
- out << " ";
- WriteFile(out, file);
- }
-}
-
-void PathOutput::WriteDir(std::ostream& out,
- const OutputFile& file,
- DirSlashEnding slash_ending) const {
- DCHECK(file.value().empty() ||
- file.value()[file.value().size() - 1] == '/');
-
- switch (slash_ending) {
- case DIR_INCLUDE_LAST_SLASH:
- EscapeStringToStream(out, file.value(), options_);
- break;
- case DIR_NO_LAST_SLASH:
- if (!file.value().empty() &&
- file.value()[file.value().size() - 1] == '/') {
- // Trim trailing slash.
- EscapeStringToStream(
- out,
- base::StringPiece(file.value().data(), file.value().size() - 1),
- options_);
- } else {
- // Doesn't end with a slash, write the whole thing.
- EscapeStringToStream(out, file.value(), options_);
- }
- break;
- }
-}
-
-void PathOutput::WriteFile(std::ostream& out,
- const base::FilePath& file) const {
- // Assume native file paths are always absolute.
- EscapeStringToStream(out, FilePathToUTF8(file), options_);
-}
-
-void PathOutput::WriteSourceRelativeString(
- std::ostream& out,
- const base::StringPiece& str) const {
- if (options_.mode == ESCAPE_NINJA_COMMAND) {
- // Shell escaping needs an intermediate string since it may end up
- // quoting the whole thing.
- std::string intermediate;
- intermediate.reserve(inverse_current_dir_.size() + str.size());
- intermediate.assign(inverse_current_dir_.c_str(),
- inverse_current_dir_.size());
- intermediate.append(str.data(), str.size());
-
- EscapeStringToStream(out,
- base::StringPiece(intermediate.c_str(), intermediate.size()),
- options_);
- } else {
- // Ninja (and none) escaping can avoid the intermediate string and
- // reprocessing of the inverse_current_dir_.
- out << inverse_current_dir_;
- EscapeStringToStream(out, str, options_);
- }
-}
-
-void PathOutput::WritePathStr(std::ostream& out,
- const base::StringPiece& str) const {
- DCHECK(str.size() > 0 && str[0] == '/');
-
- if (str.substr(0, current_dir_.value().size()) ==
- base::StringPiece(current_dir_.value())) {
- // The current dir is a prefix of the output file, so we can strip the
- // prefix and write out the result.
- EscapeStringToStream(out, str.substr(current_dir_.value().size()),
- options_);
- } else if (str.size() >= 2 && str[1] == '/') {
- WriteSourceRelativeString(out, str.substr(2));
- } else {
- // Input begins with one slash, don't write the current directory since
- // it's system-absolute.
-#if defined(OS_WIN)
- // On Windows, trim the leading slash, since the input for absolute
- // paths will look like "/C:/foo/bar.txt".
- EscapeStringToStream(out, str.substr(1), options_);
-#else
- EscapeStringToStream(out, str, options_);
-#endif
- }
-}
diff --git a/chromium/tools/gn/path_output.h b/chromium/tools/gn/path_output.h
deleted file mode 100644
index ca72948ca5b..00000000000
--- a/chromium/tools/gn/path_output.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_PATH_OUTPUT_H_
-#define TOOLS_GN_PATH_OUTPUT_H_
-
-#include <iosfwd>
-#include <string>
-
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-#include "tools/gn/escape.h"
-#include "tools/gn/source_dir.h"
-#include "tools/gn/unique_vector.h"
-
-class OutputFile;
-class SourceFile;
-
-namespace base {
-class FilePath;
-}
-
-// Writes file names to streams assuming a certain input directory and
-// escaping rules. This gives us a central place for managing this state.
-class PathOutput {
- public:
- // Controls whether writing directory names include the trailing slash.
- // Often we don't want the trailing slash when writing out to a command line,
- // especially on Windows where it's a backslash and might be interpreted as
- // escaping the thing following it.
- enum DirSlashEnding {
- DIR_INCLUDE_LAST_SLASH,
- DIR_NO_LAST_SLASH,
- };
-
- PathOutput(const SourceDir& current_dir, const base::StringPiece& source_root,
- EscapingMode escaping);
- ~PathOutput();
-
- // Read-only since inverse_current_dir_ is computed depending on this.
- EscapingMode escaping_mode() const { return options_.mode; }
-
- const SourceDir& current_dir() const { return current_dir_; }
-
- // Getter/setters for flags inside the escape options.
- bool inhibit_quoting() const { return options_.inhibit_quoting; }
- void set_inhibit_quoting(bool iq) { options_.inhibit_quoting = iq; }
- void set_escape_platform(EscapingPlatform p) { options_.platform = p; }
-
- void WriteFile(std::ostream& out, const SourceFile& file) const;
- void WriteFile(std::ostream& out, const OutputFile& file) const;
- void WriteFile(std::ostream& out, const base::FilePath& file) const;
-
- // Writes the given OutputFiles with spaces separating them. This will also
- // write an initial space before the first item.
- void WriteFiles(std::ostream& out,
- const std::vector<OutputFile>& files) const;
- void WriteFiles(std::ostream& out,
- const UniqueVector<OutputFile>& files) const;
-
- // This variant assumes the dir ends in a trailing slash or is empty.
- void WriteDir(std::ostream& out,
- const SourceDir& dir,
- DirSlashEnding slash_ending) const;
-
- void WriteDir(std::ostream& out,
- const OutputFile& file,
- DirSlashEnding slash_ending) const;
-
- // Backend for WriteFile and WriteDir. This appends the given file or
- // directory string to the file.
- void WritePathStr(std::ostream& out, const base::StringPiece& str) const;
-
- private:
- // Takes the given string and writes it out, appending to the inverse
- // current dir. This assumes leading slashes have been trimmed.
- void WriteSourceRelativeString(std::ostream& out,
- const base::StringPiece& str) const;
-
- SourceDir current_dir_;
-
- // Uses system slashes if convert_slashes_to_system_.
- std::string inverse_current_dir_;
-
- // Since the inverse_current_dir_ depends on some of these, we don't expose
- // this directly to modification.
- EscapeOptions options_;
-};
-
-#endif // TOOLS_GN_PATH_OUTPUT_H_
diff --git a/chromium/tools/gn/path_output_unittest.cc b/chromium/tools/gn/path_output_unittest.cc
deleted file mode 100644
index 6a7da19b94e..00000000000
--- a/chromium/tools/gn/path_output_unittest.cc
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <sstream>
-
-#include "base/files/file_path.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/output_file.h"
-#include "tools/gn/path_output.h"
-#include "tools/gn/source_dir.h"
-#include "tools/gn/source_file.h"
-
-TEST(PathOutput, Basic) {
- SourceDir build_dir("//out/Debug/");
- base::StringPiece source_root("/source/root");
- PathOutput writer(build_dir, source_root, ESCAPE_NONE);
- {
- // Normal source-root path.
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("//foo/bar.cc"));
- EXPECT_EQ("../../foo/bar.cc", out.str());
- }
- {
- // File in the root dir.
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("//foo.cc"));
- EXPECT_EQ("../../foo.cc", out.str());
- }
- {
- // Files in the output dir.
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("//out/Debug/foo.cc"));
- out << " ";
- writer.WriteFile(out, SourceFile("//out/Debug/bar/baz.cc"));
- EXPECT_EQ("foo.cc bar/baz.cc", out.str());
- }
-#if defined(OS_WIN)
- {
- // System-absolute path.
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("/C:/foo/bar.cc"));
- EXPECT_EQ("C:/foo/bar.cc", out.str());
- }
-#else
- {
- // System-absolute path.
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("/foo/bar.cc"));
- EXPECT_EQ("/foo/bar.cc", out.str());
- }
-#endif
-}
-
-// Same as basic but the output dir is the root.
-TEST(PathOutput, BasicInRoot) {
- SourceDir build_dir("//");
- base::StringPiece source_root("/source/root");
- PathOutput writer(build_dir, source_root, ESCAPE_NONE);
- {
- // Normal source-root path.
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("//foo/bar.cc"));
- EXPECT_EQ("foo/bar.cc", out.str());
- }
- {
- // File in the root dir.
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("//foo.cc"));
- EXPECT_EQ("foo.cc", out.str());
- }
-}
-
-TEST(PathOutput, NinjaEscaping) {
- SourceDir build_dir("//out/Debug/");
- base::StringPiece source_root("/source/root");
- PathOutput writer(build_dir, source_root, ESCAPE_NINJA);
- {
- // Spaces and $ in filenames.
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("//foo/foo bar$.cc"));
- EXPECT_EQ("../../foo/foo$ bar$$.cc", out.str());
- }
- {
- // Not other weird stuff
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("//foo/\"foo\".cc"));
- EXPECT_EQ("../../foo/\"foo\".cc", out.str());
- }
-}
-
-TEST(PathOutput, NinjaForkEscaping) {
- SourceDir build_dir("//out/Debug/");
- base::StringPiece source_root("/source/root");
- PathOutput writer(build_dir, source_root, ESCAPE_NINJA_COMMAND);
-
- // Spaces in filenames should get quoted on Windows.
- writer.set_escape_platform(ESCAPE_PLATFORM_WIN);
- {
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("//foo/foo bar.cc"));
- EXPECT_EQ("\"../../foo/foo$ bar.cc\"", out.str());
- }
-
- // Spaces in filenames should get escaped on Posix.
- writer.set_escape_platform(ESCAPE_PLATFORM_POSIX);
- {
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("//foo/foo bar.cc"));
- EXPECT_EQ("../../foo/foo\\$ bar.cc", out.str());
- }
-
- // Quotes should get blackslash-escaped on Windows and Posix.
- writer.set_escape_platform(ESCAPE_PLATFORM_WIN);
- {
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("//foo/\"foobar\".cc"));
- // Our Windows code currently quotes the whole thing in this case for
- // code simplicity, even though it's strictly unnecessary. This might
- // change in the future.
- EXPECT_EQ("\"../../foo/\\\"foobar\\\".cc\"", out.str());
- }
- writer.set_escape_platform(ESCAPE_PLATFORM_POSIX);
- {
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("//foo/\"foobar\".cc"));
- EXPECT_EQ("../../foo/\\\"foobar\\\".cc", out.str());
- }
-
- // Backslashes should get escaped on non-Windows and preserved on Windows.
- writer.set_escape_platform(ESCAPE_PLATFORM_WIN);
- {
- std::ostringstream out;
- writer.WriteFile(out, OutputFile("foo\\bar.cc"));
- EXPECT_EQ("foo\\bar.cc", out.str());
- }
- writer.set_escape_platform(ESCAPE_PLATFORM_POSIX);
- {
- std::ostringstream out;
- writer.WriteFile(out, OutputFile("foo\\bar.cc"));
- EXPECT_EQ("foo\\\\bar.cc", out.str());
- }
-}
-
-TEST(PathOutput, InhibitQuoting) {
- SourceDir build_dir("//out/Debug/");
- base::StringPiece source_root("/source/root");
- PathOutput writer(build_dir, source_root, ESCAPE_NINJA_COMMAND);
- writer.set_inhibit_quoting(true);
-
- writer.set_escape_platform(ESCAPE_PLATFORM_WIN);
- {
- // We should get unescaped spaces in the output with no quotes.
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("//foo/foo bar.cc"));
- EXPECT_EQ("../../foo/foo$ bar.cc", out.str());
- }
-
- writer.set_escape_platform(ESCAPE_PLATFORM_POSIX);
- {
- // Escapes the space.
- std::ostringstream out;
- writer.WriteFile(out, SourceFile("//foo/foo bar.cc"));
- EXPECT_EQ("../../foo/foo\\$ bar.cc", out.str());
- }
-}
-
-TEST(PathOutput, WriteDir) {
- {
- SourceDir build_dir("//out/Debug/");
- base::StringPiece source_root("/source/root");
- PathOutput writer(build_dir, source_root, ESCAPE_NINJA);
- {
- std::ostringstream out;
- writer.WriteDir(out, SourceDir("//foo/bar/"),
- PathOutput::DIR_INCLUDE_LAST_SLASH);
- EXPECT_EQ("../../foo/bar/", out.str());
- }
- {
- std::ostringstream out;
- writer.WriteDir(out, SourceDir("//foo/bar/"),
- PathOutput::DIR_NO_LAST_SLASH);
- EXPECT_EQ("../../foo/bar", out.str());
- }
-
- // Output source root dir.
- {
- std::ostringstream out;
- writer.WriteDir(out, SourceDir("//"),
- PathOutput::DIR_INCLUDE_LAST_SLASH);
- EXPECT_EQ("../../", out.str());
- }
- {
- std::ostringstream out;
- writer.WriteDir(out, SourceDir("//"),
- PathOutput::DIR_NO_LAST_SLASH);
- EXPECT_EQ("../..", out.str());
- }
-
- // Output system root dir.
- {
- std::ostringstream out;
- writer.WriteDir(out, SourceDir("/"),
- PathOutput::DIR_INCLUDE_LAST_SLASH);
- EXPECT_EQ("/", out.str());
- }
- {
- std::ostringstream out;
- writer.WriteDir(out, SourceDir("/"),
- PathOutput::DIR_INCLUDE_LAST_SLASH);
- EXPECT_EQ("/", out.str());
- }
- {
- std::ostringstream out;
- writer.WriteDir(out, SourceDir("/"),
- PathOutput::DIR_NO_LAST_SLASH);
- EXPECT_EQ("/.", out.str());
- }
-
- // Output inside current dir.
- {
- std::ostringstream out;
- writer.WriteDir(out, SourceDir("//out/Debug/"),
- PathOutput::DIR_INCLUDE_LAST_SLASH);
- EXPECT_EQ("./", out.str());
- }
- {
- std::ostringstream out;
- writer.WriteDir(out, SourceDir("//out/Debug/"),
- PathOutput::DIR_NO_LAST_SLASH);
- EXPECT_EQ(".", out.str());
- }
- {
- std::ostringstream out;
- writer.WriteDir(out, SourceDir("//out/Debug/foo/"),
- PathOutput::DIR_INCLUDE_LAST_SLASH);
- EXPECT_EQ("foo/", out.str());
- }
- {
- std::ostringstream out;
- writer.WriteDir(out, SourceDir("//out/Debug/foo/"),
- PathOutput::DIR_NO_LAST_SLASH);
- EXPECT_EQ("foo", out.str());
- }
-
- // WriteDir using an OutputFile.
- {
- std::ostringstream out;
- writer.WriteDir(out, OutputFile("foo/"),
- PathOutput::DIR_INCLUDE_LAST_SLASH);
- EXPECT_EQ("foo/", out.str());
- }
- {
- std::ostringstream out;
- writer.WriteDir(out, OutputFile("foo/"),
- PathOutput::DIR_NO_LAST_SLASH);
- EXPECT_EQ("foo", out.str());
- }
- {
- std::ostringstream out;
- writer.WriteDir(out, OutputFile(),
- PathOutput::DIR_INCLUDE_LAST_SLASH);
- EXPECT_EQ("", out.str());
- }
- }
- {
- // Empty build dir writer.
- base::StringPiece source_root("/source/root");
- PathOutput root_writer(SourceDir("//"), source_root, ESCAPE_NINJA);
- {
- std::ostringstream out;
- root_writer.WriteDir(out, SourceDir("//"),
- PathOutput::DIR_INCLUDE_LAST_SLASH);
- EXPECT_EQ("./", out.str());
- }
- {
- std::ostringstream out;
- root_writer.WriteDir(out, SourceDir("//"),
- PathOutput::DIR_NO_LAST_SLASH);
- EXPECT_EQ(".", out.str());
- }
- }
-}
diff --git a/chromium/tools/gn/pattern.cc b/chromium/tools/gn/pattern.cc
deleted file mode 100644
index 15bbf5811db..00000000000
--- a/chromium/tools/gn/pattern.cc
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/pattern.h"
-
-#include "tools/gn/value.h"
-
-namespace {
-
-void ParsePattern(const std::string& s, std::vector<Pattern::Subrange>* out) {
- // Set when the last subrange is a literal so we can just append when we
- // find another literal.
- Pattern::Subrange* last_literal = nullptr;
-
- for (size_t i = 0; i < s.size(); i++) {
- if (s[i] == '*') {
- // Don't allow two **.
- if (out->size() == 0 ||
- (*out)[out->size() - 1].type != Pattern::Subrange::ANYTHING)
- out->push_back(Pattern::Subrange(Pattern::Subrange::ANYTHING));
- last_literal = nullptr;
- } else if (s[i] == '\\') {
- if (i < s.size() - 1 && s[i + 1] == 'b') {
- // "\b" means path boundary.
- i++;
- out->push_back(Pattern::Subrange(Pattern::Subrange::PATH_BOUNDARY));
- last_literal = nullptr;
- } else {
- // Backslash + anything else means that literal char.
- if (!last_literal) {
- out->push_back(Pattern::Subrange(Pattern::Subrange::LITERAL));
- last_literal = &(*out)[out->size() - 1];
- }
- if (i < s.size() - 1) {
- i++;
- last_literal->literal.push_back(s[i]);
- } else {
- // Single backslash at end, use literal backslash.
- last_literal->literal.push_back('\\');
- }
- }
- } else {
- if (!last_literal) {
- out->push_back(Pattern::Subrange(Pattern::Subrange::LITERAL));
- last_literal = &(*out)[out->size() - 1];
- }
- last_literal->literal.push_back(s[i]);
- }
- }
-}
-
-} // namespace
-
-Pattern::Pattern(const std::string& s) {
- ParsePattern(s, &subranges_);
- is_suffix_ =
- (subranges_.size() == 2 &&
- subranges_[0].type == Subrange::ANYTHING &&
- subranges_[1].type == Subrange::LITERAL);
-}
-
-Pattern::Pattern(const Pattern& other) = default;
-
-Pattern::~Pattern() = default;
-
-bool Pattern::MatchesString(const std::string& s) const {
- // Empty pattern matches only empty string.
- if (subranges_.empty())
- return s.empty();
-
- if (is_suffix_) {
- const std::string& suffix = subranges_[1].literal;
- if (suffix.size() > s.size())
- return false; // Too short.
- return s.compare(s.size() - suffix.size(), suffix.size(), suffix) == 0;
- }
-
- return RecursiveMatch(s, 0, 0, true);
-}
-
-// We assume the number of ranges is small so recursive is always reasonable.
-// Could be optimized to only be recursive for *.
-bool Pattern::RecursiveMatch(const std::string& s,
- size_t begin_char,
- size_t subrange_index,
- bool allow_implicit_path_boundary) const {
- if (subrange_index >= subranges_.size()) {
- // Hit the end of our subranges, the text should also be at the end for a
- // match.
- return begin_char == s.size();
- }
-
- const Subrange& sr = subranges_[subrange_index];
- switch (sr.type) {
- case Subrange::LITERAL: {
- if (s.size() - begin_char < sr.literal.size())
- return false; // Not enough room.
- if (s.compare(begin_char, sr.literal.size(), sr.literal) != 0)
- return false; // Literal doesn't match.
-
- // Recursively check the next one.
- return RecursiveMatch(s, begin_char + sr.literal.size(),
- subrange_index + 1, true);
- }
-
- case Subrange::PATH_BOUNDARY: {
- // When we can accept an implicit path boundary, we have to check both
- // a match of the literal and the implicit one.
- if (allow_implicit_path_boundary &&
- (begin_char == 0 || begin_char == s.size())) {
- // At implicit path boundary, see if the rest of the pattern matches.
- if (RecursiveMatch(s, begin_char, subrange_index + 1, false))
- return true;
- }
-
- // Check for a literal "/".
- if (begin_char < s.size() && s[begin_char] == '/') {
- // At explicit boundary, see if the rest of the pattern matches.
- if (RecursiveMatch(s, begin_char + 1, subrange_index + 1, true))
- return true;
- }
- return false;
- }
-
- case Subrange::ANYTHING: {
- if (subrange_index == subranges_.size() - 1)
- return true; // * at the end, consider it matching.
-
- size_t min_next_size = sr.MinSize();
-
- // We don't care about exactly what matched as long as there was a match,
- // so we can do this front-to-back. If we needed the match, we would
- // normally want "*" to be greedy so would work backwards.
- for (size_t i = begin_char; i < s.size() - min_next_size; i++) {
- // Note: this could probably be faster by detecting the type of the
- // next match in advance and checking for a match in this loop rather
- // than doing a full recursive call for each character.
- if (RecursiveMatch(s, i, subrange_index + 1, true))
- return true;
- }
- return false;
- }
-
- default:
- NOTREACHED();
- }
-
- return false;
-}
-
-PatternList::PatternList() = default;
-
-PatternList::PatternList(const PatternList& other) = default;
-
-PatternList::~PatternList() = default;
-
-void PatternList::Append(const Pattern& pattern) {
- patterns_.push_back(pattern);
-}
-
-void PatternList::SetFromValue(const Value& v, Err* err) {
- patterns_.clear();
-
- if (v.type() != Value::LIST) {
- *err = Err(v.origin(), "This value must be a list.");
- return;
- }
-
- const std::vector<Value>& list = v.list_value();
- for (const auto& elem : list) {
- if (!elem.VerifyTypeIs(Value::STRING, err))
- return;
- patterns_.push_back(Pattern(elem.string_value()));
- }
-}
-
-bool PatternList::MatchesString(const std::string& s) const {
- for (const auto& pattern : patterns_) {
- if (pattern.MatchesString(s))
- return true;
- }
- return false;
-}
-
-bool PatternList::MatchesValue(const Value& v) const {
- if (v.type() == Value::STRING)
- return MatchesString(v.string_value());
- return false;
-}
diff --git a/chromium/tools/gn/pattern.h b/chromium/tools/gn/pattern.h
deleted file mode 100644
index f141f3eaeb1..00000000000
--- a/chromium/tools/gn/pattern.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_PATTERN_H_
-#define TOOLS_GN_PATTERN_H_
-
-#include <stddef.h>
-
-#include <string>
-#include <vector>
-
-#include "tools/gn/value.h"
-
-class Pattern {
- public:
- struct Subrange {
- enum Type {
- LITERAL, // Matches exactly the contents of the string.
- ANYTHING, // * (zero or more chars).
- PATH_BOUNDARY // '/' or beginning of string.
- };
-
- explicit Subrange(Type t, const std::string& l = std::string())
- : type(t),
- literal(l) {
- }
-
- // Returns the minimum number of chars that this subrange requires.
- size_t MinSize() const {
- switch (type) {
- case LITERAL:
- return literal.size();
- case ANYTHING:
- return 0;
- case PATH_BOUNDARY:
- return 0; // Can match beginning or end of string, which is 0 len.
- default:
- return 0;
- }
- }
-
- Type type;
-
- // When type == LITERAL this is the text to match.
- std::string literal;
- };
-
- explicit Pattern(const std::string& s);
- Pattern(const Pattern& other);
- ~Pattern();
-
- // Returns true if the current pattern matches the given string.
- bool MatchesString(const std::string& s) const;
-
- private:
- // allow_implicit_path_boundary determines if a path boundary should accept
- // matches at the beginning or end of the string.
- bool RecursiveMatch(const std::string& s,
- size_t begin_char,
- size_t subrange_index,
- bool allow_implicit_path_boundary) const;
-
- std::vector<Subrange> subranges_;
-
- // Set to true when the subranges are "*foo" ("ANYTHING" followed by a
- // literal). This covers most patterns so we optimize for this.
- bool is_suffix_;
-};
-
-class PatternList {
- public:
- PatternList();
- PatternList(const PatternList& other);
- ~PatternList();
-
- bool is_empty() const { return patterns_.empty(); }
-
- void Append(const Pattern& pattern);
-
- // Initializes the pattern list from a give list of pattern strings. Sets
- // |*err| on failure.
- void SetFromValue(const Value& v, Err* err);
-
- bool MatchesString(const std::string& s) const;
- bool MatchesValue(const Value& v) const;
-
- private:
- std::vector<Pattern> patterns_;
-};
-
-#endif // TOOLS_GN_PATTERN_H_
diff --git a/chromium/tools/gn/pattern_unittest.cc b/chromium/tools/gn/pattern_unittest.cc
deleted file mode 100644
index 683fe5662c2..00000000000
--- a/chromium/tools/gn/pattern_unittest.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/pattern.h"
-
-namespace {
-
-struct Case {
- const char* pattern;
- const char* candidate;
- bool expected_match;
-};
-
-} // namespace
-
-TEST(Pattern, Matches) {
- Case pattern_cases[] = {
- // Empty pattern matches only empty string.
- { "", "", true },
- { "", "foo", false },
- // Exact matches.
- { "foo", "foo", true },
- { "foo", "bar", false },
- // Path boundaries.
- { "\\b", "", true },
- { "\\b", "/", true },
- { "\\b\\b", "/", true },
- { "\\b\\b\\b", "", false },
- { "\\b\\b\\b", "/", true },
- { "\\b", "//", false },
- { "\\bfoo\\b", "foo", true },
- { "\\bfoo\\b", "/foo/", true },
- { "\\b\\bfoo", "/foo", true },
- // *
- { "*", "", true },
- { "*", "foo", true },
- { "*foo", "foo", true },
- { "*foo", "gagafoo", true },
- { "*foo", "gagafoob", false },
- { "foo*bar", "foobar", true },
- { "foo*bar", "foo-bar", true },
- { "foo*bar", "foolalalalabar", true },
- { "foo*bar", "foolalalalabaz", false },
- { "*a*b*c*d*", "abcd", true },
- { "*a*b*c*d*", "1a2b3c4d5", true },
- { "*a*b*c*d*", "1a2b3c45", false },
- { "*\\bfoo\\b*", "foo", true },
- { "*\\bfoo\\b*", "/foo/", true },
- { "*\\bfoo\\b*", "foob", false },
- { "*\\bfoo\\b*", "lala/foo/bar/baz", true },
- };
- for (size_t i = 0; i < arraysize(pattern_cases); i++) {
- const Case& c = pattern_cases[i];
- Pattern pattern(c.pattern);
- bool result = pattern.MatchesString(c.candidate);
- EXPECT_EQ(c.expected_match, result) << i << ": \"" << c.pattern
- << "\", \"" << c.candidate << "\"";
- }
-}
diff --git a/chromium/tools/gn/pool.cc b/chromium/tools/gn/pool.cc
deleted file mode 100644
index 4b9629bbe7f..00000000000
--- a/chromium/tools/gn/pool.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/pool.h"
-
-#include <sstream>
-
-#include "base/logging.h"
-
-Pool::~Pool() = default;
-
-Pool* Pool::AsPool() {
- return this;
-}
-
-const Pool* Pool::AsPool() const {
- return this;
-}
-
-std::string Pool::GetNinjaName(const Label& default_toolchain) const {
- bool include_toolchain = label().toolchain_dir() != default_toolchain.dir() ||
- label().toolchain_name() != default_toolchain.name();
- return GetNinjaName(include_toolchain);
-}
-
-std::string Pool::GetNinjaName(bool include_toolchain) const {
- std::ostringstream buffer;
- if (include_toolchain) {
- DCHECK(label().toolchain_dir().is_source_absolute());
- std::string toolchain_dir = label().toolchain_dir().value();
- for (std::string::size_type i = 2; i < toolchain_dir.size(); ++i) {
- buffer << (toolchain_dir[i] == '/' ? '_' : toolchain_dir[i]);
- }
- buffer << label().toolchain_name() << "_";
- }
-
- DCHECK(label().dir().is_source_absolute());
- std::string label_dir = label().dir().value();
- for (std::string::size_type i = 2; i < label_dir.size(); ++i) {
- buffer << (label_dir[i] == '/' ? '_' : label_dir[i]);
- }
- buffer << label().name();
- return buffer.str();
-}
diff --git a/chromium/tools/gn/pool.h b/chromium/tools/gn/pool.h
deleted file mode 100644
index 42a80789ec8..00000000000
--- a/chromium/tools/gn/pool.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_POOL_H_
-#define TOOLS_GN_POOL_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "tools/gn/item.h"
-
-// Represents a named pool in the dependency graph.
-//
-// A pool is used to limit the parallelism of task invocation in the
-// generated ninja build. Pools are referenced by toolchains.
-class Pool : public Item {
- public:
- using Item::Item;
- ~Pool() override;
-
- // Item implementation.
- Pool* AsPool() override;
- const Pool* AsPool() const override;
-
- // The pool depth (number of task to run simultaneously).
- int64_t depth() const { return depth_; }
- void set_depth(int64_t depth) { depth_ = depth; }
-
- // The pool name in generated ninja files.
- std::string GetNinjaName(const Label& default_toolchain) const;
-
- private:
- std::string GetNinjaName(bool include_toolchain) const;
-
- int64_t depth_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(Pool);
-};
-
-#endif // TOOLS_GN_POOL_H_
diff --git a/chromium/tools/gn/qt_creator_writer.cc b/chromium/tools/gn/qt_creator_writer.cc
deleted file mode 100644
index 687bff296e1..00000000000
--- a/chromium/tools/gn/qt_creator_writer.cc
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/qt_creator_writer.h"
-
-#include <set>
-#include <sstream>
-#include <string>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/strings/utf_string_conversions.h"
-
-#include "tools/gn/builder.h"
-#include "tools/gn/config_values_extractors.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/label.h"
-#include "tools/gn/loader.h"
-
-namespace {
-base::FilePath::CharType kProjectDirName[] =
- FILE_PATH_LITERAL("qtcreator_project");
-base::FilePath::CharType kProjectName[] = FILE_PATH_LITERAL("all");
-base::FilePath::CharType kMainProjectFileSuffix[] =
- FILE_PATH_LITERAL(".creator");
-base::FilePath::CharType kSourcesFileSuffix[] = FILE_PATH_LITERAL(".files");
-base::FilePath::CharType kIncludesFileSuffix[] = FILE_PATH_LITERAL(".includes");
-base::FilePath::CharType kDefinesFileSuffix[] = FILE_PATH_LITERAL(".config");
-}
-
-// static
-bool QtCreatorWriter::RunAndWriteFile(const BuildSettings* build_settings,
- const Builder& builder,
- Err* err,
- const std::string& root_target) {
- base::FilePath project_dir =
- build_settings->GetFullPath(build_settings->build_dir())
- .Append(kProjectDirName);
- if (!base::DirectoryExists(project_dir)) {
- base::File::Error error;
- if (!base::CreateDirectoryAndGetError(project_dir, &error)) {
- *err =
- Err(Location(), "Could not create the QtCreator project directory '" +
- FilePathToUTF8(project_dir) + "': " +
- base::File::ErrorToString(error));
- return false;
- }
- }
-
- base::FilePath project_prefix = project_dir.Append(kProjectName);
- QtCreatorWriter gen(build_settings, builder, project_prefix, root_target);
- gen.Run();
- if (gen.err_.has_error()) {
- *err = gen.err_;
- return false;
- }
- return true;
-}
-
-QtCreatorWriter::QtCreatorWriter(const BuildSettings* build_settings,
- const Builder& builder,
- const base::FilePath& project_prefix,
- const std::string& root_target_name)
- : build_settings_(build_settings),
- builder_(builder),
- project_prefix_(project_prefix),
- root_target_name_(root_target_name) {}
-
-QtCreatorWriter::~QtCreatorWriter() = default;
-
-void QtCreatorWriter::CollectDeps(const Target* target) {
- for (const auto& dep : target->GetDeps(Target::DEPS_ALL)) {
- const Target* dep_target = dep.ptr;
- if (targets_.count(dep_target))
- continue;
- targets_.insert(dep_target);
- CollectDeps(dep_target);
- }
-}
-
-bool QtCreatorWriter::DiscoverTargets() {
- auto all_targets = builder_.GetAllResolvedTargets();
-
- if (root_target_name_.empty()) {
- targets_ = std::set<const Target*>(all_targets.begin(), all_targets.end());
- return true;
- }
-
- const Target* root_target = nullptr;
- for (const Target* target : all_targets) {
- if (target->label().name() == root_target_name_) {
- root_target = target;
- break;
- }
- }
-
- if (!root_target) {
- err_ = Err(Location(), "Target '" + root_target_name_ + "' not found.");
- return false;
- }
-
- targets_.insert(root_target);
- CollectDeps(root_target);
- return true;
-}
-
-void QtCreatorWriter::AddToSources(const Target::FileList& files) {
- for (const SourceFile& file : files) {
- const std::string& file_path =
- FilePathToUTF8(build_settings_->GetFullPath(file));
- sources_.insert(file_path);
- }
-}
-
-void QtCreatorWriter::HandleTarget(const Target* target) {
- SourceFile build_file = Loader::BuildFileForLabel(target->label());
- sources_.insert(FilePathToUTF8(build_settings_->GetFullPath(build_file)));
- AddToSources(target->settings()->import_manager().GetImportedFiles());
-
- AddToSources(target->sources());
- AddToSources(target->public_headers());
-
- for (ConfigValuesIterator it(target); !it.done(); it.Next()) {
- for (const auto& input : it.cur().inputs())
- sources_.insert(FilePathToUTF8(build_settings_->GetFullPath(input)));
-
- SourceFile precompiled_source = it.cur().precompiled_source();
- if (!precompiled_source.is_null()) {
- sources_.insert(
- FilePathToUTF8(build_settings_->GetFullPath(precompiled_source)));
- }
-
- for (const SourceDir& include_dir : it.cur().include_dirs()) {
- includes_.insert(
- FilePathToUTF8(build_settings_->GetFullPath(include_dir)));
- }
-
- for (std::string define : it.cur().defines()) {
- size_t equal_pos = define.find('=');
- if (equal_pos != std::string::npos)
- define[equal_pos] = ' ';
- define.insert(0, "#define ");
- defines_.insert(define);
- }
- }
-}
-
-void QtCreatorWriter::GenerateFile(const base::FilePath::CharType* suffix,
- const std::set<std::string>& items) {
- const base::FilePath file_path = project_prefix_.AddExtension(suffix);
- std::ostringstream output;
- for (const std::string& item : items)
- output << item << std::endl;
- WriteFileIfChanged(file_path, output.str(), &err_);
-}
-
-void QtCreatorWriter::Run() {
- if (!DiscoverTargets())
- return;
-
- for (const Target* target : targets_) {
- if (target->toolchain()->label() !=
- builder_.loader()->GetDefaultToolchain())
- continue;
- HandleTarget(target);
- }
-
- std::set<std::string> empty_list;
-
- GenerateFile(kMainProjectFileSuffix, empty_list);
- GenerateFile(kSourcesFileSuffix, sources_);
- GenerateFile(kIncludesFileSuffix, includes_);
- GenerateFile(kDefinesFileSuffix, defines_);
-}
diff --git a/chromium/tools/gn/qt_creator_writer.h b/chromium/tools/gn/qt_creator_writer.h
deleted file mode 100644
index cb374049f40..00000000000
--- a/chromium/tools/gn/qt_creator_writer.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_QT_CREATOR_WRITER_H_
-#define TOOLS_GN_QT_CREATOR_WRITER_H_
-
-#include <set>
-#include <string>
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "tools/gn/err.h"
-#include "tools/gn/target.h"
-
-class Builder;
-class BuildSettings;
-
-class QtCreatorWriter {
- public:
- static bool RunAndWriteFile(const BuildSettings* build_settings,
- const Builder& builder,
- Err* err,
- const std::string& root_target);
-
- private:
- QtCreatorWriter(const BuildSettings* build_settings,
- const Builder& builder,
- const base::FilePath& project_prefix,
- const std::string& root_target_name);
- ~QtCreatorWriter();
-
- void Run();
-
- bool DiscoverTargets();
- void HandleTarget(const Target* target);
-
- void CollectDeps(const Target* target);
- void AddToSources(const Target::FileList& files);
- void GenerateFile(const base::FilePath::CharType* suffix,
- const std::set<std::string>& items);
-
- const BuildSettings* build_settings_;
- const Builder& builder_;
- base::FilePath project_prefix_;
- std::string root_target_name_;
- std::set<const Target*> targets_;
- std::set<std::string> sources_;
- std::set<std::string> includes_;
- std::set<std::string> defines_;
- Err err_;
-
- DISALLOW_COPY_AND_ASSIGN(QtCreatorWriter);
-};
-
-#endif // TOOLS_GN_QT_CREATOR_WRITER_H_
diff --git a/chromium/tools/gn/runtime_deps.cc b/chromium/tools/gn/runtime_deps.cc
deleted file mode 100644
index f0a242db8e0..00000000000
--- a/chromium/tools/gn/runtime_deps.cc
+++ /dev/null
@@ -1,314 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/runtime_deps.h"
-
-#include <map>
-#include <set>
-#include <sstream>
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/strings/string_split.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/builder.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/loader.h"
-#include "tools/gn/output_file.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/switches.h"
-#include "tools/gn/target.h"
-#include "tools/gn/trace.h"
-
-namespace {
-
-using RuntimeDepsVector = std::vector<std::pair<OutputFile, const Target*>>;
-
-// Adds the given file to the deps list if it hasn't already been listed in
-// the found_files list. Updates the list.
-void AddIfNew(const OutputFile& output_file,
- const Target* source,
- RuntimeDepsVector* deps,
- std::set<OutputFile>* found_file) {
- if (found_file->find(output_file) != found_file->end())
- return; // Already there.
- deps->push_back(std::make_pair(output_file, source));
-}
-
-// Automatically converts a string that looks like a source to an OutputFile.
-void AddIfNew(const std::string& str,
- const Target* source,
- RuntimeDepsVector* deps,
- std::set<OutputFile>* found_file) {
- OutputFile output_file(RebasePath(
- str,
- source->settings()->build_settings()->build_dir(),
- source->settings()->build_settings()->root_path_utf8()));
- AddIfNew(output_file, source, deps, found_file);
-}
-
-// To avoid duplicate traversals of targets, or duplicating output files that
-// might be listed by more than one target, the set of targets and output files
-// that have been found so far is passed. The "value" of the seen_targets map
-// is a boolean indicating if the seen dep was a data dep (true = data_dep).
-// data deps add more stuff, so we will want to revisit a target if it's a
-// data dependency and we've previously only seen it as a regular dep.
-void RecursiveCollectRuntimeDeps(const Target* target,
- bool is_target_data_dep,
- RuntimeDepsVector* deps,
- std::map<const Target*, bool>* seen_targets,
- std::set<OutputFile>* found_files) {
- const auto& found_seen_target = seen_targets->find(target);
- if (found_seen_target != seen_targets->end()) {
- // Already visited.
- if (found_seen_target->second || !is_target_data_dep) {
- // Already visited as a data dep, or the current dep is not a data
- // dep so visiting again will be a no-op.
- return;
- }
- // In the else case, the previously seen target was a regular dependency
- // and we'll now process it as a data dependency.
- }
- (*seen_targets)[target] = is_target_data_dep;
-
- // Add the main output file for executables, shared libraries, and
- // loadable modules.
- if (target->output_type() == Target::EXECUTABLE ||
- target->output_type() == Target::LOADABLE_MODULE ||
- target->output_type() == Target::SHARED_LIBRARY) {
- for (const auto& runtime_output : target->runtime_outputs())
- AddIfNew(runtime_output, target, deps, found_files);
- }
-
- // Add all data files.
- for (const auto& file : target->data())
- AddIfNew(file, target, deps, found_files);
-
- // Actions/copy have all outputs considered when the're a data dep.
- if (is_target_data_dep &&
- (target->output_type() == Target::ACTION ||
- target->output_type() == Target::ACTION_FOREACH ||
- target->output_type() == Target::COPY_FILES)) {
- std::vector<SourceFile> outputs;
- target->action_values().GetOutputsAsSourceFiles(target, &outputs);
- for (const auto& output_file : outputs)
- AddIfNew(output_file.value(), target, deps, found_files);
- }
-
- // Data dependencies.
- for (const auto& dep_pair : target->data_deps()) {
- RecursiveCollectRuntimeDeps(dep_pair.ptr, true,
- deps, seen_targets, found_files);
- }
-
- // Do not recurse into bundle targets. A bundle's dependencies should be
- // copied into the bundle itself for run-time access.
- if (target->output_type() == Target::CREATE_BUNDLE) {
- SourceDir bundle_root_dir =
- target->bundle_data().GetBundleRootDirOutputAsDir(target->settings());
- AddIfNew(bundle_root_dir.value(), target, deps, found_files);
- return;
- }
-
- // Non-data dependencies (both public and private).
- for (const auto& dep_pair : target->GetDeps(Target::DEPS_LINKED)) {
- if (dep_pair.ptr->output_type() == Target::EXECUTABLE)
- continue; // Skip executables that aren't data deps.
- if (dep_pair.ptr->output_type() == Target::SHARED_LIBRARY &&
- (target->output_type() == Target::ACTION ||
- target->output_type() == Target::ACTION_FOREACH)) {
- // Skip shared libraries that action depends on,
- // unless it were listed in data deps.
- continue;
- }
- RecursiveCollectRuntimeDeps(dep_pair.ptr, false,
- deps, seen_targets, found_files);
- }
-}
-
-bool CollectRuntimeDepsFromFlag(const Builder& builder,
- RuntimeDepsVector* files_to_write,
- Err* err) {
- std::string deps_target_list_file =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kRuntimeDepsListFile);
-
- if (deps_target_list_file.empty())
- return true;
-
- std::string list_contents;
- ScopedTrace load_trace(TraceItem::TRACE_FILE_LOAD, deps_target_list_file);
- if (!base::ReadFileToString(UTF8ToFilePath(deps_target_list_file),
- &list_contents)) {
- *err = Err(Location(),
- std::string("File for --") + switches::kRuntimeDepsListFile +
- " doesn't exist.",
- "The file given was \"" + deps_target_list_file + "\"");
- return false;
- }
- load_trace.Done();
-
- SourceDir root_dir("//");
- Label default_toolchain_label = builder.loader()->GetDefaultToolchain();
- for (const auto& line :
- base::SplitString(list_contents, "\n", base::TRIM_WHITESPACE,
- base::SPLIT_WANT_ALL)) {
- if (line.empty())
- continue;
- Label label = Label::Resolve(root_dir, default_toolchain_label,
- Value(nullptr, line), err);
- if (err->has_error())
- return false;
-
- const Item* item = builder.GetItem(label);
- const Target* target = item ? item->AsTarget() : nullptr;
- if (!target) {
- *err = Err(Location(), "The label \"" + label.GetUserVisibleName(true) +
- "\" isn't a target.",
- "When reading the line:\n " + line + "\n"
- "from the --" + switches::kRuntimeDepsListFile + "=" +
- deps_target_list_file);
- return false;
- }
-
- OutputFile output_file;
- const char extension[] = ".runtime_deps";
- if (target->output_type() == Target::SHARED_LIBRARY ||
- target->output_type() == Target::LOADABLE_MODULE) {
- // Force the first output for shared-library-type linker outputs since
- // the dependency output files might not be the main output.
- CHECK(!target->computed_outputs().empty());
- output_file =
- OutputFile(target->computed_outputs()[0].value() + extension);
- } else {
- output_file =
- OutputFile(target->dependency_output_file().value() + extension);
- }
- files_to_write->push_back(std::make_pair(output_file, target));
- }
- return true;
-}
-
-bool WriteRuntimeDepsFile(const OutputFile& output_file,
- const Target* target,
- Err* err) {
- SourceFile output_as_source =
- output_file.AsSourceFile(target->settings()->build_settings());
- base::FilePath data_deps_file =
- target->settings()->build_settings()->GetFullPath(output_as_source);
-
- std::stringstream contents;
- for (const auto& pair : ComputeRuntimeDeps(target))
- contents << pair.first.value() << std::endl;
-
- ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, output_as_source.value());
- return WriteFileIfChanged(data_deps_file, contents.str(), err);
-}
-
-} // namespace
-
-const char kRuntimeDeps_Help[] =
- R"(Runtime dependencies
-
- Runtime dependencies of a target are exposed via the "runtime_deps" category
- of "gn desc" (see "gn help desc") or they can be written at build generation
- time via write_runtime_deps(), or --runtime-deps-list-file (see "gn help
- --runtime-deps-list-file").
-
- To a first approximation, the runtime dependencies of a target are the set of
- "data" files, data directories, and the shared libraries from all transitive
- dependencies. Executables, shared libraries, and loadable modules are
- considered runtime dependencies of themselves.
-
-Executables
-
- Executable targets and those executable targets' transitive dependencies are
- not considered unless that executable is listed in "data_deps". Otherwise, GN
- assumes that the executable (and everything it requires) is a build-time
- dependency only.
-
-Actions and copies
-
- Action and copy targets that are listed as "data_deps" will have all of their
- outputs and data files considered as runtime dependencies. Action and copy
- targets that are "deps" or "public_deps" will have only their data files
- considered as runtime dependencies. These targets can list an output file in
- both the "outputs" and "data" lists to force an output file as a runtime
- dependency in all cases.
-
- The different rules for deps and data_deps are to express build-time (deps)
- vs. run-time (data_deps) outputs. If GN counted all build-time copy steps as
- data dependencies, there would be a lot of extra stuff, and if GN counted all
- run-time dependencies as regular deps, the build's parallelism would be
- unnecessarily constrained.
-
- This rule can sometimes lead to unintuitive results. For example, given the
- three targets:
- A --[data_deps]--> B --[deps]--> ACTION
- GN would say that A does not have runtime deps on the result of the ACTION,
- which is often correct. But the purpose of the B target might be to collect
- many actions into one logic unit, and the "data"-ness of A's dependency is
- lost. Solutions:
-
- - List the outputs of the action in its data section (if the results of
- that action are always runtime files).
- - Have B list the action in data_deps (if the outputs of the actions are
- always runtime files).
- - Have B list the action in both deps and data deps (if the outputs might be
- used in both contexts and you don't care about unnecessary entries in the
- list of files required at runtime).
- - Split B into run-time and build-time versions with the appropriate "deps"
- for each.
-
-Static libraries and source sets
-
- The results of static_library or source_set targets are not considered
- runtime dependencies since these are assumed to be intermediate targets only.
- If you need to list a static library as a runtime dependency, you can
- manually compute the .a/.lib file name for the current platform and list it
- in the "data" list of a target (possibly on the static library target
- itself).
-
-Multiple outputs
-
- Linker tools can specify which of their outputs should be considered when
- computing the runtime deps by setting runtime_outputs. If this is unset on
- the tool, the default will be the first output only.
-)";
-
-RuntimeDepsVector ComputeRuntimeDeps(const Target* target) {
- RuntimeDepsVector result;
- std::map<const Target*, bool> seen_targets;
- std::set<OutputFile> found_files;
-
- // The initial target is not considered a data dependency so that actions's
- // outputs (if the current target is an action) are not automatically
- // considered data deps.
- RecursiveCollectRuntimeDeps(target, false,
- &result, &seen_targets, &found_files);
- return result;
-}
-
-bool WriteRuntimeDepsFilesIfNecessary(const Builder& builder, Err* err) {
- RuntimeDepsVector files_to_write;
- if (!CollectRuntimeDepsFromFlag(builder, &files_to_write, err))
- return false;
-
- // Files scheduled by write_runtime_deps.
- for (const Target* target : g_scheduler->GetWriteRuntimeDepsTargets()) {
- files_to_write.push_back(
- std::make_pair(target->write_runtime_deps_output(), target));
- }
-
- for (const auto& entry : files_to_write) {
- // Currently this writes all runtime deps files sequentially. We generally
- // expect few of these. We can run this on the worker pool if it looks
- // like it's talking a long time.
- if (!WriteRuntimeDepsFile(entry.first, entry.second, err))
- return false;
- }
- return true;
-}
diff --git a/chromium/tools/gn/runtime_deps.h b/chromium/tools/gn/runtime_deps.h
deleted file mode 100644
index 8592677b6dd..00000000000
--- a/chromium/tools/gn/runtime_deps.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_RUNTIME_DEPS_H
-#define TOOLS_GN_RUNTIME_DEPS_H
-
-#include <utility>
-#include <vector>
-
-class Builder;
-class Err;
-class OutputFile;
-class Target;
-
-extern const char kRuntimeDeps_Help[];
-
-// Computes the runtime dependencies of the given target. The result is a list
-// of pairs listing the runtime dependency and the target that the runtime
-// dependency is from (for blaming).
-std::vector<std::pair<OutputFile, const Target*>> ComputeRuntimeDeps(
- const Target* target);
-
-// Writes all runtime deps files requested on the command line, or does nothing
-// if no files were specified.
-bool WriteRuntimeDepsFilesIfNecessary(const Builder& builder, Err* err);
-
-#endif // TOOLS_GN_RUNTIME_DEPS_H
diff --git a/chromium/tools/gn/runtime_deps_unittest.cc b/chromium/tools/gn/runtime_deps_unittest.cc
deleted file mode 100644
index bb5d46f7d1b..00000000000
--- a/chromium/tools/gn/runtime_deps_unittest.cc
+++ /dev/null
@@ -1,448 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include "base/stl_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/runtime_deps.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scheduler.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-void InitTargetWithType(TestWithScope& setup,
- Target* target,
- Target::OutputType type) {
- target->set_output_type(type);
- target->visibility().SetPublic();
- target->SetToolchain(setup.toolchain());
-}
-
-// Convenience function to make the correct kind of pair.
-std::pair<OutputFile, const Target*> MakePair(const char* str,
- const Target* t) {
- return std::pair<OutputFile, const Target*>(OutputFile(str), t);
-}
-
-std::string GetVectorDescription(
- const std::vector<std::pair<OutputFile, const Target*>>& v) {
- std::string result;
- for (size_t i = 0; i < v.size(); i++) {
- if (i != 0)
- result.append(", ");
- result.append("\"" + v[i].first.value() + "\"");
- }
- return result;
-}
-
-} // namespace
-
-using RuntimeDeps = TestWithScheduler;
-
-// Tests an exe depending on different types of libraries.
-TEST_F(RuntimeDeps, Libs) {
- TestWithScope setup;
- Err err;
-
- // Dependency hierarchy: main(exe) -> static library
- // -> shared library
- // -> loadable module
- // -> source set
-
- Target stat(setup.settings(), Label(SourceDir("//"), "stat"));
- InitTargetWithType(setup, &stat, Target::STATIC_LIBRARY);
- stat.data().push_back("//stat.dat");
- ASSERT_TRUE(stat.OnResolved(&err));
-
- Target shared(setup.settings(), Label(SourceDir("//"), "shared"));
- InitTargetWithType(setup, &shared, Target::SHARED_LIBRARY);
- shared.data().push_back("//shared.dat");
- ASSERT_TRUE(shared.OnResolved(&err));
-
- Target loadable(setup.settings(), Label(SourceDir("//"), "loadable"));
- InitTargetWithType(setup, &loadable, Target::LOADABLE_MODULE);
- loadable.data().push_back("//loadable.dat");
- ASSERT_TRUE(loadable.OnResolved(&err));
-
- Target set(setup.settings(), Label(SourceDir("//"), "set"));
- InitTargetWithType(setup, &set, Target::SOURCE_SET);
- set.data().push_back("//set.dat");
- ASSERT_TRUE(set.OnResolved(&err));
-
- Target main(setup.settings(), Label(SourceDir("//"), "main"));
- InitTargetWithType(setup, &main, Target::EXECUTABLE);
- main.private_deps().push_back(LabelTargetPair(&stat));
- main.private_deps().push_back(LabelTargetPair(&shared));
- main.private_deps().push_back(LabelTargetPair(&loadable));
- main.private_deps().push_back(LabelTargetPair(&set));
- main.data().push_back("//main.dat");
- ASSERT_TRUE(main.OnResolved(&err));
-
- std::vector<std::pair<OutputFile, const Target*>> result =
- ComputeRuntimeDeps(&main);
-
- // The result should have deps of main, all 5 dat files, libshared.so, and
- // libloadable.so.
- ASSERT_EQ(8u, result.size()) << GetVectorDescription(result);
-
- // The first one should always be the main exe.
- EXPECT_TRUE(MakePair("./main", &main) == result[0]);
-
- // The rest of the ordering is undefined. First the data files.
- EXPECT_TRUE(base::ContainsValue(result, MakePair("../../stat.dat", &stat)))
- << GetVectorDescription(result);
- EXPECT_TRUE(
- base::ContainsValue(result, MakePair("../../shared.dat", &shared)))
- << GetVectorDescription(result);
- EXPECT_TRUE(
- base::ContainsValue(result, MakePair("../../loadable.dat", &loadable)))
- << GetVectorDescription(result);
- EXPECT_TRUE(base::ContainsValue(result, MakePair("../../set.dat", &set)))
- << GetVectorDescription(result);
- EXPECT_TRUE(base::ContainsValue(result, MakePair("../../main.dat", &main)))
- << GetVectorDescription(result);
-
- // Check the static library and loadable module.
- EXPECT_TRUE(base::ContainsValue(result, MakePair("./libshared.so", &shared)))
- << GetVectorDescription(result);
- EXPECT_TRUE(
- base::ContainsValue(result, MakePair("./libloadable.so", &loadable)))
- << GetVectorDescription(result);
-}
-
-// Tests that executables that aren't listed as data deps aren't included in
-// the output, but executables that are data deps are included.
-TEST_F(RuntimeDeps, ExeDataDep) {
- TestWithScope setup;
- Err err;
-
- // Dependency hierarchy: main(exe) -> datadep(exe) -> final_in(source set)
- // -> dep(exe) -> final_out(source set)
- // The final_in/out targets each have data files. final_in's should be
- // included, final_out's should not be.
-
- Target final_in(setup.settings(), Label(SourceDir("//"), "final_in"));
- InitTargetWithType(setup, &final_in, Target::SOURCE_SET);
- final_in.data().push_back("//final_in.dat");
- ASSERT_TRUE(final_in.OnResolved(&err));
-
- Target datadep(setup.settings(), Label(SourceDir("//"), "datadep"));
- InitTargetWithType(setup, &datadep, Target::EXECUTABLE);
- datadep.private_deps().push_back(LabelTargetPair(&final_in));
- ASSERT_TRUE(datadep.OnResolved(&err));
-
- Target final_out(setup.settings(), Label(SourceDir("//"), "final_out"));
- InitTargetWithType(setup, &final_out, Target::SOURCE_SET);
- final_out.data().push_back("//final_out.dat");
- ASSERT_TRUE(final_out.OnResolved(&err));
-
- Target dep(setup.settings(), Label(SourceDir("//"), "dep"));
- InitTargetWithType(setup, &dep, Target::EXECUTABLE);
- dep.private_deps().push_back(LabelTargetPair(&final_out));
- ASSERT_TRUE(dep.OnResolved(&err));
-
- Target main(setup.settings(), Label(SourceDir("//"), "main"));
- InitTargetWithType(setup, &main, Target::EXECUTABLE);
- main.private_deps().push_back(LabelTargetPair(&dep));
- main.data_deps().push_back(LabelTargetPair(&datadep));
- ASSERT_TRUE(main.OnResolved(&err));
-
- std::vector<std::pair<OutputFile, const Target*>> result =
- ComputeRuntimeDeps(&main);
-
- // The result should have deps of main, datadep, final_in.dat
- ASSERT_EQ(3u, result.size()) << GetVectorDescription(result);
-
- // The first one should always be the main exe.
- EXPECT_TRUE(MakePair("./main", &main) == result[0]);
-
- // The rest of the ordering is undefined.
- EXPECT_TRUE(base::ContainsValue(result, MakePair("./datadep", &datadep)))
- << GetVectorDescription(result);
- EXPECT_TRUE(
- base::ContainsValue(result, MakePair("../../final_in.dat", &final_in)))
- << GetVectorDescription(result);
-}
-
-TEST_F(RuntimeDeps, ActionSharedLib) {
- TestWithScope setup;
- Err err;
-
- // Dependency hierarchy: main(exe) -> action -> datadep(shared library)
- // -> dep(shared library)
- // Datadep should be included, dep should not be.
-
- Target dep(setup.settings(), Label(SourceDir("//"), "dep"));
- InitTargetWithType(setup, &dep, Target::SHARED_LIBRARY);
- ASSERT_TRUE(dep.OnResolved(&err));
-
- Target datadep(setup.settings(), Label(SourceDir("//"), "datadep"));
- InitTargetWithType(setup, &datadep, Target::SHARED_LIBRARY);
- ASSERT_TRUE(datadep.OnResolved(&err));
-
- Target action(setup.settings(), Label(SourceDir("//"), "action"));
- InitTargetWithType(setup, &action, Target::ACTION);
- action.private_deps().push_back(LabelTargetPair(&dep));
- action.data_deps().push_back(LabelTargetPair(&datadep));
- action.action_values().outputs() =
- SubstitutionList::MakeForTest("//action.output");
- ASSERT_TRUE(action.OnResolved(&err));
-
- Target main(setup.settings(), Label(SourceDir("//"), "main"));
- InitTargetWithType(setup, &main, Target::EXECUTABLE);
- main.private_deps().push_back(LabelTargetPair(&action));
- ASSERT_TRUE(main.OnResolved(&err));
-
- std::vector<std::pair<OutputFile, const Target*>> result =
- ComputeRuntimeDeps(&main);
-
- // The result should have deps of main and data_dep.
- ASSERT_EQ(2u, result.size()) << GetVectorDescription(result);
-
- // The first one should always be the main exe.
- EXPECT_TRUE(MakePair("./main", &main) == result[0]);
- EXPECT_TRUE(MakePair("./libdatadep.so", &datadep) == result[1]);
-}
-
-// Tests that action and copy outputs are considered if they're data deps, but
-// not if they're regular deps. Action and copy "data" files are always
-// included.
-TEST_F(RuntimeDeps, ActionOutputs) {
- TestWithScope setup;
- Err err;
-
- // Dependency hierarchy: main(exe) -> datadep (action)
- // -> datadep_copy (copy)
- // -> dep (action)
- // -> dep_copy (copy)
-
- Target datadep(setup.settings(), Label(SourceDir("//"), "datadep"));
- InitTargetWithType(setup, &datadep, Target::ACTION);
- datadep.data().push_back("//datadep.data");
- datadep.action_values().outputs() =
- SubstitutionList::MakeForTest("//datadep.output");
- ASSERT_TRUE(datadep.OnResolved(&err));
-
- Target datadep_copy(setup.settings(), Label(SourceDir("//"), "datadep_copy"));
- InitTargetWithType(setup, &datadep_copy, Target::COPY_FILES);
- datadep_copy.sources().push_back(SourceFile("//input"));
- datadep_copy.data().push_back("//datadep_copy.data");
- datadep_copy.action_values().outputs() =
- SubstitutionList::MakeForTest("//datadep_copy.output");
- ASSERT_TRUE(datadep_copy.OnResolved(&err));
-
- Target dep(setup.settings(), Label(SourceDir("//"), "dep"));
- InitTargetWithType(setup, &dep, Target::ACTION);
- dep.data().push_back("//dep.data");
- dep.action_values().outputs() =
- SubstitutionList::MakeForTest("//dep.output");
- ASSERT_TRUE(dep.OnResolved(&err));
-
- Target dep_copy(setup.settings(), Label(SourceDir("//"), "dep_copy"));
- InitTargetWithType(setup, &dep_copy, Target::COPY_FILES);
- dep_copy.sources().push_back(SourceFile("//input"));
- dep_copy.data().push_back("//dep_copy/data/"); // Tests a directory.
- dep_copy.action_values().outputs() =
- SubstitutionList::MakeForTest("//dep_copy.output");
- ASSERT_TRUE(dep_copy.OnResolved(&err));
-
- Target main(setup.settings(), Label(SourceDir("//"), "main"));
- InitTargetWithType(setup, &main, Target::EXECUTABLE);
- main.private_deps().push_back(LabelTargetPair(&dep));
- main.private_deps().push_back(LabelTargetPair(&dep_copy));
- main.data_deps().push_back(LabelTargetPair(&datadep));
- main.data_deps().push_back(LabelTargetPair(&datadep_copy));
- ASSERT_TRUE(main.OnResolved(&err));
-
- std::vector<std::pair<OutputFile, const Target*>> result =
- ComputeRuntimeDeps(&main);
-
- // The result should have deps of main, both datadeps files, but only
- // the data file from dep.
- ASSERT_EQ(7u, result.size()) << GetVectorDescription(result);
-
- // The first one should always be the main exe.
- EXPECT_TRUE(MakePair("./main", &main) == result[0]);
-
- // The rest of the ordering is undefined.
- EXPECT_TRUE(
- base::ContainsValue(result, MakePair("../../datadep.data", &datadep)))
- << GetVectorDescription(result);
- EXPECT_TRUE(base::ContainsValue(
- result, MakePair("../../datadep_copy.data", &datadep_copy)))
- << GetVectorDescription(result);
- EXPECT_TRUE(
- base::ContainsValue(result, MakePair("../../datadep.output", &datadep)))
- << GetVectorDescription(result);
- EXPECT_TRUE(base::ContainsValue(
- result, MakePair("../../datadep_copy.output", &datadep_copy)))
- << GetVectorDescription(result);
- EXPECT_TRUE(base::ContainsValue(result, MakePair("../../dep.data", &dep)))
- << GetVectorDescription(result);
- EXPECT_TRUE(
- base::ContainsValue(result, MakePair("../../dep_copy/data/", &dep_copy)))
- << GetVectorDescription(result);
-
- // Explicitly asking for the runtime deps of an action target only includes
- // the data and not all outputs.
- result = ComputeRuntimeDeps(&dep);
- ASSERT_EQ(1u, result.size());
- EXPECT_TRUE(MakePair("../../dep.data", &dep) == result[0]);
-}
-
-// Tests that the search for dependencies terminates at a bundle target,
-// ignoring any shared libraries or loadable modules that get copied into the
-// bundle.
-TEST_F(RuntimeDeps, CreateBundle) {
- TestWithScope setup;
- Err err;
-
- // Dependency hierarchy:
- // main(exe) -> dep(bundle) -> dep(shared_library) -> dep(source set)
- // -> dep(bundle_data) -> dep(loadable_module)
- // -> data(lm.data)
- // -> datadep(datadep) -> data(dd.data)
-
- const SourceDir source_dir("//");
- const std::string& build_dir = setup.build_settings()->build_dir().value();
-
- Target loadable_module(setup.settings(),
- Label(source_dir, "loadable_module"));
- InitTargetWithType(setup, &loadable_module, Target::LOADABLE_MODULE);
- loadable_module.data().push_back("//lm.data");
- ASSERT_TRUE(loadable_module.OnResolved(&err));
-
- Target module_data(setup.settings(), Label(source_dir, "module_data"));
- InitTargetWithType(setup, &module_data, Target::BUNDLE_DATA);
- module_data.private_deps().push_back(LabelTargetPair(&loadable_module));
- module_data.bundle_data().file_rules().push_back(BundleFileRule(
- nullptr,
- std::vector<SourceFile>{SourceFile(build_dir + "loadable_module.so")},
- SubstitutionPattern::MakeForTest("{{bundle_resources_dir}}")));
- ASSERT_TRUE(module_data.OnResolved(&err));
-
- Target source_set(setup.settings(), Label(source_dir, "sources"));
- InitTargetWithType(setup, &source_set, Target::SOURCE_SET);
- source_set.sources().push_back(SourceFile(source_dir.value() + "foo.cc"));
- ASSERT_TRUE(source_set.OnResolved(&err));
-
- Target dylib(setup.settings(), Label(source_dir, "dylib"));
- dylib.set_output_prefix_override(true);
- dylib.set_output_extension("");
- dylib.set_output_name("Bundle");
- InitTargetWithType(setup, &dylib, Target::SHARED_LIBRARY);
- dylib.private_deps().push_back(LabelTargetPair(&source_set));
- ASSERT_TRUE(dylib.OnResolved(&err));
-
- Target dylib_data(setup.settings(), Label(source_dir, "dylib_data"));
- InitTargetWithType(setup, &dylib_data, Target::BUNDLE_DATA);
- dylib_data.private_deps().push_back(LabelTargetPair(&dylib));
- dylib_data.bundle_data().file_rules().push_back(BundleFileRule(
- nullptr, std::vector<SourceFile>{SourceFile(build_dir + "dylib")},
- SubstitutionPattern::MakeForTest("{{bundle_executable_dir}}")));
- ASSERT_TRUE(dylib_data.OnResolved(&err));
-
- Target data_dep(setup.settings(), Label(source_dir, "datadep"));
- InitTargetWithType(setup, &data_dep, Target::EXECUTABLE);
- data_dep.data().push_back("//dd.data");
- ASSERT_TRUE(data_dep.OnResolved(&err));
-
- Target bundle(setup.settings(), Label(source_dir, "bundle"));
- InitTargetWithType(setup, &bundle, Target::CREATE_BUNDLE);
- const std::string root_dir(build_dir + "Bundle.framework/");
- const std::string contents_dir(root_dir + "Versions/A/");
- bundle.bundle_data().root_dir() = SourceDir(root_dir);
- bundle.bundle_data().contents_dir() = SourceDir(contents_dir);
- bundle.bundle_data().resources_dir() = SourceDir(contents_dir + "Resources");
- bundle.bundle_data().executable_dir() = SourceDir(contents_dir + "MacOS");
- bundle.private_deps().push_back(LabelTargetPair(&dylib_data));
- bundle.private_deps().push_back(LabelTargetPair(&module_data));
- bundle.data_deps().push_back(LabelTargetPair(&data_dep));
- bundle.data().push_back("//b.data");
- ASSERT_TRUE(bundle.OnResolved(&err));
-
- Target main(setup.settings(), Label(source_dir, "main"));
- InitTargetWithType(setup, &main, Target::EXECUTABLE);
- main.data_deps().push_back(LabelTargetPair(&bundle));
- ASSERT_TRUE(main.OnResolved(&err));
-
- std::vector<std::pair<OutputFile, const Target*>> result =
- ComputeRuntimeDeps(&main);
-
- // The result should have deps of main, datadep, final_in.dat
- ASSERT_EQ(5u, result.size()) << GetVectorDescription(result);
-
- // The first one should always be the main exe.
- EXPECT_EQ(MakePair("./main", &main), result[0]);
-
- // The rest of the ordering is undefined.
-
- // The framework bundle's internal dependencies should not be incldued.
- EXPECT_TRUE(
- base::ContainsValue(result, MakePair("Bundle.framework/", &bundle)))
- << GetVectorDescription(result);
- // But direct data and data dependencies should be.
- EXPECT_TRUE(base::ContainsValue(result, MakePair("./datadep", &data_dep)))
- << GetVectorDescription(result);
- EXPECT_TRUE(base::ContainsValue(result, MakePair("../../dd.data", &data_dep)))
- << GetVectorDescription(result);
- EXPECT_TRUE(base::ContainsValue(result, MakePair("../../b.data", &bundle)))
- << GetVectorDescription(result);
-}
-
-// Tests that a dependency duplicated in regular and data deps is processed
-// as a data dep.
-TEST_F(RuntimeDeps, Dupe) {
- TestWithScope setup;
- Err err;
-
- Target action(setup.settings(), Label(SourceDir("//"), "action"));
- InitTargetWithType(setup, &action, Target::ACTION);
- action.action_values().outputs() =
- SubstitutionList::MakeForTest("//action.output");
- ASSERT_TRUE(action.OnResolved(&err));
-
- Target target(setup.settings(), Label(SourceDir("//"), "foo"));
- InitTargetWithType(setup, &target, Target::EXECUTABLE);
- target.private_deps().push_back(LabelTargetPair(&action));
- target.data_deps().push_back(LabelTargetPair(&action));
- ASSERT_TRUE(target.OnResolved(&err));
-
- // The results should be the executable and the copy output.
- std::vector<std::pair<OutputFile, const Target*>> result =
- ComputeRuntimeDeps(&target);
- EXPECT_TRUE(
- base::ContainsValue(result, MakePair("../../action.output", &action)))
- << GetVectorDescription(result);
-}
-
-// Tests that actions can't have output substitutions.
-TEST_F(RuntimeDeps, WriteRuntimeDepsVariable) {
- TestWithScope setup;
- Err err;
-
- // Should refuse to write files outside of the output dir.
- EXPECT_FALSE(setup.ExecuteSnippet(
- "group(\"foo\") { write_runtime_deps = \"//foo.txt\" }", &err));
-
- // Should fail for garbage inputs.
- err = Err();
- EXPECT_FALSE(setup.ExecuteSnippet(
- "group(\"foo\") { write_runtime_deps = 0 }", &err));
-
- // Should be able to write inside the out dir, and shouldn't write the one
- // in the else clause.
- err = Err();
- EXPECT_TRUE(setup.ExecuteSnippet(
- "if (true) {\n"
- " group(\"foo\") { write_runtime_deps = \"//out/Debug/foo.txt\" }\n"
- "} else {\n"
- " group(\"bar\") { write_runtime_deps = \"//out/Debug/bar.txt\" }\n"
- "}", &err));
- EXPECT_EQ(1U, setup.items().size());
- EXPECT_EQ(1U, scheduler().GetWriteRuntimeDepsTargets().size());
-}
diff --git a/chromium/tools/gn/scheduler.cc b/chromium/tools/gn/scheduler.cc
deleted file mode 100644
index cf66dc746ff..00000000000
--- a/chromium/tools/gn/scheduler.cc
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/scheduler.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/single_thread_task_runner.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "tools/gn/standard_out.h"
-#include "tools/gn/target.h"
-
-Scheduler* g_scheduler = nullptr;
-
-Scheduler::Scheduler()
- : main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- input_file_manager_(new InputFileManager),
- verbose_logging_(false),
- pool_work_count_cv_(&pool_work_count_lock_),
- is_failed_(false),
- has_been_shutdown_(false) {
- g_scheduler = this;
-}
-
-Scheduler::~Scheduler() {
- WaitForPoolTasks();
- g_scheduler = nullptr;
-}
-
-bool Scheduler::Run() {
- runner_.Run();
- bool local_is_failed;
- {
- base::AutoLock lock(lock_);
- local_is_failed = is_failed();
- has_been_shutdown_ = true;
- }
- // Don't do this while holding |lock_|, since it will block on the workers,
- // which may be in turn waiting on the lock.
- WaitForPoolTasks();
- return !local_is_failed;
-}
-
-void Scheduler::Log(const std::string& verb, const std::string& msg) {
- if (task_runner()->BelongsToCurrentThread()) {
- LogOnMainThread(verb, msg);
- } else {
- // The run loop always joins on the sub threads, so the lifetime of this
- // object outlives the invocations of this function, hence "unretained".
- task_runner()->PostTask(FROM_HERE,
- base::Bind(&Scheduler::LogOnMainThread,
- base::Unretained(this), verb, msg));
- }
-}
-
-void Scheduler::FailWithError(const Err& err) {
- DCHECK(err.has_error());
- {
- base::AutoLock lock(lock_);
-
- if (is_failed_ || has_been_shutdown_)
- return; // Ignore errors once we see one.
- is_failed_ = true;
- }
-
- if (task_runner()->BelongsToCurrentThread()) {
- FailWithErrorOnMainThread(err);
- } else {
- // The run loop always joins on the sub threads, so the lifetime of this
- // object outlives the invocations of this function, hence "unretained".
- task_runner()->PostTask(FROM_HERE,
- base::Bind(&Scheduler::FailWithErrorOnMainThread,
- base::Unretained(this), err));
- }
-}
-
-void Scheduler::ScheduleWork(base::OnceClosure work) {
- IncrementWorkCount();
- pool_work_count_.Increment();
- base::PostTaskWithTraits(
- FROM_HERE, {base::MayBlock()},
- base::BindOnce(&Scheduler::DoWork, base::Unretained(this),
- std::move(work)));
-}
-
-void Scheduler::AddGenDependency(const base::FilePath& file) {
- base::AutoLock lock(lock_);
- gen_dependencies_.push_back(file);
-}
-
-std::vector<base::FilePath> Scheduler::GetGenDependencies() const {
- base::AutoLock lock(lock_);
- return gen_dependencies_;
-}
-
-void Scheduler::AddWrittenFile(const SourceFile& file) {
- base::AutoLock lock(lock_);
- written_files_.push_back(file);
-}
-
-void Scheduler::AddUnknownGeneratedInput(const Target* target,
- const SourceFile& file) {
- base::AutoLock lock(lock_);
- unknown_generated_inputs_.insert(std::make_pair(file, target));
-}
-
-void Scheduler::AddWriteRuntimeDepsTarget(const Target* target) {
- base::AutoLock lock(lock_);
- write_runtime_deps_targets_.push_back(target);
-}
-
-std::vector<const Target*> Scheduler::GetWriteRuntimeDepsTargets() const {
- base::AutoLock lock(lock_);
- return write_runtime_deps_targets_;
-}
-
-bool Scheduler::IsFileGeneratedByWriteRuntimeDeps(
- const OutputFile& file) const {
- base::AutoLock lock(lock_);
- // Number of targets should be quite small, so brute-force search is fine.
- for (const Target* target : write_runtime_deps_targets_) {
- if (file == target->write_runtime_deps_output()) {
- return true;
- }
- }
- return false;
-}
-
-std::multimap<SourceFile, const Target*>
- Scheduler::GetUnknownGeneratedInputs() const {
- base::AutoLock lock(lock_);
-
- // Remove all unknown inputs that were written files. These are OK as inputs
- // to build steps since they were written as a side-effect of running GN.
- //
- // It's assumed that this function is called once during cleanup to check for
- // errors, so performing this work in the lock doesn't matter.
- std::multimap<SourceFile, const Target*> filtered = unknown_generated_inputs_;
- for (const SourceFile& file : written_files_)
- filtered.erase(file);
-
- return filtered;
-}
-
-void Scheduler::ClearUnknownGeneratedInputsAndWrittenFiles() {
- base::AutoLock lock(lock_);
- unknown_generated_inputs_.clear();
- written_files_.clear();
-}
-
-void Scheduler::IncrementWorkCount() {
- work_count_.Increment();
-}
-
-void Scheduler::DecrementWorkCount() {
- if (!work_count_.Decrement()) {
- if (task_runner()->BelongsToCurrentThread()) {
- OnComplete();
- } else {
- task_runner()->PostTask(FROM_HERE, base::Bind(&Scheduler::OnComplete,
- base::Unretained(this)));
- }
- }
-}
-
-void Scheduler::LogOnMainThread(const std::string& verb,
- const std::string& msg) {
- OutputString(verb, DECORATION_YELLOW);
- OutputString(" " + msg + "\n");
-}
-
-void Scheduler::FailWithErrorOnMainThread(const Err& err) {
- err.PrintToStdout();
- runner_.Quit();
-}
-
-void Scheduler::DoWork(base::OnceClosure closure) {
- std::move(closure).Run();
- DecrementWorkCount();
- if (!pool_work_count_.Decrement()) {
- base::AutoLock auto_lock(pool_work_count_lock_);
- pool_work_count_cv_.Signal();
- }
-}
-
-void Scheduler::OnComplete() {
- // Should be called on the main thread.
- DCHECK(task_runner()->BelongsToCurrentThread());
- runner_.Quit();
-}
-
-void Scheduler::WaitForPoolTasks() {
- base::AutoLock lock(pool_work_count_lock_);
- while (!pool_work_count_.IsZero())
- pool_work_count_cv_.Wait();
-}
diff --git a/chromium/tools/gn/scheduler.h b/chromium/tools/gn/scheduler.h
deleted file mode 100644
index 02c1d8a756c..00000000000
--- a/chromium/tools/gn/scheduler.h
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_SCHEDULER_H_
-#define TOOLS_GN_SCHEDULER_H_
-
-#include <map>
-
-#include "base/atomic_ref_count.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "tools/gn/input_file_manager.h"
-#include "tools/gn/label.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/token.h"
-
-class Target;
-
-// Maintains the thread pool and error state.
-class Scheduler {
- public:
- Scheduler();
- ~Scheduler();
-
- bool Run();
-
- scoped_refptr<base::SingleThreadTaskRunner> task_runner() {
- return main_thread_task_runner_;
- }
-
- InputFileManager* input_file_manager() { return input_file_manager_.get(); }
-
- bool verbose_logging() const { return verbose_logging_; }
- void set_verbose_logging(bool v) { verbose_logging_ = v; }
-
- // TODO(brettw) data race on this access (benign?).
- bool is_failed() const { return is_failed_; }
-
- void Log(const std::string& verb, const std::string& msg);
- void FailWithError(const Err& err);
-
- void ScheduleWork(base::OnceClosure work);
-
- void Shutdown();
-
- // Declares that the given file was read and affected the build output.
- //
- // TODO(brettw) this is global rather than per-BuildSettings. If we
- // start using >1 build settings, then we probably want this to take a
- // BuildSettings object so we know the depdency on a per-build basis.
- // If moved, most of the Add/Get functions below should move as well.
- void AddGenDependency(const base::FilePath& file);
- std::vector<base::FilePath> GetGenDependencies() const;
-
- // Tracks calls to write_file for resolving with the unknown generated
- // inputs (see AddUnknownGeneratedInput below).
- void AddWrittenFile(const SourceFile& file);
-
- // Schedules a file to be written due to a target setting write_runtime_deps.
- void AddWriteRuntimeDepsTarget(const Target* entry);
- std::vector<const Target*> GetWriteRuntimeDepsTargets() const;
- bool IsFileGeneratedByWriteRuntimeDeps(const OutputFile& file) const;
-
- // Unknown generated inputs are files that a target declares as an input
- // in the output directory, but which aren't generated by any dependency.
- //
- // Some of these files will be files written by write_file and will be
- // GenDependencies (see AddWrittenFile above). There are OK and include
- // things like response files for scripts. Others cases will be ones where
- // the file is generated by a target that's not a dependency.
- //
- // In order to distinguish these two cases, the checking for these input
- // files needs to be done after all targets are complete. This also has the
- // nice side effect that if a target generates the file we can find it and
- // tell the user which dependency is missing.
- //
- // The result returned by GetUnknownGeneratedInputs will not count any files
- // that were written by write_file during execution.
- void AddUnknownGeneratedInput(const Target* target, const SourceFile& file);
- std::multimap<SourceFile, const Target*> GetUnknownGeneratedInputs() const;
- void ClearUnknownGeneratedInputsAndWrittenFiles(); // For testing.
-
- // We maintain a count of the things we need to do that works like a
- // refcount. When this reaches 0, the program exits.
- void IncrementWorkCount();
- void DecrementWorkCount();
-
- private:
- void LogOnMainThread(const std::string& verb, const std::string& msg);
- void FailWithErrorOnMainThread(const Err& err);
-
- void DoTargetFileWrite(const Target* target);
-
- void DoWork(base::OnceClosure closure);
-
- void OnComplete();
-
- // Waits for tasks scheduled via ScheduleWork() to complete their execution.
- void WaitForPoolTasks();
-
- // TaskRunner for the thread on which the Scheduler is initialized.
- const scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
-
- scoped_refptr<InputFileManager> input_file_manager_;
-
- base::RunLoop runner_;
-
- bool verbose_logging_;
-
- base::AtomicRefCount work_count_;
-
- // Number of tasks scheduled by ScheduleWork() that haven't completed their
- // execution.
- base::AtomicRefCount pool_work_count_;
-
- // Lock for |pool_work_count_cv_|.
- base::Lock pool_work_count_lock_;
-
- // Condition variable signaled when |pool_work_count_| reaches zero.
- base::ConditionVariable pool_work_count_cv_;
-
- mutable base::Lock lock_;
- bool is_failed_;
-
- // Used to track whether the worker pool has been shutdown. This is necessary
- // to clean up after tests that make a scheduler but don't run the message
- // loop.
- bool has_been_shutdown_;
-
- // Protected by the lock. See the corresponding Add/Get functions above.
- std::vector<base::FilePath> gen_dependencies_;
- std::vector<SourceFile> written_files_;
- std::vector<const Target*> write_runtime_deps_targets_;
- std::multimap<SourceFile, const Target*> unknown_generated_inputs_;
-
- DISALLOW_COPY_AND_ASSIGN(Scheduler);
-};
-
-extern Scheduler* g_scheduler;
-
-#endif // TOOLS_GN_SCHEDULER_H_
diff --git a/chromium/tools/gn/scope.cc b/chromium/tools/gn/scope.cc
deleted file mode 100644
index 145d6ad7c18..00000000000
--- a/chromium/tools/gn/scope.cc
+++ /dev/null
@@ -1,576 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/scope.h"
-
-#include <memory>
-
-#include "base/logging.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/template.h"
-
-namespace {
-
-// FLags set in the mode_flags_ of a scope. If a bit is set, it applies
-// recursively to all dependent scopes.
-const unsigned kProcessingBuildConfigFlag = 1;
-const unsigned kProcessingImportFlag = 2;
-
-// Returns true if this variable name should be considered private. Private
-// values start with an underscore, and are not imported from "gni" files
-// when processing an import.
-bool IsPrivateVar(const base::StringPiece& name) {
- return name.empty() || name[0] == '_';
-}
-
-} // namespace
-
-// Defaults to all false, which are the things least likely to cause errors.
-Scope::MergeOptions::MergeOptions()
- : clobber_existing(false),
- skip_private_vars(false),
- mark_dest_used(false) {}
-
-Scope::MergeOptions::~MergeOptions() = default;
-
-Scope::ProgrammaticProvider::~ProgrammaticProvider() {
- scope_->RemoveProvider(this);
-}
-
-Scope::Scope(const Settings* settings)
- : const_containing_(nullptr),
- mutable_containing_(nullptr),
- settings_(settings),
- mode_flags_(0),
- item_collector_(nullptr) {}
-
-Scope::Scope(Scope* parent)
- : const_containing_(nullptr),
- mutable_containing_(parent),
- settings_(parent->settings()),
- mode_flags_(0),
- item_collector_(nullptr),
- build_dependency_files_(parent->build_dependency_files_) {}
-
-Scope::Scope(const Scope* parent)
- : const_containing_(parent),
- mutable_containing_(nullptr),
- settings_(parent->settings()),
- mode_flags_(0),
- item_collector_(nullptr),
- build_dependency_files_(parent->build_dependency_files_) {}
-
-Scope::~Scope() = default;
-
-void Scope::DetachFromContaining() {
- const_containing_ = nullptr;
- mutable_containing_ = nullptr;
-}
-
-bool Scope::HasValues(SearchNested search_nested) const {
- DCHECK(search_nested == SEARCH_CURRENT);
- return !values_.empty();
-}
-
-const Value* Scope::GetValue(const base::StringPiece& ident,
- bool counts_as_used) {
- const Scope* found_in_scope = nullptr;
- return GetValueWithScope(ident, counts_as_used, &found_in_scope);
-}
-
-const Value* Scope::GetValueWithScope(const base::StringPiece& ident,
- bool counts_as_used,
- const Scope** found_in_scope) {
- // First check for programmatically-provided values.
- for (auto* provider : programmatic_providers_) {
- const Value* v = provider->GetProgrammaticValue(ident);
- if (v) {
- *found_in_scope = nullptr;
- return v;
- }
- }
-
- RecordMap::iterator found = values_.find(ident);
- if (found != values_.end()) {
- if (counts_as_used)
- found->second.used = true;
- *found_in_scope = this;
- return &found->second.value;
- }
-
- // Search in the parent scope.
- if (const_containing_)
- return const_containing_->GetValueWithScope(ident, found_in_scope);
- if (mutable_containing_) {
- return mutable_containing_->GetValueWithScope(ident, counts_as_used,
- found_in_scope);
- }
- return nullptr;
-}
-
-Value* Scope::GetMutableValue(const base::StringPiece& ident,
- SearchNested search_mode,
- bool counts_as_used) {
- // Don't do programmatic values, which are not mutable.
- RecordMap::iterator found = values_.find(ident);
- if (found != values_.end()) {
- if (counts_as_used)
- found->second.used = true;
- return &found->second.value;
- }
-
- // Search in the parent mutable scope if requested, but not const one.
- if (search_mode == SEARCH_NESTED && mutable_containing_) {
- return mutable_containing_->GetMutableValue(ident, Scope::SEARCH_NESTED,
- counts_as_used);
- }
- return nullptr;
-}
-
-base::StringPiece Scope::GetStorageKey(const base::StringPiece& ident) const {
- RecordMap::const_iterator found = values_.find(ident);
- if (found != values_.end())
- return found->first;
-
- // Search in parent scope.
- if (containing())
- return containing()->GetStorageKey(ident);
- return base::StringPiece();
-}
-
-const Value* Scope::GetValue(const base::StringPiece& ident) const {
- const Scope *found_in_scope = nullptr;
- return GetValueWithScope(ident, &found_in_scope);
-}
-
-const Value* Scope::GetValueWithScope(const base::StringPiece& ident,
- const Scope** found_in_scope) const {
- RecordMap::const_iterator found = values_.find(ident);
- if (found != values_.end()) {
- *found_in_scope = this;
- return &found->second.value;
- }
- if (containing())
- return containing()->GetValueWithScope(ident, found_in_scope);
- return nullptr;
-}
-
-Value* Scope::SetValue(const base::StringPiece& ident,
- Value v,
- const ParseNode* set_node) {
- Record& r = values_[ident]; // Clears any existing value.
- r.value = std::move(v);
- r.value.set_origin(set_node);
- return &r.value;
-}
-
-void Scope::RemoveIdentifier(const base::StringPiece& ident) {
- RecordMap::iterator found = values_.find(ident);
- if (found != values_.end())
- values_.erase(found);
-}
-
-void Scope::RemovePrivateIdentifiers() {
- // Do it in two phases to avoid mutating while iterating. Our hash map is
- // currently backed by several different vendor-specific implementations and
- // I'm not sure if all of them support mutating while iterating. Since this
- // is not perf-critical, do the safe thing.
- std::vector<base::StringPiece> to_remove;
- for (const auto& cur : values_) {
- if (IsPrivateVar(cur.first))
- to_remove.push_back(cur.first);
- }
-
- for (const auto& cur : to_remove)
- values_.erase(cur);
-}
-
-bool Scope::AddTemplate(const std::string& name, const Template* templ) {
- if (GetTemplate(name))
- return false;
- templates_[name] = templ;
- return true;
-}
-
-const Template* Scope::GetTemplate(const std::string& name) const {
- TemplateMap::const_iterator found = templates_.find(name);
- if (found != templates_.end())
- return found->second.get();
- if (containing())
- return containing()->GetTemplate(name);
- return nullptr;
-}
-
-void Scope::MarkUsed(const base::StringPiece& ident) {
- RecordMap::iterator found = values_.find(ident);
- if (found == values_.end()) {
- NOTREACHED();
- return;
- }
- found->second.used = true;
-}
-
-void Scope::MarkAllUsed() {
- for (auto& cur : values_)
- cur.second.used = true;
-}
-
-void Scope::MarkAllUsed(const std::set<std::string>& excluded_values) {
- for (auto& cur : values_) {
- if (!excluded_values.empty() &&
- excluded_values.find(cur.first.as_string()) != excluded_values.end()) {
- continue; // Skip this excluded value.
- }
- cur.second.used = true;
- }
-}
-
-void Scope::MarkUnused(const base::StringPiece& ident) {
- RecordMap::iterator found = values_.find(ident);
- if (found == values_.end()) {
- NOTREACHED();
- return;
- }
- found->second.used = false;
-}
-
-bool Scope::IsSetButUnused(const base::StringPiece& ident) const {
- RecordMap::const_iterator found = values_.find(ident);
- if (found != values_.end()) {
- if (!found->second.used) {
- return true;
- }
- }
- return false;
-}
-
-bool Scope::CheckForUnusedVars(Err* err) const {
- for (const auto& pair : values_) {
- if (!pair.second.used) {
- std::string help =
- "You set the variable \"" + pair.first.as_string() +
- "\" here and it was unused before it went\nout of scope.";
-
- const BinaryOpNode* binary = pair.second.value.origin()->AsBinaryOp();
- if (binary && binary->op().type() == Token::EQUAL) {
- // Make a nicer error message for normal var sets.
- *err = Err(binary->left()->GetRange(), "Assignment had no effect.",
- help);
- } else {
- // This will happen for internally-generated variables.
- *err = Err(pair.second.value.origin(), "Assignment had no effect.",
- help);
- }
- return false;
- }
- }
- return true;
-}
-
-void Scope::GetCurrentScopeValues(KeyValueMap* output) const {
- for (const auto& pair : values_)
- (*output)[pair.first] = pair.second.value;
-}
-
-bool Scope::NonRecursiveMergeTo(Scope* dest,
- const MergeOptions& options,
- const ParseNode* node_for_err,
- const char* desc_for_err,
- Err* err) const {
- // Values.
- for (const auto& pair : values_) {
- const base::StringPiece& current_name = pair.first;
- if (options.skip_private_vars && IsPrivateVar(current_name))
- continue; // Skip this private var.
- if (!options.excluded_values.empty() &&
- options.excluded_values.find(current_name.as_string()) !=
- options.excluded_values.end()) {
- continue; // Skip this excluded value.
- }
-
- const Value& new_value = pair.second.value;
- if (!options.clobber_existing) {
- const Value* existing_value = dest->GetValue(current_name);
- if (existing_value && new_value != *existing_value) {
- // Value present in both the source and the dest.
- std::string desc_string(desc_for_err);
- *err = Err(node_for_err, "Value collision.",
- "This " + desc_string + " contains \"" +
- current_name.as_string() + "\"");
- err->AppendSubErr(
- Err(pair.second.value, "defined here.",
- "Which would clobber the one in your current scope"));
- err->AppendSubErr(
- Err(*existing_value, "defined here.",
- "Executing " + desc_string +
- " should not conflict with anything "
- "in the current\nscope unless the values are identical."));
- return false;
- }
- }
- dest->values_[current_name] = pair.second;
-
- if (options.mark_dest_used)
- dest->MarkUsed(current_name);
- }
-
- // Target defaults are owning pointers.
- for (const auto& pair : target_defaults_) {
- const std::string& current_name = pair.first;
- if (!options.excluded_values.empty() &&
- options.excluded_values.find(current_name) !=
- options.excluded_values.end()) {
- continue; // Skip the excluded value.
- }
-
- if (!options.clobber_existing) {
- const Scope* dest_defaults = dest->GetTargetDefaults(current_name);
- if (dest_defaults) {
- if (RecordMapValuesEqual(pair.second->values_,
- dest_defaults->values_)) {
- // Values of the two defaults are equivalent, just ignore the
- // collision.
- continue;
- } else {
- // TODO(brettw) it would be nice to know the origin of a
- // set_target_defaults so we can give locations for the colliding
- // target defaults.
- std::string desc_string(desc_for_err);
- *err = Err(node_for_err, "Target defaults collision.",
- "This " + desc_string +
- " contains target defaults for\n"
- "\"" +
- current_name +
- "\" which would clobber one for the\n"
- "same target type in your current scope. It's "
- "unfortunate that "
- "I'm too stupid\nto tell you the location of where "
- "the target "
- "defaults were set. Usually\nthis happens in the "
- "BUILDCONFIG.gn "
- "file or in a related .gni file.\n");
- return false;
- }
- }
- }
-
- std::unique_ptr<Scope>& dest_scope = dest->target_defaults_[current_name];
- dest_scope = std::make_unique<Scope>(settings_);
- pair.second->NonRecursiveMergeTo(dest_scope.get(), options, node_for_err,
- "<SHOULDN'T HAPPEN>", err);
- }
-
- // Sources assignment filter.
- if (sources_assignment_filter_) {
- if (!options.clobber_existing) {
- if (dest->GetSourcesAssignmentFilter()) {
- // Sources assignment filter present in both the source and the dest.
- std::string desc_string(desc_for_err);
- *err = Err(node_for_err, "Assignment filter collision.",
- "The " + desc_string +
- " contains a sources_assignment_filter "
- "which\nwould clobber the one in your current scope.");
- return false;
- }
- }
- dest->sources_assignment_filter_ =
- std::make_unique<PatternList>(*sources_assignment_filter_);
- }
-
- // Templates.
- for (const auto& pair : templates_) {
- const std::string& current_name = pair.first;
- if (options.skip_private_vars && IsPrivateVar(current_name))
- continue; // Skip this private template.
- if (!options.excluded_values.empty() &&
- options.excluded_values.find(current_name) !=
- options.excluded_values.end()) {
- continue; // Skip the excluded value.
- }
-
- if (!options.clobber_existing) {
- const Template* existing_template = dest->GetTemplate(current_name);
- // Since templates are refcounted, we can check if it's the same one by
- // comparing pointers.
- if (existing_template && pair.second.get() != existing_template) {
- // Rule present in both the source and the dest, and they're not the
- // same one.
- std::string desc_string(desc_for_err);
- *err = Err(node_for_err, "Template collision.",
- "This " + desc_string + " contains a template \"" +
- current_name + "\"");
- err->AppendSubErr(
- Err(pair.second->GetDefinitionRange(), "defined here.",
- "Which would clobber the one in your current scope"));
- err->AppendSubErr(Err(existing_template->GetDefinitionRange(),
- "defined here.",
- "Executing " + desc_string +
- " should not conflict with anything "
- "in the current\nscope."));
- return false;
- }
- }
-
- // Be careful to delete any pointer we're about to clobber.
- dest->templates_[current_name] = pair.second;
- }
-
- // Propogate build dependency files,
- dest->build_dependency_files_.insert(build_dependency_files_.begin(),
- build_dependency_files_.end());
-
- return true;
-}
-
-std::unique_ptr<Scope> Scope::MakeClosure() const {
- std::unique_ptr<Scope> result;
- if (const_containing_) {
- // We reached the top of the mutable scope stack. The result scope just
- // references the const scope (which will never change).
- result = std::make_unique<Scope>(const_containing_);
- } else if (mutable_containing_) {
- // There are more nested mutable scopes. Recursively go up the stack to
- // get the closure.
- result = mutable_containing_->MakeClosure();
- } else {
- // This is a standalone scope, just copy it.
- result = std::make_unique<Scope>(settings_);
- }
-
- // Want to clobber since we've flattened some nested scopes, and our parent
- // scope may have a duplicate value set.
- MergeOptions options;
- options.clobber_existing = true;
-
- // Add in our variables and we're done.
- Err err;
- NonRecursiveMergeTo(result.get(), options, nullptr, "<SHOULDN'T HAPPEN>",
- &err);
- DCHECK(!err.has_error());
- return result;
-}
-
-Scope* Scope::MakeTargetDefaults(const std::string& target_type) {
- std::unique_ptr<Scope>& dest = target_defaults_[target_type];
- dest = std::make_unique<Scope>(settings_);
- return dest.get();
-}
-
-const Scope* Scope::GetTargetDefaults(const std::string& target_type) const {
- NamedScopeMap::const_iterator found = target_defaults_.find(target_type);
- if (found != target_defaults_.end())
- return found->second.get();
- if (containing())
- return containing()->GetTargetDefaults(target_type);
- return nullptr;
-}
-
-const PatternList* Scope::GetSourcesAssignmentFilter() const {
- if (sources_assignment_filter_)
- return sources_assignment_filter_.get();
- if (containing())
- return containing()->GetSourcesAssignmentFilter();
- return nullptr;
-}
-
-void Scope::SetProcessingBuildConfig() {
- DCHECK((mode_flags_ & kProcessingBuildConfigFlag) == 0);
- mode_flags_ |= kProcessingBuildConfigFlag;
-}
-
-void Scope::ClearProcessingBuildConfig() {
- DCHECK(mode_flags_ & kProcessingBuildConfigFlag);
- mode_flags_ &= ~(kProcessingBuildConfigFlag);
-}
-
-bool Scope::IsProcessingBuildConfig() const {
- if (mode_flags_ & kProcessingBuildConfigFlag)
- return true;
- if (containing())
- return containing()->IsProcessingBuildConfig();
- return false;
-}
-
-void Scope::SetProcessingImport() {
- DCHECK((mode_flags_ & kProcessingImportFlag) == 0);
- mode_flags_ |= kProcessingImportFlag;
-}
-
-void Scope::ClearProcessingImport() {
- DCHECK(mode_flags_ & kProcessingImportFlag);
- mode_flags_ &= ~(kProcessingImportFlag);
-}
-
-bool Scope::IsProcessingImport() const {
- if (mode_flags_ & kProcessingImportFlag)
- return true;
- if (containing())
- return containing()->IsProcessingImport();
- return false;
-}
-
-const SourceDir& Scope::GetSourceDir() const {
- if (!source_dir_.is_null())
- return source_dir_;
- if (containing())
- return containing()->GetSourceDir();
- return source_dir_;
-}
-
-void Scope::AddBuildDependencyFile(const SourceFile& build_dependency_file) {
- build_dependency_files_.insert(build_dependency_file);
-}
-
-Scope::ItemVector* Scope::GetItemCollector() {
- if (item_collector_)
- return item_collector_;
- if (mutable_containing())
- return mutable_containing()->GetItemCollector();
- return nullptr;
-}
-
-void Scope::SetProperty(const void* key, void* value) {
- if (!value) {
- DCHECK(properties_.find(key) != properties_.end());
- properties_.erase(key);
- } else {
- properties_[key] = value;
- }
-}
-
-void* Scope::GetProperty(const void* key, const Scope** found_on_scope) const {
- PropertyMap::const_iterator found = properties_.find(key);
- if (found != properties_.end()) {
- if (found_on_scope)
- *found_on_scope = this;
- return found->second;
- }
- if (containing())
- return containing()->GetProperty(key, found_on_scope);
- return nullptr;
-}
-
-void Scope::AddProvider(ProgrammaticProvider* p) {
- programmatic_providers_.insert(p);
-}
-
-void Scope::RemoveProvider(ProgrammaticProvider* p) {
- DCHECK(programmatic_providers_.find(p) != programmatic_providers_.end());
- programmatic_providers_.erase(p);
-}
-
-// static
-bool Scope::RecordMapValuesEqual(const RecordMap& a, const RecordMap& b) {
- if (a.size() != b.size())
- return false;
- for (const auto& pair : a) {
- const auto& found_b = b.find(pair.first);
- if (found_b == b.end())
- return false; // Item in 'a' but not 'b'.
- if (pair.second.value != found_b->second.value)
- return false; // Values for variable in 'a' and 'b' are different.
- }
- return true;
-}
diff --git a/chromium/tools/gn/scope.h b/chromium/tools/gn/scope.h
deleted file mode 100644
index 9e683d26627..00000000000
--- a/chromium/tools/gn/scope.h
+++ /dev/null
@@ -1,397 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_SCOPE_H_
-#define TOOLS_GN_SCOPE_H_
-
-#include <map>
-#include <memory>
-#include <set>
-#include <utility>
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "tools/gn/err.h"
-#include "tools/gn/pattern.h"
-#include "tools/gn/source_dir.h"
-#include "tools/gn/value.h"
-
-class Item;
-class ParseNode;
-class Settings;
-class SourceFile;
-class Template;
-
-// Scope for the script execution.
-//
-// Scopes are nested. Writing goes into the toplevel scope, reading checks
-// values resursively down the stack until a match is found or there are no
-// more containing scopes.
-//
-// A containing scope can be const or non-const. The const containing scope is
-// used primarily to refer to the master build config which is shared across
-// many invocations. A const containing scope, however, prevents us from
-// marking variables "used" which prevents us from issuing errors on unused
-// variables. So you should use a non-const containing scope whenever possible.
-class Scope {
- public:
- typedef base::hash_map<base::StringPiece, Value, base::StringPieceHash>
- KeyValueMap;
- // Holds an owning list of Items.
- typedef std::vector<std::unique_ptr<Item>> ItemVector;
-
- // A flag to indicate whether a function should recurse into nested scopes,
- // or only operate on the current scope.
- enum SearchNested {
- SEARCH_NESTED,
- SEARCH_CURRENT
- };
-
- // Allows code to provide values for built-in variables. This class will
- // automatically register itself on construction and deregister itself on
- // destruction.
- class ProgrammaticProvider {
- public:
- explicit ProgrammaticProvider(Scope* scope) : scope_(scope) {
- scope_->AddProvider(this);
- }
- virtual ~ProgrammaticProvider();
-
- // Returns a non-null value if the given value can be programmatically
- // generated, or NULL if there is none.
- virtual const Value* GetProgrammaticValue(
- const base::StringPiece& ident) = 0;
-
- protected:
- Scope* scope_;
- };
-
- // Options for configuring scope merges.
- struct MergeOptions {
- MergeOptions();
- ~MergeOptions();
-
- // When set, all existing avlues in the destination scope will be
- // overwritten.
- //
- // When false, it will be an error to merge a variable into another scope
- // where a variable with the same name is already set. The exception is
- // if both of the variables have the same value (which happens if you
- // somehow multiply import the same file, for example). This case will be
- // ignored since there is nothing getting lost.
- bool clobber_existing;
-
- // When true, private variables (names beginning with an underscore) will
- // be copied to the destination scope. When false, private values will be
- // skipped.
- bool skip_private_vars;
-
- // When set, values copied to the destination scope will be marked as used
- // so won't trigger an unused variable warning. You want this when doing an
- // import, for example, or files that don't need a variable from the .gni
- // file will throw an error.
- bool mark_dest_used;
-
- // When set, those variables are not merged.
- std::set<std::string> excluded_values;
- };
-
- // Creates an empty toplevel scope.
- explicit Scope(const Settings* settings);
-
- // Creates a dependent scope.
- explicit Scope(Scope* parent);
- explicit Scope(const Scope* parent);
-
- ~Scope();
-
- const Settings* settings() const { return settings_; }
-
- // See the const_/mutable_containing_ var declarations below. Yes, it's a
- // bit weird that we can have a const pointer to the "mutable" one.
- Scope* mutable_containing() { return mutable_containing_; }
- const Scope* mutable_containing() const { return mutable_containing_; }
- const Scope* const_containing() const { return const_containing_; }
- const Scope* containing() const {
- return mutable_containing_ ? mutable_containing_ : const_containing_;
- }
-
- // Clears any references to containing scopes. This scope will now be
- // self-sufficient.
- void DetachFromContaining();
-
- // Returns true if the scope has any values set. This does not check other
- // things that may be set like templates or defaults.
- //
- // Currently this does not search nested scopes and this will assert if you
- // want to search nested scopes. The enum is passed so the callers are
- // unambiguous about nested scope handling. This can be added if needed.
- bool HasValues(SearchNested search_nested) const;
-
- // Returns NULL if there's no such value.
- //
- // counts_as_used should be set if the variable is being read in a way that
- // should count for unused variable checking.
- //
- // found_in_scope is set to the scope that contains the definition of the
- // ident. If the value was provided programmatically (like host_cpu),
- // found_in_scope will be set to null.
- const Value* GetValue(const base::StringPiece& ident,
- bool counts_as_used);
- const Value* GetValue(const base::StringPiece& ident) const;
- const Value* GetValueWithScope(const base::StringPiece& ident,
- const Scope** found_in_scope) const;
- const Value* GetValueWithScope(const base::StringPiece& ident,
- bool counts_as_used,
- const Scope** found_in_scope);
-
- // Returns the requested value as a mutable one if possible. If the value
- // is not found in a mutable scope, then returns null. Note that the value
- // could still exist in a const scope, so GetValue() could still return
- // non-null in this case.
- //
- // Say you have a local scope that then refers to the const root scope from
- // the master build config. You can't change the values from the master
- // build config (it's read-only so it can be read from multiple threads
- // without locking). Read-only operations would work on values from the root
- // scope, but write operations would only work on values in the derived
- // scope(s).
- //
- // Be careful when calling this. It's not normally correct to modify values,
- // but you should instead do a new Set each time.
- //
- // Consider this code:
- // a = 5
- // {
- // a = 6
- // }
- // The 6 should get set on the nested scope rather than modify the value
- // in the outer one.
- Value* GetMutableValue(const base::StringPiece& ident,
- SearchNested search_mode,
- bool counts_as_used);
-
- // Returns the StringPiece used to identify the value. This string piece
- // will have the same contents as "ident" passed in, but may point to a
- // different underlying buffer. This is useful because this StringPiece is
- // static and won't be deleted for the life of the program, so it can be used
- // as keys in places that may outlive a temporary. It will return an empty
- // string for programmatic and nonexistant values.
- base::StringPiece GetStorageKey(const base::StringPiece& ident) const;
-
- // The set_node indicates the statement that caused the set, for displaying
- // errors later. Returns a pointer to the value in the current scope (a copy
- // is made for storage).
- Value* SetValue(const base::StringPiece& ident,
- Value v,
- const ParseNode* set_node);
-
- // Removes the value with the given identifier if it exists on the current
- // scope. This does not search recursive scopes. Does nothing if not found.
- void RemoveIdentifier(const base::StringPiece& ident);
-
- // Removes from this scope all identifiers and templates that are considered
- // private.
- void RemovePrivateIdentifiers();
-
- // Templates associated with this scope. A template can only be set once, so
- // AddTemplate will fail and return false if a rule with that name already
- // exists. GetTemplate returns NULL if the rule doesn't exist, and it will
- // check all containing scoped rescursively.
- bool AddTemplate(const std::string& name, const Template* templ);
- const Template* GetTemplate(const std::string& name) const;
-
- // Marks the given identifier as (un)used in the current scope.
- void MarkUsed(const base::StringPiece& ident);
- void MarkAllUsed();
- void MarkAllUsed(const std::set<std::string>& excluded_values);
- void MarkUnused(const base::StringPiece& ident);
-
- // Checks to see if the scope has a var set that hasn't been used. This is
- // called before replacing the var with a different one. It does not check
- // containing scopes.
- //
- // If the identifier is present but hasnn't been used, return true.
- bool IsSetButUnused(const base::StringPiece& ident) const;
-
- // Checks the scope to see if any values were set but not used, and fills in
- // the error and returns false if they were.
- bool CheckForUnusedVars(Err* err) const;
-
- // Returns all values set in the current scope, without going to the parent
- // scopes.
- void GetCurrentScopeValues(KeyValueMap* output) const;
-
- // Copies this scope's values into the destination. Values from the
- // containing scope(s) (normally shadowed into the current one) will not be
- // copied, neither will the reference to the containing scope (this is why
- // it's "non-recursive").
- //
- // This is used in different contexts. When generating the error, the given
- // parse node will be blamed, and the given desc will be used to describe
- // the operation that doesn't support doing this. For example, desc_for_err
- // would be "import" when doing an import, and the error string would say
- // something like "The import contains...".
- bool NonRecursiveMergeTo(Scope* dest,
- const MergeOptions& options,
- const ParseNode* node_for_err,
- const char* desc_for_err,
- Err* err) const;
-
- // Constructs a scope that is a copy of the current one. Nested scopes will
- // be collapsed until we reach a const containing scope. Private values will
- // be included. The resulting closure will reference the const containing
- // scope as its containing scope (since we assume the const scope won't
- // change, we don't have to copy its values).
- std::unique_ptr<Scope> MakeClosure() const;
-
- // Makes an empty scope with the given name. Overwrites any existing one.
- Scope* MakeTargetDefaults(const std::string& target_type);
-
- // Gets the scope associated with the given target name, or null if it hasn't
- // been set.
- const Scope* GetTargetDefaults(const std::string& target_type) const;
-
- // Filter to apply when the sources variable is assigned. May return NULL.
- const PatternList* GetSourcesAssignmentFilter() const;
- void set_sources_assignment_filter(std::unique_ptr<PatternList> f) {
- sources_assignment_filter_ = std::move(f);
- }
-
- // Indicates if we're currently processing the build configuration file.
- // This is true when processing the config file for any toolchain.
- //
- // To set or clear the flag, it must currently be in the opposite state in
- // the current scope. Note that querying the state of the flag recursively
- // checks all containing scopes until it reaches the top or finds the flag
- // set.
- void SetProcessingBuildConfig();
- void ClearProcessingBuildConfig();
- bool IsProcessingBuildConfig() const;
-
- // Indicates if we're currently processing an import file.
- //
- // See SetProcessingBaseConfig for how flags work.
- void SetProcessingImport();
- void ClearProcessingImport();
- bool IsProcessingImport() const;
-
- // The source directory associated with this scope. This will check embedded
- // scopes until it finds a nonempty source directory. This will default to
- // an empty dir if no containing scope has a source dir set.
- const SourceDir& GetSourceDir() const;
- void set_source_dir(const SourceDir& d) { source_dir_ = d; }
-
- // Set of files that may affect the execution of this scope. Note that this
- // set is constructed conservatively, meanining that every file that can
- // potentially affect this scope is included, but not necessarily every change
- // to these files will affect this scope.
- const std::set<SourceFile>& build_dependency_files() const {
- return build_dependency_files_;
- }
- void AddBuildDependencyFile(const SourceFile& build_dependency_file);
-
- // The item collector is where Items (Targets, Configs, etc.) go that have
- // been defined. If a scope can generate items, this non-owning pointer will
- // point to the storage for such items. The creator of this scope will be
- // responsible for setting up the collector and then dealing with the
- // collected items once execution of the context is complete.
- //
- // The items in a scope are collected as we go and then dispatched at the end
- // of execution of a scope so that we can query the previously-generated
- // targets (like getting the outputs).
- //
- // This can be null if the current scope can not generate items (like for
- // imports and such).
- //
- // When retrieving the collector, the non-const scopes are recursively
- // queried. The collector is not copied for closures, etc.
- void set_item_collector(ItemVector* collector) {
- item_collector_ = collector;
- }
- ItemVector* GetItemCollector();
-
- // Properties are opaque pointers that code can use to set state on a Scope
- // that it can retrieve later.
- //
- // The key should be a pointer to some use-case-specific object (to avoid
- // collisions, otherwise it doesn't matter). Memory management is up to the
- // setter. Setting the value to NULL will delete the property.
- //
- // Getting a property recursively searches all scopes, and the optional
- // |found_on_scope| variable will be filled with the actual scope containing
- // the key (if the pointer is non-NULL).
- void SetProperty(const void* key, void* value);
- void* GetProperty(const void* key, const Scope** found_on_scope) const;
-
- private:
- friend class ProgrammaticProvider;
-
- struct Record {
- Record() : used(false) {}
- explicit Record(const Value& v) : used(false), value(v) {}
-
- bool used; // Set to true when the variable is used.
- Value value;
- };
-
- typedef base::hash_map<base::StringPiece, Record, base::StringPieceHash>
- RecordMap;
-
- void AddProvider(ProgrammaticProvider* p);
- void RemoveProvider(ProgrammaticProvider* p);
-
- // Returns true if the two RecordMaps contain the same values (the origins
- // of the values may be different).
- static bool RecordMapValuesEqual(const RecordMap& a, const RecordMap& b);
-
- // Scopes can have no containing scope (both null), a mutable containing
- // scope, or a const containing scope. The reason is that when we're doing
- // a new target, we want to refer to the base_config scope which will be read
- // by multiple threads at the same time, so we REALLY want it to be const.
- // When you jsut do a nested {}, however, we sometimes want to be able to
- // change things (especially marking unused vars).
- const Scope* const_containing_;
- Scope* mutable_containing_;
-
- const Settings* settings_;
-
- // Bits set for different modes. See the flag definitions in the .cc file
- // for more.
- unsigned mode_flags_;
-
- RecordMap values_;
-
- // Note that this can't use string pieces since the names are constructed from
- // Values which might be deallocated before this goes out of scope.
- typedef base::hash_map<std::string, std::unique_ptr<Scope>> NamedScopeMap;
- NamedScopeMap target_defaults_;
-
- // Null indicates not set and that we should fallback to the containing
- // scope's filter.
- std::unique_ptr<PatternList> sources_assignment_filter_;
-
- // Owning pointers, must be deleted.
- typedef std::map<std::string, scoped_refptr<const Template> > TemplateMap;
- TemplateMap templates_;
-
- ItemVector* item_collector_;
-
- // Opaque pointers. See SetProperty() above.
- typedef std::map<const void*, void*> PropertyMap;
- PropertyMap properties_;
-
- typedef std::set<ProgrammaticProvider*> ProviderSet;
- ProviderSet programmatic_providers_;
-
- SourceDir source_dir_;
-
- std::set<SourceFile> build_dependency_files_;
-
- DISALLOW_COPY_AND_ASSIGN(Scope);
-};
-
-#endif // TOOLS_GN_SCOPE_H_
diff --git a/chromium/tools/gn/scope_per_file_provider.cc b/chromium/tools/gn/scope_per_file_provider.cc
deleted file mode 100644
index a577129c59b..00000000000
--- a/chromium/tools/gn/scope_per_file_provider.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/scope_per_file_provider.h"
-
-#include <memory>
-
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/value.h"
-#include "tools/gn/variables.h"
-
-ScopePerFileProvider::ScopePerFileProvider(Scope* scope,
- bool allow_target_vars)
- : ProgrammaticProvider(scope),
- allow_target_vars_(allow_target_vars) {
-}
-
-ScopePerFileProvider::~ScopePerFileProvider() = default;
-
-const Value* ScopePerFileProvider::GetProgrammaticValue(
- const base::StringPiece& ident) {
- if (ident == variables::kCurrentToolchain)
- return GetCurrentToolchain();
- if (ident == variables::kDefaultToolchain)
- return GetDefaultToolchain();
- if (ident == variables::kPythonPath)
- return GetPythonPath();
-
- if (ident == variables::kRootBuildDir)
- return GetRootBuildDir();
- if (ident == variables::kRootGenDir)
- return GetRootGenDir();
- if (ident == variables::kRootOutDir)
- return GetRootOutDir();
-
- if (allow_target_vars_) {
- if (ident == variables::kTargetGenDir)
- return GetTargetGenDir();
- if (ident == variables::kTargetOutDir)
- return GetTargetOutDir();
- }
- return nullptr;
-}
-
-const Value* ScopePerFileProvider::GetCurrentToolchain() {
- if (!current_toolchain_) {
- current_toolchain_ = std::make_unique<Value>(
- nullptr,
- scope_->settings()->toolchain_label().GetUserVisibleName(false));
- }
- return current_toolchain_.get();
-}
-
-const Value* ScopePerFileProvider::GetDefaultToolchain() {
- if (!default_toolchain_) {
- default_toolchain_ = std::make_unique<Value>(
- nullptr,
- scope_->settings()->default_toolchain_label().GetUserVisibleName(
- false));
- }
- return default_toolchain_.get();
-}
-
-const Value* ScopePerFileProvider::GetPythonPath() {
- if (!python_path_) {
- python_path_ = std::make_unique<Value>(
- nullptr,
- FilePathToUTF8(scope_->settings()->build_settings()->python_path()));
- }
- return python_path_.get();
-}
-
-const Value* ScopePerFileProvider::GetRootBuildDir() {
- if (!root_build_dir_) {
- root_build_dir_ = std::make_unique<Value>(
- nullptr, DirectoryWithNoLastSlash(
- scope_->settings()->build_settings()->build_dir()));
- }
- return root_build_dir_.get();
-}
-
-const Value* ScopePerFileProvider::GetRootGenDir() {
- if (!root_gen_dir_) {
- root_gen_dir_ = std::make_unique<Value>(
- nullptr, DirectoryWithNoLastSlash(GetBuildDirAsSourceDir(
- BuildDirContext(scope_), BuildDirType::GEN)));
- }
- return root_gen_dir_.get();
-}
-
-const Value* ScopePerFileProvider::GetRootOutDir() {
- if (!root_out_dir_) {
- root_out_dir_ = std::make_unique<Value>(
- nullptr, DirectoryWithNoLastSlash(GetScopeCurrentBuildDirAsSourceDir(
- scope_, BuildDirType::TOOLCHAIN_ROOT)));
- }
- return root_out_dir_.get();
-}
-
-const Value* ScopePerFileProvider::GetTargetGenDir() {
- if (!target_gen_dir_) {
- target_gen_dir_ = std::make_unique<Value>(
- nullptr, DirectoryWithNoLastSlash(GetScopeCurrentBuildDirAsSourceDir(
- scope_, BuildDirType::GEN)));
- }
- return target_gen_dir_.get();
-}
-
-const Value* ScopePerFileProvider::GetTargetOutDir() {
- if (!target_out_dir_) {
- target_out_dir_ = std::make_unique<Value>(
- nullptr, DirectoryWithNoLastSlash(GetScopeCurrentBuildDirAsSourceDir(
- scope_, BuildDirType::OBJ)));
- }
- return target_out_dir_.get();
-}
diff --git a/chromium/tools/gn/scope_per_file_provider.h b/chromium/tools/gn/scope_per_file_provider.h
deleted file mode 100644
index ac0d8720615..00000000000
--- a/chromium/tools/gn/scope_per_file_provider.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_SCOPE_PER_FILE_PROVIDER_H_
-#define TOOLS_GN_SCOPE_PER_FILE_PROVIDER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "tools/gn/scope.h"
-
-// ProgrammaticProvider for a scope to provide it with per-file built-in
-// variable support.
-class ScopePerFileProvider : public Scope::ProgrammaticProvider {
- public:
- // allow_target_vars allows the target-related variables to get resolved.
- // When allow_target_vars is unset, the target-related values will be
- // undefined to GN script.
- ScopePerFileProvider(Scope* scope, bool allow_target_vars);
- ~ScopePerFileProvider() override;
-
- // ProgrammaticProvider implementation.
- const Value* GetProgrammaticValue(const base::StringPiece& ident) override;
-
- private:
- const Value* GetCurrentToolchain();
- const Value* GetDefaultToolchain();
- const Value* GetPythonPath();
- const Value* GetRootBuildDir();
- const Value* GetRootGenDir();
- const Value* GetRootOutDir();
- const Value* GetTargetGenDir();
- const Value* GetTargetOutDir();
-
- bool allow_target_vars_;
-
- // All values are lazily created.
- std::unique_ptr<Value> current_toolchain_;
- std::unique_ptr<Value> default_toolchain_;
- std::unique_ptr<Value> python_path_;
- std::unique_ptr<Value> root_build_dir_;
- std::unique_ptr<Value> root_gen_dir_;
- std::unique_ptr<Value> root_out_dir_;
- std::unique_ptr<Value> target_gen_dir_;
- std::unique_ptr<Value> target_out_dir_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopePerFileProvider);
-};
-
-#endif // TOOLS_GN_SCOPE_PER_FILE_PROVIDER_H_
diff --git a/chromium/tools/gn/scope_per_file_provider_unittest.cc b/chromium/tools/gn/scope_per_file_provider_unittest.cc
deleted file mode 100644
index d016a1e1f5c..00000000000
--- a/chromium/tools/gn/scope_per_file_provider_unittest.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/scope_per_file_provider.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/test_with_scope.h"
-#include "tools/gn/toolchain.h"
-#include "tools/gn/variables.h"
-
-TEST(ScopePerFileProvider, Expected) {
- TestWithScope test;
-
-// Prevent horrible wrapping of calls below.
-#define GPV(val) provider.GetProgrammaticValue(val)->string_value()
-
- // Test the default toolchain.
- {
- Scope scope(test.settings());
- scope.set_source_dir(SourceDir("//source/"));
- ScopePerFileProvider provider(&scope, true);
-
- EXPECT_EQ("//toolchain:default", GPV(variables::kCurrentToolchain));
- // TODO(brettw) this test harness does not set up the Toolchain manager
- // which is the source of this value, so we can't test this yet.
- //EXPECT_EQ("//toolchain:default", GPV(variables::kDefaultToolchain));
- EXPECT_EQ("//out/Debug", GPV(variables::kRootBuildDir));
- EXPECT_EQ("//out/Debug/gen", GPV(variables::kRootGenDir));
- EXPECT_EQ("//out/Debug", GPV(variables::kRootOutDir));
- EXPECT_EQ("//out/Debug/gen/source", GPV(variables::kTargetGenDir));
- EXPECT_EQ("//out/Debug/obj/source", GPV(variables::kTargetOutDir));
- }
-
- // Test some with an alternate toolchain.
- {
- Settings settings(test.build_settings(), "tc/");
- Toolchain toolchain(&settings, Label(SourceDir("//toolchain/"), "tc"));
- settings.set_toolchain_label(toolchain.label());
-
- Scope scope(&settings);
- scope.set_source_dir(SourceDir("//source/"));
- ScopePerFileProvider provider(&scope, true);
-
- EXPECT_EQ("//toolchain:tc", GPV(variables::kCurrentToolchain));
- // See above.
- //EXPECT_EQ("//toolchain:default", GPV(variables::kDefaultToolchain));
- EXPECT_EQ("//out/Debug", GPV(variables::kRootBuildDir));
- EXPECT_EQ("//out/Debug/tc/gen", GPV(variables::kRootGenDir));
- EXPECT_EQ("//out/Debug/tc", GPV(variables::kRootOutDir));
- EXPECT_EQ("//out/Debug/tc/gen/source", GPV(variables::kTargetGenDir));
- EXPECT_EQ("//out/Debug/tc/obj/source", GPV(variables::kTargetOutDir));
- }
-}
diff --git a/chromium/tools/gn/scope_unittest.cc b/chromium/tools/gn/scope_unittest.cc
deleted file mode 100644
index ce3fe0b1f28..00000000000
--- a/chromium/tools/gn/scope_unittest.cc
+++ /dev/null
@@ -1,336 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/scope.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/template.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-bool HasStringValueEqualTo(const Scope* scope,
- const char* name,
- const char* expected_value) {
- const Value* value = scope->GetValue(name);
- if (!value)
- return false;
- if (value->type() != Value::STRING)
- return false;
- return value->string_value() == expected_value;
-}
-
-bool ContainsBuildDependencyFile(const Scope* scope,
- const SourceFile& source_file) {
- const auto& build_dependency_files = scope->build_dependency_files();
- return build_dependency_files.end() !=
- build_dependency_files.find(source_file);
-}
-
-} // namespace
-
-TEST(Scope, InheritBuildDependencyFilesFromParent) {
- TestWithScope setup;
- SourceFile source_file = SourceFile("//a/BUILD.gn");
- setup.scope()->AddBuildDependencyFile(source_file);
-
- Scope new_scope(setup.scope());
- EXPECT_EQ(1U, new_scope.build_dependency_files().size());
- EXPECT_TRUE(ContainsBuildDependencyFile(&new_scope, source_file));
-}
-
-TEST(Scope, NonRecursiveMergeTo) {
- TestWithScope setup;
-
- // Make a pretend parse node with proper tracking that we can blame for the
- // given value.
- InputFile input_file(SourceFile("//foo"));
- Token assignment_token(Location(&input_file, 1, 1, 1), Token::STRING,
- "\"hello\"");
- LiteralNode assignment;
- assignment.set_value(assignment_token);
-
- // Add some values to the scope.
- Value old_value(&assignment, "hello");
- setup.scope()->SetValue("v", old_value, &assignment);
- base::StringPiece private_var_name("_private");
- setup.scope()->SetValue(private_var_name, old_value, &assignment);
-
- // Add some templates to the scope.
- FunctionCallNode templ_definition;
- scoped_refptr<Template> templ(new Template(setup.scope(), &templ_definition));
- setup.scope()->AddTemplate("templ", templ.get());
- scoped_refptr<Template> private_templ(
- new Template(setup.scope(), &templ_definition));
- setup.scope()->AddTemplate("_templ", private_templ.get());
-
- // Detect collisions of values' values.
- {
- Scope new_scope(setup.settings());
- Value new_value(&assignment, "goodbye");
- new_scope.SetValue("v", new_value, &assignment);
-
- Err err;
- EXPECT_FALSE(setup.scope()->NonRecursiveMergeTo(
- &new_scope, Scope::MergeOptions(),
- &assignment, "error", &err));
- EXPECT_TRUE(err.has_error());
- }
-
- // Template name collisions.
- {
- Scope new_scope(setup.settings());
-
- scoped_refptr<Template> new_templ(
- new Template(&new_scope, &templ_definition));
- new_scope.AddTemplate("templ", new_templ.get());
-
- Err err;
- EXPECT_FALSE(setup.scope()->NonRecursiveMergeTo(
- &new_scope, Scope::MergeOptions(), &assignment, "error", &err));
- EXPECT_TRUE(err.has_error());
- }
-
- // The clobber flag should just overwrite colliding values.
- {
- Scope new_scope(setup.settings());
- Value new_value(&assignment, "goodbye");
- new_scope.SetValue("v", new_value, &assignment);
-
- Err err;
- Scope::MergeOptions options;
- options.clobber_existing = true;
- EXPECT_TRUE(setup.scope()->NonRecursiveMergeTo(
- &new_scope, options, &assignment, "error", &err));
- EXPECT_FALSE(err.has_error());
-
- const Value* found_value = new_scope.GetValue("v");
- ASSERT_TRUE(found_value);
- EXPECT_TRUE(old_value == *found_value);
- }
-
- // Clobber flag for templates.
- {
- Scope new_scope(setup.settings());
-
- scoped_refptr<Template> new_templ(
- new Template(&new_scope, &templ_definition));
- new_scope.AddTemplate("templ", new_templ.get());
- Scope::MergeOptions options;
- options.clobber_existing = true;
-
- Err err;
- EXPECT_TRUE(setup.scope()->NonRecursiveMergeTo(
- &new_scope, options, &assignment, "error", &err));
- EXPECT_FALSE(err.has_error());
-
- const Template* found_value = new_scope.GetTemplate("templ");
- ASSERT_TRUE(found_value);
- EXPECT_TRUE(templ.get() == found_value);
- }
-
- // Don't flag values that technically collide but have the same value.
- {
- Scope new_scope(setup.settings());
- Value new_value(&assignment, "hello");
- new_scope.SetValue("v", new_value, &assignment);
-
- Err err;
- EXPECT_TRUE(setup.scope()->NonRecursiveMergeTo(
- &new_scope, Scope::MergeOptions(), &assignment, "error", &err));
- EXPECT_FALSE(err.has_error());
- }
-
- // Templates that technically collide but are the same.
- {
- Scope new_scope(setup.settings());
-
- scoped_refptr<Template> new_templ(
- new Template(&new_scope, &templ_definition));
- new_scope.AddTemplate("templ", templ.get());
-
- Err err;
- EXPECT_TRUE(setup.scope()->NonRecursiveMergeTo(
- &new_scope, Scope::MergeOptions(), &assignment, "error", &err));
- EXPECT_FALSE(err.has_error());
- }
-
- // Copy private values and templates.
- {
- Scope new_scope(setup.settings());
-
- Err err;
- EXPECT_TRUE(setup.scope()->NonRecursiveMergeTo(
- &new_scope, Scope::MergeOptions(), &assignment, "error", &err));
- EXPECT_FALSE(err.has_error());
- EXPECT_TRUE(new_scope.GetValue(private_var_name));
- EXPECT_TRUE(new_scope.GetTemplate("_templ"));
- }
-
- // Skip private values and templates.
- {
- Scope new_scope(setup.settings());
-
- Err err;
- Scope::MergeOptions options;
- options.skip_private_vars = true;
- EXPECT_TRUE(setup.scope()->NonRecursiveMergeTo(
- &new_scope, options, &assignment, "error", &err));
- EXPECT_FALSE(err.has_error());
- EXPECT_FALSE(new_scope.GetValue(private_var_name));
- EXPECT_FALSE(new_scope.GetTemplate("_templ"));
- }
-
- // Don't mark used.
- {
- Scope new_scope(setup.settings());
-
- Err err;
- Scope::MergeOptions options;
- EXPECT_TRUE(setup.scope()->NonRecursiveMergeTo(
- &new_scope, options, &assignment, "error", &err));
- EXPECT_FALSE(err.has_error());
- EXPECT_FALSE(new_scope.CheckForUnusedVars(&err));
- EXPECT_TRUE(err.has_error());
- }
-
- // Mark dest used.
- {
- Scope new_scope(setup.settings());
-
- Err err;
- Scope::MergeOptions options;
- options.mark_dest_used = true;
- EXPECT_TRUE(setup.scope()->NonRecursiveMergeTo(
- &new_scope, options, &assignment, "error", &err));
- EXPECT_FALSE(err.has_error());
- EXPECT_TRUE(new_scope.CheckForUnusedVars(&err));
- EXPECT_FALSE(err.has_error());
- }
-
- // Build dependency files are merged.
- {
- Scope from_scope(setup.settings());
- SourceFile source_file = SourceFile("//a/BUILD.gn");
- from_scope.AddBuildDependencyFile(source_file);
-
- Scope to_scope(setup.settings());
- EXPECT_FALSE(ContainsBuildDependencyFile(&to_scope, source_file));
-
- Scope::MergeOptions options;
- Err err;
- EXPECT_TRUE(from_scope.NonRecursiveMergeTo(&to_scope, options, &assignment,
- "error", &err));
- EXPECT_FALSE(err.has_error());
- EXPECT_EQ(1U, to_scope.build_dependency_files().size());
- EXPECT_TRUE(ContainsBuildDependencyFile(&to_scope, source_file));
- }
-}
-
-TEST(Scope, MakeClosure) {
- // Create 3 nested scopes [const root from setup] <- nested1 <- nested2.
- TestWithScope setup;
-
- // Make a pretend parse node with proper tracking that we can blame for the
- // given value.
- InputFile input_file(SourceFile("//foo"));
- Token assignment_token(Location(&input_file, 1, 1, 1), Token::STRING,
- "\"hello\"");
- LiteralNode assignment;
- assignment.set_value(assignment_token);
- setup.scope()->SetValue("on_root", Value(&assignment, "on_root"),
- &assignment);
-
- // Root scope should be const from the nested caller's perspective.
- Scope nested1(static_cast<const Scope*>(setup.scope()));
- nested1.SetValue("on_one", Value(&assignment, "on_one"), &assignment);
-
- Scope nested2(&nested1);
- nested2.SetValue("on_one", Value(&assignment, "on_two"), &assignment);
- nested2.SetValue("on_two", Value(&assignment, "on_two2"), &assignment);
-
- // Making a closure from the root scope.
- std::unique_ptr<Scope> result = setup.scope()->MakeClosure();
- EXPECT_FALSE(result->containing()); // Should have no containing scope.
- EXPECT_TRUE(result->GetValue("on_root")); // Value should be copied.
-
- // Making a closure from the second nested scope.
- result = nested2.MakeClosure();
- EXPECT_EQ(setup.scope(),
- result->containing()); // Containing scope should be the root.
- EXPECT_TRUE(HasStringValueEqualTo(result.get(), "on_root", "on_root"));
- EXPECT_TRUE(HasStringValueEqualTo(result.get(), "on_one", "on_two"));
- EXPECT_TRUE(HasStringValueEqualTo(result.get(), "on_two", "on_two2"));
-}
-
-TEST(Scope, GetMutableValue) {
- TestWithScope setup;
-
- // Make a pretend parse node with proper tracking that we can blame for the
- // given value.
- InputFile input_file(SourceFile("//foo"));
- Token assignment_token(Location(&input_file, 1, 1, 1), Token::STRING,
- "\"hello\"");
- LiteralNode assignment;
- assignment.set_value(assignment_token);
-
- const char kOnConst[] = "on_const";
- const char kOnMutable1[] = "on_mutable1";
- const char kOnMutable2[] = "on_mutable2";
-
- Value value(&assignment, "hello");
-
- // Create a root scope with one value.
- Scope root_scope(setup.settings());
- root_scope.SetValue(kOnConst, value, &assignment);
-
- // Create a first nested scope with a different value.
- const Scope* const_root_scope = &root_scope;
- Scope mutable_scope1(const_root_scope);
- mutable_scope1.SetValue(kOnMutable1, value, &assignment);
-
- // Create a second nested scope with a different value.
- Scope mutable_scope2(&mutable_scope1);
- mutable_scope2.SetValue(kOnMutable2, value, &assignment);
-
- // Check getting root scope values.
- EXPECT_TRUE(mutable_scope2.GetValue(kOnConst, true));
- EXPECT_FALSE(mutable_scope2.GetMutableValue(
- kOnConst, Scope::SEARCH_NESTED, true));
-
- // Test reading a value from scope 1.
- Value* mutable1_result = mutable_scope2.GetMutableValue(
- kOnMutable1, Scope::SEARCH_NESTED, false);
- ASSERT_TRUE(mutable1_result);
- EXPECT_TRUE(*mutable1_result == value);
-
- // Make sure CheckForUnusedVars works on scope1 (we didn't mark the value as
- // used in the previous step).
- Err err;
- EXPECT_FALSE(mutable_scope1.CheckForUnusedVars(&err));
- mutable1_result = mutable_scope2.GetMutableValue(
- kOnMutable1, Scope::SEARCH_NESTED, true);
- EXPECT_TRUE(mutable1_result);
- err = Err();
- EXPECT_TRUE(mutable_scope1.CheckForUnusedVars(&err));
-
- // Test reading a value from scope 2.
- Value* mutable2_result = mutable_scope2.GetMutableValue(
- kOnMutable2, Scope::SEARCH_NESTED, true);
- ASSERT_TRUE(mutable2_result);
- EXPECT_TRUE(*mutable2_result == value);
-}
-
-TEST(Scope, RemovePrivateIdentifiers) {
- TestWithScope setup;
- setup.scope()->SetValue("a", Value(nullptr, true), nullptr);
- setup.scope()->SetValue("_b", Value(nullptr, true), nullptr);
-
- setup.scope()->RemovePrivateIdentifiers();
- EXPECT_TRUE(setup.scope()->GetValue("a"));
- EXPECT_FALSE(setup.scope()->GetValue("_b"));
-}
diff --git a/chromium/tools/gn/settings.cc b/chromium/tools/gn/settings.cc
deleted file mode 100644
index d206f5c9273..00000000000
--- a/chromium/tools/gn/settings.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/settings.h"
-
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "tools/gn/filesystem_utils.h"
-
-Settings::Settings(const BuildSettings* build_settings,
- const std::string& output_subdir_name)
- : build_settings_(build_settings),
- import_manager_(),
- base_config_(this),
- greedy_target_generation_(false) {
- if (output_subdir_name.empty()) {
- toolchain_output_dir_ = build_settings->build_dir();
- } else {
- // We guarantee this ends in a slash.
- DCHECK(output_subdir_name[output_subdir_name.size() - 1] == '/');
- toolchain_output_subdir_.value().append(output_subdir_name);
-
- DCHECK(!build_settings->build_dir().is_null());
- toolchain_output_dir_ = SourceDir(build_settings->build_dir().value() +
- toolchain_output_subdir_.value());
- }
- // The output dir will be null in some tests and when invoked to parsed
- // one-off data without doing generation.
- if (!toolchain_output_dir_.is_null())
- toolchain_gen_dir_ = SourceDir(toolchain_output_dir_.value() + "gen/");
-}
-
-Settings::~Settings() = default;
diff --git a/chromium/tools/gn/settings.h b/chromium/tools/gn/settings.h
deleted file mode 100644
index 91f641060f3..00000000000
--- a/chromium/tools/gn/settings.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_SETTINGS_H_
-#define TOOLS_GN_SETTINGS_H_
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/import_manager.h"
-#include "tools/gn/output_file.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/source_dir.h"
-#include "tools/gn/toolchain.h"
-
-// Holds the settings for one toolchain invocation. There will be one
-// Settings object for each toolchain type, each referring to the same
-// BuildSettings object for shared stuff.
-//
-// The Settings object is const once it is constructed, which allows us to
-// use it from multiple threads during target generation without locking (which
-// is important, because it gets used a lot).
-//
-// The Toolchain object holds the set of stuff that is set by the toolchain
-// declaration, which obviously needs to be set later when we actually parse
-// the file with the toolchain declaration in it.
-class Settings {
- public:
- // Constructs a toolchain settings.
- //
- // The output_subdir_name is the name we should use for the subdirectory in
- // the build output directory for this toolchain's outputs. The default
- // toolchain would use an empty string (it goes in the root build dir).
- // Otherwise, it must end in a slash.
- Settings(const BuildSettings* build_settings,
- const std::string& output_subdir_name);
- ~Settings();
-
- const BuildSettings* build_settings() const { return build_settings_; }
-
- // The actual Toolchain object pointer is not available on the settings
- // object because it might not be resolved yet. Code running after the
- // load is complete can ask the Builder for the Toolchain corresponding to
- // this label.
- const Label& toolchain_label() const { return toolchain_label_; }
- void set_toolchain_label(const Label& l) { toolchain_label_ = l; }
-
- const Label& default_toolchain_label() const {
- return default_toolchain_label_;
- }
- void set_default_toolchain_label(const Label& default_label) {
- default_toolchain_label_ = default_label;
- }
-
- // Indicates if this corresponds to the default toolchain.
- bool is_default() const {
- return toolchain_label_ == default_toolchain_label_;
- }
-
- const OutputFile& toolchain_output_subdir() const {
- return toolchain_output_subdir_;
- }
- const SourceDir& toolchain_output_dir() const {
- return toolchain_output_dir_;
- }
-
- // Directory for generated files.
- const SourceDir& toolchain_gen_dir() const {
- return toolchain_gen_dir_;
- }
-
- // The import manager caches the result of executing imported files in the
- // context of a given settings object.
- //
- // See the ItemTree getter in GlobalSettings for why this doesn't return a
- // const pointer.
- ImportManager& import_manager() const { return import_manager_; }
-
- const Scope* base_config() const { return &base_config_; }
- Scope* base_config() { return &base_config_; }
-
- // Set to true when every target we encounter should be generated. False
- // means that only targets that have a dependency from (directly or
- // indirectly) some magic root node are actually generated. See the comments
- // on ItemTree for more.
- bool greedy_target_generation() const {
- return greedy_target_generation_;
- }
- void set_greedy_target_generation(bool gtg) {
- greedy_target_generation_ = gtg;
- }
-
- private:
- const BuildSettings* build_settings_;
-
- Label toolchain_label_;
- Label default_toolchain_label_;
-
- mutable ImportManager import_manager_;
-
- // The subdirectory inside the build output for this toolchain. For the
- // default toolchain, this will be empty (since the deafult toolchain's
- // output directory is the same as the build directory). When nonempty, this
- // is guaranteed to end in a slash.
- OutputFile toolchain_output_subdir_;
-
- // Full source file path to the toolchain output directory.
- SourceDir toolchain_output_dir_;
-
- SourceDir toolchain_gen_dir_;
-
- Scope base_config_;
-
- bool greedy_target_generation_;
-
- DISALLOW_COPY_AND_ASSIGN(Settings);
-};
-
-#endif // TOOLS_GN_SETTINGS_H_
diff --git a/chromium/tools/gn/setup.cc b/chromium/tools/gn/setup.cc
deleted file mode 100644
index 36b6ec5f767..00000000000
--- a/chromium/tools/gn/setup.cc
+++ /dev/null
@@ -1,818 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/setup.h"
-
-#include <stdlib.h>
-
-#include <algorithm>
-#include <memory>
-#include <sstream>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/process/launch.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "tools/gn/command_format.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/parser.h"
-#include "tools/gn/source_dir.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/standard_out.h"
-#include "tools/gn/switches.h"
-#include "tools/gn/tokenizer.h"
-#include "tools/gn/trace.h"
-#include "tools/gn/value.h"
-#include "tools/gn/value_extractors.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-const char kDotfile_Help[] =
- R"(.gn file
-
- When gn starts, it will search the current directory and parent directories
- for a file called ".gn". This indicates the source root. You can override
- this detection by using the --root command-line argument
-
- The .gn file in the source root will be executed. The syntax is the same as a
- buildfile, but with very limited build setup-specific meaning.
-
- If you specify --root, by default GN will look for the file .gn in that
- directory. If you want to specify a different file, you can additionally pass
- --dotfile:
-
- gn gen out/Debug --root=/home/build --dotfile=/home/my_gn_file.gn
-
-Variables
-
- arg_file_template [optional]
- Path to a file containing the text that should be used as the default
- args.gn content when you run `gn args`.
-
- buildconfig [required]
- Path to the build config file. This file will be used to set up the
- build file execution environment for each toolchain.
-
- check_targets [optional]
- A list of labels and label patterns that should be checked when running
- "gn check" or "gn gen --check". If unspecified, all targets will be
- checked. If it is the empty list, no targets will be checked.
-
- The format of this list is identical to that of "visibility" so see "gn
- help visibility" for examples.
-
- exec_script_whitelist [optional]
- A list of .gn/.gni files (not labels) that have permission to call the
- exec_script function. If this list is defined, calls to exec_script will
- be checked against this list and GN will fail if the current file isn't
- in the list.
-
- This is to allow the use of exec_script to be restricted since is easy to
- use inappropriately. Wildcards are not supported. Files in the
- secondary_source tree (if defined) should be referenced by ignoring the
- secondary tree and naming them as if they are in the main tree.
-
- If unspecified, the ability to call exec_script is unrestricted.
-
- Example:
- exec_script_whitelist = [
- "//base/BUILD.gn",
- "//build/my_config.gni",
- ]
-
- root [optional]
- Label of the root build target. The GN build will start by loading the
- build file containing this target name. This defaults to "//:" which will
- cause the file //BUILD.gn to be loaded.
-
- script_executable [optional]
- Path to specific Python executable or potentially a different language
- interpreter that is used to execute scripts in action targets and
- exec_script calls.
-
- secondary_source [optional]
- Label of an alternate directory tree to find input files. When searching
- for a BUILD.gn file (or the build config file discussed above), the file
- will first be looked for in the source root. If it's not found, the
- secondary source root will be checked (which would contain a parallel
- directory hierarchy).
-
- This behavior is intended to be used when BUILD.gn files can't be checked
- in to certain source directories for whatever reason.
-
- The secondary source root must be inside the main source tree.
-
- default_args [optional]
- Scope containing the default overrides for declared arguments. These
- overrides take precedence over the default values specified in the
- declare_args() block, but can be overriden using --args or the
- args.gn file.
-
- This is intended to be used when subprojects declare arguments with
- default values that need to be changed for whatever reason.
-
-Example .gn file contents
-
- buildconfig = "//build/config/BUILDCONFIG.gn"
-
- check_targets = [
- "//doom_melon/*", # Check everything in this subtree.
- "//tools:mind_controlling_ant", # Check this specific target.
- ]
-
- root = "//:root"
-
- secondary_source = "//build/config/temporary_buildfiles/"
-
- default_args = {
- # Default to release builds for this project.
- is_debug = false
- is_component_build = false
- }
-)";
-
-namespace {
-
-const base::FilePath::CharType kGnFile[] = FILE_PATH_LITERAL(".gn");
-
-base::FilePath FindDotFile(const base::FilePath& current_dir) {
- base::FilePath try_this_file = current_dir.Append(kGnFile);
- if (base::PathExists(try_this_file))
- return try_this_file;
-
- base::FilePath with_no_slash = current_dir.StripTrailingSeparators();
- base::FilePath up_one_dir = with_no_slash.DirName();
- if (up_one_dir == current_dir)
- return base::FilePath(); // Got to the top.
-
- return FindDotFile(up_one_dir);
-}
-
-void ForwardItemDefinedToBuilderInMainThread(
- Builder* builder_call_on_main_thread_only,
- std::unique_ptr<Item> item) {
- builder_call_on_main_thread_only->ItemDefined(std::move(item));
-
- // Pair to the Increment in ItemDefinedCallback.
- g_scheduler->DecrementWorkCount();
-}
-
-// Called on any thread. Post the item to the builder on the main thread.
-void ItemDefinedCallback(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- Builder* builder_call_on_main_thread_only,
- std::unique_ptr<Item> item) {
- DCHECK(item);
-
- // Increment the work count for the duration of defining the item with the
- // builder. Otherwise finishing this callback will race finishing loading
- // files. If there is no other pending work at any point in the middle of
- // this call completing on the main thread, the 'Complete' function will
- // be signaled and we'll stop running with an incomplete build.
- g_scheduler->IncrementWorkCount();
- task_runner->PostTask(
- FROM_HERE,
- base::Bind(&ForwardItemDefinedToBuilderInMainThread,
- base::Unretained(builder_call_on_main_thread_only),
- base::Passed(&item)));
-}
-
-void DecrementWorkCount() {
- g_scheduler->DecrementWorkCount();
-}
-
-#if defined(OS_WIN)
-
-// Given the path to a batch file that runs Python, extracts the name of the
-// executable actually implementing Python. Generally people write a batch file
-// to put something named "python" on the path, which then just redirects to
-// a python.exe somewhere else. This step decodes that setup. On failure,
-// returns empty path.
-base::FilePath PythonBatToExe(const base::FilePath& bat_path) {
- // Note exciting double-quoting to allow spaces. The /c switch seems to check
- // for quotes around the whole thing and then deletes them. If you want to
- // quote the first argument in addition (to allow for spaces in the Python
- // path, you need *another* set of quotes around that, likewise, we need
- // two quotes at the end.
- base::string16 command = L"cmd.exe /c \"\"";
- command.append(bat_path.value());
- command.append(L"\" -c \"import sys; print sys.executable\"\"");
-
- std::string python_path;
- if (base::GetAppOutput(command, &python_path)) {
- base::TrimWhitespaceASCII(python_path, base::TRIM_ALL, &python_path);
-
- // Python uses the system multibyte code page for sys.executable.
- base::FilePath exe_path(base::SysNativeMBToWide(python_path));
-
- // Check for reasonable output, cmd may have output an error message.
- if (base::PathExists(exe_path))
- return exe_path;
- }
- return base::FilePath();
-}
-
-const base::char16 kPythonExeName[] = L"python.exe";
-const base::char16 kPythonBatName[] = L"python.bat";
-
-base::FilePath FindWindowsPython() {
- base::char16 current_directory[MAX_PATH];
- ::GetCurrentDirectory(MAX_PATH, current_directory);
-
- // First search for python.exe in the current directory.
- base::FilePath cur_dir_candidate_exe =
- base::FilePath(current_directory).Append(kPythonExeName);
- if (base::PathExists(cur_dir_candidate_exe))
- return cur_dir_candidate_exe;
-
- // Get the path.
- const base::char16 kPathEnvVarName[] = L"Path";
- DWORD path_length = ::GetEnvironmentVariable(kPathEnvVarName, nullptr, 0);
- if (path_length == 0)
- return base::FilePath();
- std::unique_ptr<base::char16[]> full_path(new base::char16[path_length]);
- DWORD actual_path_length =
- ::GetEnvironmentVariable(kPathEnvVarName, full_path.get(), path_length);
- CHECK_EQ(path_length, actual_path_length + 1);
-
- // Search for python.exe in the path.
- for (const auto& component : base::SplitStringPiece(
- base::StringPiece16(full_path.get(), path_length), L";",
- base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
- base::FilePath candidate_exe =
- base::FilePath(component).Append(kPythonExeName);
- if (base::PathExists(candidate_exe))
- return candidate_exe;
-
- // Also allow python.bat, but convert into the .exe.
- base::FilePath candidate_bat =
- base::FilePath(component).Append(kPythonBatName);
- if (base::PathExists(candidate_bat)) {
- base::FilePath python_exe = PythonBatToExe(candidate_bat);
- if (!python_exe.empty())
- return python_exe;
- }
- }
- return base::FilePath();
-}
-#endif
-
-} // namespace
-
-const char Setup::kBuildArgFileName[] = "args.gn";
-
-Setup::Setup()
- : build_settings_(),
- loader_(new LoaderImpl(&build_settings_)),
- builder_(loader_.get()),
- root_build_file_("//BUILD.gn"),
- check_public_headers_(false),
- dotfile_settings_(&build_settings_, std::string()),
- dotfile_scope_(&dotfile_settings_),
- default_args_(nullptr),
- fill_arguments_(true) {
- dotfile_settings_.set_toolchain_label(Label());
-
- build_settings_.set_item_defined_callback(
- base::Bind(&ItemDefinedCallback, scheduler_.task_runner(), &builder_));
-
- loader_->set_complete_callback(base::Bind(&DecrementWorkCount));
- // The scheduler's task runner wasn't created when the Loader was created, so
- // we need to set it now.
- loader_->set_task_runner(scheduler_.task_runner());
-}
-
-Setup::~Setup() = default;
-
-bool Setup::DoSetup(const std::string& build_dir, bool force_create) {
- base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
-
- scheduler_.set_verbose_logging(cmdline->HasSwitch(switches::kVerbose));
- if (cmdline->HasSwitch(switches::kTime) ||
- cmdline->HasSwitch(switches::kTracelog))
- EnableTracing();
-
- ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "DoSetup");
-
- if (!FillSourceDir(*cmdline))
- return false;
- if (!RunConfigFile())
- return false;
- if (!FillOtherConfig(*cmdline))
- return false;
-
- // Must be after FillSourceDir to resolve.
- if (!FillBuildDir(build_dir, !force_create))
- return false;
-
- // Apply project-specific default (if specified).
- // Must happen before FillArguments().
- if (default_args_) {
- Scope::KeyValueMap overrides;
- default_args_->GetCurrentScopeValues(&overrides);
- build_settings_.build_args().AddDefaultArgOverrides(overrides);
- }
-
- if (fill_arguments_) {
- if (!FillArguments(*cmdline))
- return false;
- }
- if (!FillPythonPath(*cmdline))
- return false;
-
- // Check for unused variables in the .gn file.
- Err err;
- if (!dotfile_scope_.CheckForUnusedVars(&err)) {
- err.PrintToStdout();
- return false;
- }
-
- return true;
-}
-
-bool Setup::Run() {
- RunPreMessageLoop();
- if (!scheduler_.Run())
- return false;
- return RunPostMessageLoop();
-}
-
-SourceFile Setup::GetBuildArgFile() const {
- return SourceFile(build_settings_.build_dir().value() + kBuildArgFileName);
-}
-
-void Setup::RunPreMessageLoop() {
- // Will be decremented with the loader is drained.
- g_scheduler->IncrementWorkCount();
-
- // Load the root build file.
- loader_->Load(root_build_file_, LocationRange(), Label());
-}
-
-bool Setup::RunPostMessageLoop() {
- Err err;
- if (!builder_.CheckForBadItems(&err)) {
- err.PrintToStdout();
- return false;
- }
-
- if (!build_settings_.build_args().VerifyAllOverridesUsed(&err)) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kFailOnUnusedArgs)) {
- err.PrintToStdout();
- return false;
- }
- err.PrintNonfatalToStdout();
- OutputString("\nThe build continued as if that argument was "
- "unspecified.\n\n");
- return true;
- }
-
- if (check_public_headers_) {
- std::vector<const Target*> all_targets = builder_.GetAllResolvedTargets();
- std::vector<const Target*> to_check;
- if (check_patterns()) {
- commands::FilterTargetsByPatterns(all_targets, *check_patterns(),
- &to_check);
- } else {
- to_check = all_targets;
- }
-
- if (!commands::CheckPublicHeaders(&build_settings_, all_targets,
- to_check, false)) {
- return false;
- }
- }
-
- // Write out tracing and timing if requested.
- const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
- if (cmdline->HasSwitch(switches::kTime))
- PrintLongHelp(SummarizeTraces());
- if (cmdline->HasSwitch(switches::kTracelog))
- SaveTraces(cmdline->GetSwitchValuePath(switches::kTracelog));
-
- return true;
-}
-
-bool Setup::FillArguments(const base::CommandLine& cmdline) {
- // Use the args on the command line if specified, and save them. Do this even
- // if the list is empty (this means clear any defaults).
- if (cmdline.HasSwitch(switches::kArgs)) {
- if (!FillArgsFromCommandLine(cmdline.GetSwitchValueASCII(switches::kArgs)))
- return false;
- SaveArgsToFile();
- return true;
- }
-
- // No command line args given, use the arguments from the build dir (if any).
- return FillArgsFromFile();
-}
-
-bool Setup::FillArgsFromCommandLine(const std::string& args) {
- args_input_file_ = std::make_unique<InputFile>(SourceFile());
- args_input_file_->SetContents(args);
- args_input_file_->set_friendly_name("the command-line \"--args\"");
- return FillArgsFromArgsInputFile();
-}
-
-bool Setup::FillArgsFromFile() {
- ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Load args file");
-
- SourceFile build_arg_source_file = GetBuildArgFile();
- base::FilePath build_arg_file =
- build_settings_.GetFullPath(build_arg_source_file);
-
- std::string contents;
- if (!base::ReadFileToString(build_arg_file, &contents))
- return true; // File doesn't exist, continue with default args.
-
- // Add a dependency on the build arguments file. If this changes, we want
- // to re-generate the build.
- g_scheduler->AddGenDependency(build_arg_file);
-
- if (contents.empty())
- return true; // Empty file, do nothing.
-
- args_input_file_ = std::make_unique<InputFile>(build_arg_source_file);
- args_input_file_->SetContents(contents);
- args_input_file_->set_friendly_name(
- "build arg file (use \"gn args <out_dir>\" to edit)");
-
- setup_trace.Done(); // Only want to count the load as part of the trace.
- return FillArgsFromArgsInputFile();
-}
-
-bool Setup::FillArgsFromArgsInputFile() {
- ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Parse args");
-
- Err err;
- args_tokens_ = Tokenizer::Tokenize(args_input_file_.get(), &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
-
- args_root_ = Parser::Parse(args_tokens_, &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
-
- Scope arg_scope(&dotfile_settings_);
- // Set soure dir so relative imports in args work.
- SourceDir root_source_dir =
- SourceDirForCurrentDirectory(build_settings_.root_path());
- arg_scope.set_source_dir(root_source_dir);
- args_root_->Execute(&arg_scope, &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
-
- // Save the result of the command args.
- Scope::KeyValueMap overrides;
- arg_scope.GetCurrentScopeValues(&overrides);
- build_settings_.build_args().AddArgOverrides(overrides);
- build_settings_.build_args().set_build_args_dependency_files(
- arg_scope.build_dependency_files());
- return true;
-}
-
-bool Setup::SaveArgsToFile() {
- ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Save args file");
-
- // For the first run, the build output dir might not be created yet, so do
- // that so we can write a file into it. Ignore errors, we'll catch the error
- // when we try to write a file to it below.
- base::FilePath build_arg_file =
- build_settings_.GetFullPath(GetBuildArgFile());
- base::CreateDirectory(build_arg_file.DirName());
-
- std::string contents = args_input_file_->contents();
- commands::FormatStringToString(contents, false, &contents);
-#if defined(OS_WIN)
- // Use Windows lineendings for this file since it will often open in
- // Notepad which can't handle Unix ones.
- base::ReplaceSubstringsAfterOffset(&contents, 0, "\n", "\r\n");
-#endif
- if (base::WriteFile(build_arg_file, contents.c_str(),
- static_cast<int>(contents.size())) == -1) {
- Err(Location(), "Args file could not be written.",
- "The file is \"" + FilePathToUTF8(build_arg_file) +
- "\"").PrintToStdout();
- return false;
- }
-
- // Add a dependency on the build arguments file. If this changes, we want
- // to re-generate the build.
- g_scheduler->AddGenDependency(build_arg_file);
-
- return true;
-}
-
-bool Setup::FillSourceDir(const base::CommandLine& cmdline) {
- // Find the .gn file.
- base::FilePath root_path;
-
- // Prefer the command line args to the config file.
- base::FilePath relative_root_path =
- cmdline.GetSwitchValuePath(switches::kRoot);
- if (!relative_root_path.empty()) {
- root_path = base::MakeAbsoluteFilePath(relative_root_path);
- if (root_path.empty()) {
- Err(Location(), "Root source path not found.",
- "The path \"" + FilePathToUTF8(relative_root_path) +
- "\" doesn't exist.").PrintToStdout();
- return false;
- }
-
- // When --root is specified, an alternate --dotfile can also be set.
- // --dotfile should be a real file path and not a "//foo" source-relative
- // path.
- base::FilePath dot_file_path =
- cmdline.GetSwitchValuePath(switches::kDotfile);
- if (dot_file_path.empty()) {
- dotfile_name_ = root_path.Append(kGnFile);
- } else {
- dotfile_name_ = base::MakeAbsoluteFilePath(dot_file_path);
- if (dotfile_name_.empty()) {
- Err(Location(), "Could not load dotfile.",
- "The file \"" + FilePathToUTF8(dot_file_path) +
- "\" couldn't be loaded.").PrintToStdout();
- return false;
- }
- }
- } else {
- // In the default case, look for a dotfile and that also tells us where the
- // source root is.
- base::FilePath cur_dir;
- base::GetCurrentDirectory(&cur_dir);
- dotfile_name_ = FindDotFile(cur_dir);
- if (dotfile_name_.empty()) {
- Err(Location(), "Can't find source root.",
- "I could not find a \".gn\" file in the current directory or any "
- "parent,\nand the --root command-line argument was not specified.")
- .PrintToStdout();
- return false;
- }
- root_path = dotfile_name_.DirName();
- }
-
- base::FilePath root_realpath = base::MakeAbsoluteFilePath(root_path);
- if (root_realpath.empty()) {
- Err(Location(), "Can't get the real root path.",
- "I could not get the real path of \"" + FilePathToUTF8(root_path) +
- "\".").PrintToStdout();
- return false;
- }
- if (scheduler_.verbose_logging())
- scheduler_.Log("Using source root", FilePathToUTF8(root_realpath));
- build_settings_.SetRootPath(root_realpath);
-
- return true;
-}
-
-bool Setup::FillBuildDir(const std::string& build_dir, bool require_exists) {
- Err err;
- SourceDir resolved =
- SourceDirForCurrentDirectory(build_settings_.root_path()).
- ResolveRelativeDir(Value(nullptr, build_dir), &err,
- build_settings_.root_path_utf8());
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
-
- base::FilePath build_dir_path = build_settings_.GetFullPath(resolved);
- if (!base::CreateDirectory(build_dir_path)) {
- Err(Location(), "Can't create the build dir.",
- "I could not create the build dir \"" + FilePathToUTF8(build_dir_path) +
- "\".").PrintToStdout();
- return false;
- }
- base::FilePath build_dir_realpath =
- base::MakeAbsoluteFilePath(build_dir_path);
- if (build_dir_realpath.empty()) {
- Err(Location(), "Can't get the real build dir path.",
- "I could not get the real path of \"" + FilePathToUTF8(build_dir_path) +
- "\".").PrintToStdout();
- return false;
- }
- resolved = SourceDirForPath(build_settings_.root_path(),
- build_dir_realpath);
-
- if (scheduler_.verbose_logging())
- scheduler_.Log("Using build dir", resolved.value());
-
- if (require_exists) {
- if (!base::PathExists(build_dir_path.Append(
- FILE_PATH_LITERAL("build.ninja")))) {
- Err(Location(), "Not a build directory.",
- "This command requires an existing build directory. I interpreted "
- "your input\n\"" + build_dir + "\" as:\n " +
- FilePathToUTF8(build_dir_path) +
- "\nwhich doesn't seem to contain a previously-generated build.")
- .PrintToStdout();
- return false;
- }
- }
-
- build_settings_.SetBuildDir(resolved);
- return true;
-}
-
-bool Setup::FillPythonPath(const base::CommandLine& cmdline) {
- // Trace this since it tends to be a bit slow on Windows.
- ScopedTrace setup_trace(TraceItem::TRACE_SETUP, "Fill Python Path");
- const Value* value = dotfile_scope_.GetValue("script_executable", true);
- if (cmdline.HasSwitch(switches::kScriptExecutable)) {
- build_settings_.set_python_path(
- cmdline.GetSwitchValuePath(switches::kScriptExecutable));
- } else if (value) {
- Err err;
- if (!value->VerifyTypeIs(Value::STRING, &err)) {
- err.PrintToStdout();
- return false;
- }
- build_settings_.set_python_path(
- base::FilePath(UTF8ToFilePath(value->string_value())));
- } else {
-#if defined(OS_WIN)
- base::FilePath python_path = FindWindowsPython();
- if (python_path.empty()) {
- scheduler_.Log("WARNING", "Could not find python on path, using "
- "just \"python.exe\"");
- python_path = base::FilePath(kPythonExeName);
- }
- build_settings_.set_python_path(python_path.NormalizePathSeparatorsTo('/'));
-#else
- build_settings_.set_python_path(base::FilePath("python"));
-#endif
- }
- return true;
-}
-
-bool Setup::RunConfigFile() {
- if (scheduler_.verbose_logging())
- scheduler_.Log("Got dotfile", FilePathToUTF8(dotfile_name_));
-
- dotfile_input_file_ = std::make_unique<InputFile>(SourceFile("//.gn"));
- if (!dotfile_input_file_->Load(dotfile_name_)) {
- Err(Location(), "Could not load dotfile.",
- "The file \"" + FilePathToUTF8(dotfile_name_) + "\" couldn't be loaded")
- .PrintToStdout();
- return false;
- }
-
- Err err;
- dotfile_tokens_ = Tokenizer::Tokenize(dotfile_input_file_.get(), &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
-
- dotfile_root_ = Parser::Parse(dotfile_tokens_, &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
-
- dotfile_scope_.AddBuildDependencyFile(SourceFile("//.gn"));
- dotfile_root_->Execute(&dotfile_scope_, &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
-
- return true;
-}
-
-bool Setup::FillOtherConfig(const base::CommandLine& cmdline) {
- Err err;
- SourceDir current_dir("//");
- Label root_target_label(current_dir, "");
-
- // Secondary source path, read from the config file if present.
- // Read from the config file if present.
- const Value* secondary_value =
- dotfile_scope_.GetValue("secondary_source", true);
- if (secondary_value) {
- if (!secondary_value->VerifyTypeIs(Value::STRING, &err)) {
- err.PrintToStdout();
- return false;
- }
- build_settings_.SetSecondarySourcePath(
- SourceDir(secondary_value->string_value()));
- }
-
- // Root build file.
- const Value* root_value = dotfile_scope_.GetValue("root", true);
- if (root_value) {
- if (!root_value->VerifyTypeIs(Value::STRING, &err)) {
- err.PrintToStdout();
- return false;
- }
-
- root_target_label = Label::Resolve(current_dir, Label(), *root_value, &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
-
- root_build_file_ = Loader::BuildFileForLabel(root_target_label);
- }
- build_settings_.SetRootTargetLabel(root_target_label);
-
- // Build config file.
- const Value* build_config_value =
- dotfile_scope_.GetValue("buildconfig", true);
- if (!build_config_value) {
- Err(Location(), "No build config file.",
- "Your .gn file (\"" + FilePathToUTF8(dotfile_name_) + "\")\n"
- "didn't specify a \"buildconfig\" value.").PrintToStdout();
- return false;
- } else if (!build_config_value->VerifyTypeIs(Value::STRING, &err)) {
- err.PrintToStdout();
- return false;
- }
- build_settings_.set_build_config_file(
- SourceFile(build_config_value->string_value()));
-
- // Targets to check.
- const Value* check_targets_value =
- dotfile_scope_.GetValue("check_targets", true);
- if (check_targets_value) {
- check_patterns_.reset(new std::vector<LabelPattern>);
- ExtractListOfLabelPatterns(*check_targets_value, current_dir,
- check_patterns_.get(), &err);
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
- }
-
- // Fill exec_script_whitelist.
- const Value* exec_script_whitelist_value =
- dotfile_scope_.GetValue("exec_script_whitelist", true);
- if (exec_script_whitelist_value) {
- // Fill the list of targets to check.
- if (!exec_script_whitelist_value->VerifyTypeIs(Value::LIST, &err)) {
- err.PrintToStdout();
- return false;
- }
- std::unique_ptr<std::set<SourceFile>> whitelist =
- std::make_unique<std::set<SourceFile>>();
- for (const auto& item : exec_script_whitelist_value->list_value()) {
- if (!item.VerifyTypeIs(Value::STRING, &err)) {
- err.PrintToStdout();
- return false;
- }
- whitelist->insert(current_dir.ResolveRelativeFile(item, &err));
- if (err.has_error()) {
- err.PrintToStdout();
- return false;
- }
- }
- build_settings_.set_exec_script_whitelist(std::move(whitelist));
- }
-
- // Fill optional default_args.
- const Value* default_args_value =
- dotfile_scope_.GetValue("default_args", true);
- if (default_args_value) {
- if (!default_args_value->VerifyTypeIs(Value::SCOPE, &err)) {
- err.PrintToStdout();
- return false;
- }
-
- default_args_ = default_args_value->scope_value();
- }
-
- const Value* arg_file_template_value =
- dotfile_scope_.GetValue("arg_file_template", true);
- if (arg_file_template_value) {
- if (!arg_file_template_value->VerifyTypeIs(Value::STRING, &err)) {
- err.PrintToStdout();
- return false;
- }
- SourceFile path(arg_file_template_value->string_value());
- build_settings_.set_arg_file_template_path(path);
- }
-
- return true;
-}
diff --git a/chromium/tools/gn/setup.h b/chromium/tools/gn/setup.h
deleted file mode 100644
index 08bb11b8c79..00000000000
--- a/chromium/tools/gn/setup.h
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_SETUP_H_
-#define TOOLS_GN_SETUP_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/builder.h"
-#include "tools/gn/label_pattern.h"
-#include "tools/gn/loader.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/token.h"
-#include "tools/gn/toolchain.h"
-
-class InputFile;
-class ParseNode;
-
-namespace base {
-class CommandLine;
-}
-
-extern const char kDotfile_Help[];
-
-// Helper class to setup the build settings and environment for the various
-// commands to run.
-class Setup {
- public:
- Setup();
- ~Setup();
-
- // Configures the build for the current command line. On success returns
- // true. On failure, prints the error and returns false.
- //
- // The parameter is the string the user specified for the build directory. We
- // will try to interpret this as a SourceDir if possible, and will fail if is
- // is malformed.
- //
- // With force_create = false, setup will fail if the build directory doesn't
- // already exist with an args file in it. With force_create set to true, the
- // directory will be created if necessary. Commands explicitly doing
- // generation should set this to true to create it, but querying commands
- // should set it to false to prevent creating oddly-named directories in case
- // the user omits the build directory argument (which is easy to do).
- bool DoSetup(const std::string& build_dir, bool force_create);
-
- // Runs the load, returning true on success. On failure, prints the error
- // and returns false. This includes both RunPreMessageLoop() and
- // RunPostMessageLoop().
- bool Run();
-
- Scheduler& scheduler() { return scheduler_; }
-
- // Returns the file used to store the build arguments. Note that the path
- // might not exist.
- SourceFile GetBuildArgFile() const;
-
- // Sets whether the build arguments should be filled during setup from the
- // command line/build argument file. This will be true by default. The use
- // case for setting it to false is when editing build arguments, we don't
- // want to rely on them being valid.
- void set_fill_arguments(bool fa) { fill_arguments_ = fa; }
-
- // After a successful run, setting this will additionally cause the public
- // headers to be checked. Defaults to false.
- void set_check_public_headers(bool s) {
- check_public_headers_ = s;
- }
-
- // Read from the .gn file, these are the targets to check. If the .gn file
- // does not specify anything, this will be null. If the .gn file specifies
- // the empty list, this will be non-null but empty.
- const std::vector<LabelPattern>* check_patterns() const {
- return check_patterns_.get();
- }
-
- BuildSettings& build_settings() { return build_settings_; }
- Builder& builder() { return builder_; }
- LoaderImpl* loader() { return loader_.get(); }
-
- const SourceFile& GetDotFile() const { return dotfile_input_file_->name(); }
-
- // Name of the file in the root build directory that contains the build
- // arguments.
- static const char kBuildArgFileName[];
-
- private:
- // Performs the two sets of operations to run the generation before and after
- // the message loop is run.
- void RunPreMessageLoop();
- bool RunPostMessageLoop();
-
- // Fills build arguments. Returns true on success.
- bool FillArguments(const base::CommandLine& cmdline);
-
- // Fills the build arguments from the command line or from the build arg file.
- bool FillArgsFromCommandLine(const std::string& args);
- bool FillArgsFromFile();
-
- // Given an already-loaded args_input_file_, parses and saves the resulting
- // arguments. Backend for the different FillArgs variants.
- bool FillArgsFromArgsInputFile();
-
- // Writes the build arguments to the build arg file.
- bool SaveArgsToFile();
-
- // Fills the root directory into the settings. Returns true on success.
- bool FillSourceDir(const base::CommandLine& cmdline);
-
- // Fills the build directory given the value the user has specified.
- // Must happen after FillSourceDir so we can resolve source-relative
- // paths. If require_exists is false, it will fail if the dir doesn't exist.
- bool FillBuildDir(const std::string& build_dir, bool require_exists);
-
- // Fills the python path portion of the command line. On failure, sets
- // it to just "python".
- bool FillPythonPath(const base::CommandLine& cmdline);
-
- // Run config file.
- bool RunConfigFile();
-
- bool FillOtherConfig(const base::CommandLine& cmdline);
-
- BuildSettings build_settings_;
- scoped_refptr<LoaderImpl> loader_;
- Builder builder_;
-
- SourceFile root_build_file_;
-
- bool check_public_headers_;
-
- // See getter for info.
- std::unique_ptr<std::vector<LabelPattern>> check_patterns_;
-
- Scheduler scheduler_;
-
- // These settings and toolchain are used to interpret the command line and
- // dot file.
- Settings dotfile_settings_;
- Scope dotfile_scope_;
-
- // State for invoking the dotfile.
- base::FilePath dotfile_name_;
- std::unique_ptr<InputFile> dotfile_input_file_;
- std::vector<Token> dotfile_tokens_;
- std::unique_ptr<ParseNode> dotfile_root_;
-
- // Default overrides, specified in the dotfile.
- // Owned by the Value (if it exists) in the dotfile_scope_.
- const Scope* default_args_;
-
- // Set to true when we should populate the build arguments from the command
- // line or build argument file. See setter above.
- bool fill_arguments_;
-
- // State for invoking the command line args. We specifically want to keep
- // this around for the entire run so that Values can blame to the command
- // line when we issue errors about them.
- std::unique_ptr<InputFile> args_input_file_;
- std::vector<Token> args_tokens_;
- std::unique_ptr<ParseNode> args_root_;
-
- DISALLOW_COPY_AND_ASSIGN(Setup);
-};
-
-#endif // TOOLS_GN_SETUP_H_
diff --git a/chromium/tools/gn/source_dir.cc b/chromium/tools/gn/source_dir.cc
deleted file mode 100644
index 17eeb612fa1..00000000000
--- a/chromium/tools/gn/source_dir.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/source_dir.h"
-
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/source_file.h"
-
-namespace {
-
-void AssertValueSourceDirString(const std::string& s) {
- if (!s.empty()) {
-#if defined(OS_WIN)
- DCHECK(s[0] == '/' ||
- (s.size() > 2 && s[0] != '/' && s[1] == ':' && IsSlash(s[2])));
-#else
- DCHECK(s[0] == '/');
-#endif
- DCHECK(EndsWithSlash(s)) << s;
- }
-}
-
-// Validates input value (input_value) and sets proper error message.
-// Note: Parameter blame_input is used only for generating error message.
-template <typename StringType>
-bool ValidateResolveInput(bool as_file,
- const Value& blame_input_value,
- const StringType& input_value,
- Err* err) {
- if (as_file) {
- // It's an error to resolve an empty string or one that is a directory
- // (indicated by a trailing slash) because this is the function that expects
- // to return a file.
- if (input_value.empty()) {
- *err = Err(blame_input_value, "Empty file path.",
- "You can't use empty strings as file paths.");
- return false;
- } else if (input_value[input_value.size() - 1] == '/') {
- std::string help = "You specified the path\n ";
- help.append(std::string(input_value));
- help.append(
- "\nand it ends in a slash, indicating you think it's a directory."
- "\nBut here you're supposed to be listing a file.");
- *err = Err(blame_input_value, "File path ends in a slash.", help);
- return false;
- }
- } else if (input_value.empty()) {
- *err = Err(blame_input_value, "Empty directory path.",
- "You can't use empty strings as directories.");
- return false;
- }
- return true;
-}
-
-} // namespace
-
-SourceDir::SourceDir() = default;
-
-SourceDir::SourceDir(const base::StringPiece& p)
- : value_(p.data(), p.size()) {
- if (!EndsWithSlash(value_))
- value_.push_back('/');
- AssertValueSourceDirString(value_);
-}
-
-SourceDir::SourceDir(SwapIn, std::string* s) {
- value_.swap(*s);
- if (!EndsWithSlash(value_))
- value_.push_back('/');
- AssertValueSourceDirString(value_);
-}
-
-SourceDir::~SourceDir() = default;
-
-template <typename StringType>
-std::string SourceDir::ResolveRelativeAs(
- bool as_file,
- const Value& blame_input_value,
- const StringType& input_value,
- Err* err,
- const base::StringPiece& source_root) const {
- if (!ValidateResolveInput<StringType>(as_file, blame_input_value, input_value,
- err)) {
- return std::string();
- }
- return ResolveRelative(input_value, value_, as_file, source_root);
-}
-
-SourceFile SourceDir::ResolveRelativeFile(
- const Value& p,
- Err* err,
- const base::StringPiece& source_root) const {
- SourceFile ret;
-
- if (!p.VerifyTypeIs(Value::STRING, err))
- return ret;
-
- const std::string& input_string = p.string_value();
- if (!ValidateResolveInput<std::string>(true, p, input_string, err)) {
- return ret;
- }
- ret.value_ = ResolveRelative(input_string, value_, true, source_root);
- return ret;
-}
-
-std::string SourceDir::ResolveRelativeAs(bool as_file,
- const Value& v,
- Err* err,
- const base::StringPiece& source_root,
- const std::string* v_value) const {
- if (!v.VerifyTypeIs(Value::STRING, err))
- return std::string();
-
- if (!v_value) {
- v_value = &v.string_value();
- }
- std::string result =
- ResolveRelativeAs(as_file, v, *v_value, err, source_root);
- if (!as_file)
- AssertValueSourceDirString(result);
- return result;
-}
-
-SourceDir SourceDir::ResolveRelativeDir(
- const Value& v,
- Err* err,
- const base::StringPiece& source_root) const {
- if (!v.VerifyTypeIs(Value::STRING, err))
- return SourceDir();
-
- return ResolveRelativeDir<std::string>(v, v.string_value(), err, source_root);
-}
-
-base::FilePath SourceDir::Resolve(const base::FilePath& source_root) const {
- return ResolvePath(value_, false, source_root);
-}
-
-void SourceDir::SwapValue(std::string* v) {
- value_.swap(*v);
- AssertValueSourceDirString(value_);
-}
-
-// Explicit template instantiation
-template std::string SourceDir::ResolveRelativeAs(
- bool as_file,
- const Value& blame_input_value,
- const std::string& input_value,
- Err* err,
- const base::StringPiece& source_root) const;
-
-template std::string SourceDir::ResolveRelativeAs(
- bool as_file,
- const Value& blame_input_value,
- const base::StringPiece& input_value,
- Err* err,
- const base::StringPiece& source_root) const;
diff --git a/chromium/tools/gn/source_dir.h b/chromium/tools/gn/source_dir.h
deleted file mode 100644
index 142285ce236..00000000000
--- a/chromium/tools/gn/source_dir.h
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_SOURCE_DIR_H_
-#define TOOLS_GN_SOURCE_DIR_H_
-
-#include <stddef.h>
-
-#include <algorithm>
-#include <string>
-
-#include "base/containers/hash_tables.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/strings/string_piece.h"
-
-class Err;
-class SourceFile;
-class Value;
-
-// Represents a directory within the source tree. Source dirs begin and end in
-// slashes.
-//
-// If there is one slash at the beginning, it will mean a system-absolute file
-// path. On Windows, absolute system paths will be of the form "/C:/foo/bar".
-//
-// Two slashes at the beginning indicate a path relative to the source root.
-class SourceDir {
- public:
- enum SwapIn { SWAP_IN };
-
- SourceDir();
- explicit SourceDir(const base::StringPiece& p);
- // Swaps the given string in without copies. The given string will be empty
- // after this call.
- SourceDir(SwapIn, std::string* s);
- ~SourceDir();
-
- // Resolves a file or dir name (based on as_file parameter) relative
- // to this source directory. Will return an empty string on error
- // and set the give *err pointer (required). Empty input is always an error.
- //
- // Passed non null v_value will be used to resolve path (in cases where
- // a substring has been extracted from the value, as with label resolution).
- // In this use case parameter v is used to generate proper error.
- //
- // If source_root is supplied, these functions will additionally handle the
- // case where the input is a system-absolute but still inside the source
- // tree. This is the case for some external tools.
- std::string ResolveRelativeAs(
- bool as_file,
- const Value& v,
- Err* err,
- const base::StringPiece& source_root = base::StringPiece(),
- const std::string* v_value = nullptr) const;
-
- // Like ResolveRelativeAs above, but allows to produce result
- // without overhead for string conversion (on input value).
- template <typename StringType>
- std::string ResolveRelativeAs(
- bool as_file,
- const Value& blame_input_value,
- const StringType& input_value,
- Err* err,
- const base::StringPiece& source_root = base::StringPiece()) const;
-
- // Wrapper for ResolveRelativeAs.
- SourceFile ResolveRelativeFile(
- const Value& p,
- Err* err,
- const base::StringPiece& source_root = base::StringPiece()) const;
-
- // Wrapper for ResolveRelativeAs.
- template <typename StringType>
- SourceDir ResolveRelativeDir(
- const Value& blame_input_value,
- const StringType& input_value,
- Err* err,
- const base::StringPiece& source_root = base::StringPiece()) const {
- SourceDir ret;
- ret.value_ = ResolveRelativeAs<StringType>(false, blame_input_value,
- input_value, err, source_root);
- return ret;
- }
-
- // Wrapper for ResolveRelativeDir where input_value equals to
- // v.string_value().
- SourceDir ResolveRelativeDir(
- const Value& v,
- Err* err,
- const base::StringPiece& source_root = base::StringPiece()) const;
-
- // Resolves this source file relative to some given source root. Returns
- // an empty file path on error.
- base::FilePath Resolve(const base::FilePath& source_root) const;
-
- bool is_null() const { return value_.empty(); }
- const std::string& value() const { return value_; }
-
- // Returns true if this path starts with a "//" which indicates a path
- // from the source root.
- bool is_source_absolute() const {
- return value_.size() >= 2 && value_[0] == '/' && value_[1] == '/';
- }
-
- // Returns true if this path starts with a single slash which indicates a
- // system-absolute path.
- bool is_system_absolute() const {
- return !is_source_absolute();
- }
-
- // Returns a source-absolute path starting with only one slash at the
- // beginning (normally source-absolute paths start with two slashes to mark
- // them as such). This is normally used when concatenating directories
- // together.
- //
- // This function asserts that the directory is actually source-absolute. The
- // return value points into our buffer.
- base::StringPiece SourceAbsoluteWithOneSlash() const {
- CHECK(is_source_absolute());
- return base::StringPiece(&value_[1], value_.size() - 1);
- }
-
- void SwapValue(std::string* v);
-
- bool operator==(const SourceDir& other) const {
- return value_ == other.value_;
- }
- bool operator!=(const SourceDir& other) const {
- return !operator==(other);
- }
- bool operator<(const SourceDir& other) const {
- return value_ < other.value_;
- }
-
- void swap(SourceDir& other) {
- value_.swap(other.value_);
- }
-
- private:
- friend class SourceFile;
- std::string value_;
-
- // Copy & assign supported.
-};
-
-namespace BASE_HASH_NAMESPACE {
-
-template<> struct hash<SourceDir> {
- std::size_t operator()(const SourceDir& v) const {
- hash<std::string> h;
- return h(v.value());
- }
-};
-
-} // namespace BASE_HASH_NAMESPACE
-
-inline void swap(SourceDir& lhs, SourceDir& rhs) {
- lhs.swap(rhs);
-}
-
-#endif // TOOLS_GN_SOURCE_DIR_H_
diff --git a/chromium/tools/gn/source_dir_unittest.cc b/chromium/tools/gn/source_dir_unittest.cc
deleted file mode 100644
index 80f9a5f6d4b..00000000000
--- a/chromium/tools/gn/source_dir_unittest.cc
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/err.h"
-#include "tools/gn/source_dir.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/value.h"
-
-TEST(SourceDir, ResolveRelativeFile) {
- Err err;
- SourceDir base("//base/");
-#if defined(OS_WIN)
- base::StringPiece source_root("C:/source/root");
-#else
- base::StringPiece source_root("/source/root");
-#endif
-
- // Empty input is an error.
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, std::string()), &err, source_root) == SourceFile());
- EXPECT_TRUE(err.has_error());
-
- // These things are directories, so should be an error.
- err = Err();
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "//foo/bar/"), &err, source_root) == SourceFile());
- EXPECT_TRUE(err.has_error());
-
- err = Err();
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "bar/"), &err, source_root) == SourceFile());
- EXPECT_TRUE(err.has_error());
-
- // Absolute paths should be passed unchanged.
- err = Err();
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "//foo"), &err, source_root) == SourceFile("//foo"));
- EXPECT_FALSE(err.has_error());
-
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "/foo"), &err, source_root) == SourceFile("/foo"));
- EXPECT_FALSE(err.has_error());
-
- // Basic relative stuff.
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "foo"), &err, source_root) == SourceFile("//base/foo"));
- EXPECT_FALSE(err.has_error());
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "./foo"), &err, source_root) == SourceFile("//base/foo"));
- EXPECT_FALSE(err.has_error());
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "../foo"), &err, source_root) == SourceFile("//foo"));
- EXPECT_FALSE(err.has_error());
-
- // If the given relative path points outside the source root, we
- // expect an absolute path.
-#if defined(OS_WIN)
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "../../foo"), &err, source_root) ==
- SourceFile("/C:/source/foo"));
- EXPECT_FALSE(err.has_error());
-
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "//../foo"), &err, source_root) ==
- SourceFile("/C:/source/foo"));
- EXPECT_FALSE(err.has_error());
-
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "//../root/foo"), &err, source_root) ==
- SourceFile("/C:/source/root/foo"));
- EXPECT_FALSE(err.has_error());
-
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "//../../../foo/bar"), &err, source_root) ==
- SourceFile("/foo/bar"));
- EXPECT_FALSE(err.has_error());
-#else
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "../../foo"), &err, source_root) ==
- SourceFile("/source/foo"));
- EXPECT_FALSE(err.has_error());
-
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "//../foo"), &err, source_root) ==
- SourceFile("/source/foo"));
- EXPECT_FALSE(err.has_error());
-
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "//../root/foo"), &err, source_root) ==
- SourceFile("/source/root/foo"));
- EXPECT_FALSE(err.has_error());
-
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "//../../../foo/bar"), &err, source_root) ==
- SourceFile("/foo/bar"));
- EXPECT_FALSE(err.has_error());
-#endif
-
-#if defined(OS_WIN)
- // Note that we don't canonicalize the backslashes to forward slashes.
- // This could potentially be changed in the future which would mean we should
- // just change the expected result.
- EXPECT_TRUE(base.ResolveRelativeFile(
- Value(nullptr, "C:\\foo\\bar.txt"), &err, source_root) ==
- SourceFile("/C:/foo/bar.txt"));
- EXPECT_FALSE(err.has_error());
-#endif
-}
-
-TEST(SourceDir, ResolveRelativeDir) {
- Err err;
- SourceDir base("//base/");
-#if defined(OS_WIN)
- base::StringPiece source_root("C:/source/root");
-#else
- base::StringPiece source_root("/source/root");
-#endif
-
- // Empty input is an error.
- EXPECT_TRUE(base.ResolveRelativeDir(
- Value(nullptr, std::string()), &err, source_root) == SourceDir());
- EXPECT_TRUE(err.has_error());
-
- // Absolute paths should be passed unchanged.
- err = Err();
- EXPECT_TRUE(base.ResolveRelativeDir(
- Value(nullptr, "//foo"), &err, source_root) == SourceDir("//foo/"));
- EXPECT_FALSE(err.has_error());
- EXPECT_TRUE(base.ResolveRelativeDir(
- Value(nullptr, "/foo"), &err, source_root) == SourceDir("/foo/"));
- EXPECT_FALSE(err.has_error());
-
- // Basic relative stuff.
- EXPECT_TRUE(base.ResolveRelativeDir(
- Value(nullptr, "foo"), &err, source_root) == SourceDir("//base/foo/"));
- EXPECT_FALSE(err.has_error());
- EXPECT_TRUE(base.ResolveRelativeDir(
- Value(nullptr, "./foo"), &err, source_root) == SourceDir("//base/foo/"));
- EXPECT_FALSE(err.has_error());
- EXPECT_TRUE(base.ResolveRelativeDir(
- Value(nullptr, "../foo"), &err, source_root) == SourceDir("//foo/"));
- EXPECT_FALSE(err.has_error());
-
- // If the given relative path points outside the source root, we
- // expect an absolute path.
-#if defined(OS_WIN)
- EXPECT_TRUE(base.ResolveRelativeDir(
- Value(nullptr, "../../foo"), &err, source_root) ==
- SourceDir("/C:/source/foo/"));
- EXPECT_FALSE(err.has_error());
- EXPECT_TRUE(base.ResolveRelativeDir(
- Value(nullptr, "//../foo"), &err, source_root) ==
- SourceDir("/C:/source/foo/"));
- EXPECT_FALSE(err.has_error());
- EXPECT_TRUE(base.ResolveRelativeDir(
- Value(nullptr, "//.."), &err, source_root) ==
- SourceDir("/C:/source/"));
- EXPECT_FALSE(err.has_error());
-#else
- EXPECT_TRUE(base.ResolveRelativeDir(
- Value(nullptr, "../../foo"), &err, source_root) ==
- SourceDir("/source/foo/"));
- EXPECT_FALSE(err.has_error());
- EXPECT_TRUE(base.ResolveRelativeDir(
- Value(nullptr, "//../foo"), &err, source_root) ==
- SourceDir("/source/foo/"));
- EXPECT_FALSE(err.has_error());
- EXPECT_TRUE(base.ResolveRelativeDir(
- Value(nullptr, "//.."), &err, source_root) ==
- SourceDir("/source/"));
- EXPECT_FALSE(err.has_error());
-#endif
-
-#if defined(OS_WIN)
- // Canonicalize the existing backslashes to forward slashes and add a
- // leading slash if necessary.
- EXPECT_TRUE(base.ResolveRelativeDir(
- Value(nullptr, "\\C:\\foo"), &err) == SourceDir("/C:/foo/"));
- EXPECT_FALSE(err.has_error());
- EXPECT_TRUE(base.ResolveRelativeDir(
- Value(nullptr, "C:\\foo"), &err) == SourceDir("/C:/foo/"));
- EXPECT_FALSE(err.has_error());
-#endif
-}
diff --git a/chromium/tools/gn/source_file.cc b/chromium/tools/gn/source_file.cc
deleted file mode 100644
index befc5a590f6..00000000000
--- a/chromium/tools/gn/source_file.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/source_file.h"
-
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/source_dir.h"
-
-namespace {
-
-void AssertValueSourceFileString(const std::string& s) {
-#if defined(OS_WIN)
- DCHECK(s[0] == '/' ||
- (s.size() > 2 && s[0] != '/' && s[1] == ':' && IsSlash(s[2])));
-#else
- DCHECK(s[0] == '/');
-#endif
- DCHECK(!EndsWithSlash(s)) << s;
-}
-
-} // namespace
-
-SourceFile::SourceFile() = default;
-
-SourceFile::SourceFile(const base::StringPiece& p)
- : value_(p.data(), p.size()) {
- DCHECK(!value_.empty());
- AssertValueSourceFileString(value_);
- NormalizePath(&value_);
-}
-
-SourceFile::SourceFile(SwapIn, std::string* value) {
- value_.swap(*value);
- DCHECK(!value_.empty());
- AssertValueSourceFileString(value_);
- NormalizePath(&value_);
-}
-
-SourceFile::~SourceFile() = default;
-
-std::string SourceFile::GetName() const {
- if (is_null())
- return std::string();
-
- DCHECK(value_.find('/') != std::string::npos);
- size_t last_slash = value_.rfind('/');
- return std::string(&value_[last_slash + 1],
- value_.size() - last_slash - 1);
-}
-
-SourceDir SourceFile::GetDir() const {
- if (is_null())
- return SourceDir();
-
- DCHECK(value_.find('/') != std::string::npos);
- size_t last_slash = value_.rfind('/');
- return SourceDir(base::StringPiece(&value_[0], last_slash + 1));
-}
-
-base::FilePath SourceFile::Resolve(const base::FilePath& source_root) const {
- return ResolvePath(value_, true, source_root);
-}
diff --git a/chromium/tools/gn/source_file.h b/chromium/tools/gn/source_file.h
deleted file mode 100644
index 06bbd110ab9..00000000000
--- a/chromium/tools/gn/source_file.h
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_SOURCE_FILE_H_
-#define TOOLS_GN_SOURCE_FILE_H_
-
-#include <stddef.h>
-
-#include <algorithm>
-#include <string>
-
-#include "base/containers/hash_tables.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/strings/string_piece.h"
-
-class SourceDir;
-
-// Represents a file within the source tree. Always begins in a slash, never
-// ends in one.
-class SourceFile {
- public:
- enum SwapIn { SWAP_IN };
-
- SourceFile();
-
- // Takes a known absolute source file. Always begins in a slash.
- explicit SourceFile(const base::StringPiece& p);
- SourceFile(const SourceFile& other) = default;
-
- // Constructs from the given string by swapping in the contents of the given
- // value. The value will be the empty string after this call.
- SourceFile(SwapIn, std::string* value);
-
- ~SourceFile();
-
- bool is_null() const { return value_.empty(); }
- const std::string& value() const { return value_; }
-
- // Returns everything after the last slash.
- std::string GetName() const;
- SourceDir GetDir() const;
-
- // Resolves this source file relative to some given source root. Returns
- // an empty file path on error.
- base::FilePath Resolve(const base::FilePath& source_root) const;
-
- // Returns true if this file starts with a "//" which indicates a path
- // from the source root.
- bool is_source_absolute() const {
- return value_.size() >= 2 && value_[0] == '/' && value_[1] == '/';
- }
-
- // Returns true if this file starts with a single slash which indicates a
- // system-absolute path.
- bool is_system_absolute() const {
- return !is_source_absolute();
- }
-
- // Returns a source-absolute path starting with only one slash at the
- // beginning (normally source-absolute paths start with two slashes to mark
- // them as such). This is normally used when concatenating names together.
- //
- // This function asserts that the file is actually source-absolute. The
- // return value points into our buffer.
- base::StringPiece SourceAbsoluteWithOneSlash() const {
- CHECK(is_source_absolute());
- return base::StringPiece(&value_[1], value_.size() - 1);
- }
-
- bool operator==(const SourceFile& other) const {
- return value_ == other.value_;
- }
- bool operator!=(const SourceFile& other) const {
- return !operator==(other);
- }
- bool operator<(const SourceFile& other) const {
- return value_ < other.value_;
- }
-
- void swap(SourceFile& other) {
- value_.swap(other.value_);
- }
-
- private:
- friend class SourceDir;
-
- std::string value_;
-
- // Copy & assign supported.
-};
-
-namespace BASE_HASH_NAMESPACE {
-
-template<> struct hash<SourceFile> {
- std::size_t operator()(const SourceFile& v) const {
- hash<std::string> h;
- return h(v.value());
- }
-};
-
-} // namespace BASE_HASH_NAMESPACE
-
-inline void swap(SourceFile& lhs, SourceFile& rhs) {
- lhs.swap(rhs);
-}
-
-#endif // TOOLS_GN_SOURCE_FILE_H_
diff --git a/chromium/tools/gn/source_file_type.cc b/chromium/tools/gn/source_file_type.cc
deleted file mode 100644
index 328b2abbac3..00000000000
--- a/chromium/tools/gn/source_file_type.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/source_file_type.h"
-
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/source_file.h"
-
-SourceFileType GetSourceFileType(const SourceFile& file) {
- base::StringPiece extension = FindExtension(&file.value());
- if (extension == "cc" || extension == "cpp" || extension == "cxx")
- return SOURCE_CPP;
- if (extension == "h" || extension == "hpp" || extension == "hxx" ||
- extension == "hh")
- return SOURCE_H;
- if (extension == "c")
- return SOURCE_C;
- if (extension == "m")
- return SOURCE_M;
- if (extension == "mm")
- return SOURCE_MM;
- if (extension == "rc")
- return SOURCE_RC;
- if (extension == "S" || extension == "s" || extension == "asm")
- return SOURCE_S;
- if (extension == "o" || extension == "obj")
- return SOURCE_O;
- if (extension == "def")
- return SOURCE_DEF;
-
- return SOURCE_UNKNOWN;
-}
-
diff --git a/chromium/tools/gn/source_file_type.h b/chromium/tools/gn/source_file_type.h
deleted file mode 100644
index c43b4324443..00000000000
--- a/chromium/tools/gn/source_file_type.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_SOURCE_FILE_TYPE_H_
-#define TOOLS_GN_SOURCE_FILE_TYPE_H_
-
-class SourceFile;
-
-// This should be sequential integers starting from 0 so they can be used as
-// array indices.
-enum SourceFileType {
- SOURCE_UNKNOWN = 0,
- SOURCE_ASM,
- SOURCE_C,
- SOURCE_CPP,
- SOURCE_H,
- SOURCE_M,
- SOURCE_MM,
- SOURCE_S,
- SOURCE_RC,
- SOURCE_O, // Object files can be inputs, too. Also counts .obj.
- SOURCE_DEF,
-
- // Must be last.
- SOURCE_NUMTYPES,
-};
-
-SourceFileType GetSourceFileType(const SourceFile& file);
-
-#endif // TOOLS_GN_SOURCE_FILE_TYPE_H_
diff --git a/chromium/tools/gn/source_file_unittest.cc b/chromium/tools/gn/source_file_unittest.cc
deleted file mode 100644
index 8a9218f5d28..00000000000
--- a/chromium/tools/gn/source_file_unittest.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/source_file.h"
-
-// The SourceFile object should normalize the input passed to the constructor.
-// The normalizer unit test checks for all the weird edge cases for normalizing
-// so here just check that it gets called.
-TEST(SourceFile, Normalize) {
- SourceFile a("//foo/../bar.cc");
- EXPECT_EQ("//bar.cc", a.value());
-
- std::string b_str("//foo/././../bar.cc");
- SourceFile b(SourceFile::SwapIn(), &b_str);
- EXPECT_TRUE(b_str.empty()); // Should have been swapped in.
- EXPECT_EQ("//bar.cc", b.value());
-}
diff --git a/chromium/tools/gn/standard_out.cc b/chromium/tools/gn/standard_out.cc
deleted file mode 100644
index 8a6b7ef63b0..00000000000
--- a/chromium/tools/gn/standard_out.cc
+++ /dev/null
@@ -1,335 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/standard_out.h"
-
-#include <stddef.h>
-
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "build/build_config.h"
-#include "tools/gn/switches.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#else
-#include <stdio.h>
-#include <unistd.h>
-#endif
-
-namespace {
-
-bool initialized = false;
-
-#if defined(OS_WIN)
-HANDLE hstdout;
-WORD default_attributes;
-#endif
-bool is_console = false;
-
-bool is_markdown = false;
-
-void EnsureInitialized() {
- if (initialized)
- return;
- initialized = true;
-
- const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
- if (cmdline->HasSwitch(switches::kMarkdown)) {
- // Output help in Markdown's syntax, not color-highlighted.
- is_markdown = true;
- }
-
- if (cmdline->HasSwitch(switches::kNoColor)) {
- // Force color off.
- is_console = false;
- return;
- }
-
-#if defined(OS_WIN)
- // On Windows, we can't force the color on. If the output handle isn't a
- // console, there's nothing we can do about it.
- hstdout = ::GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_SCREEN_BUFFER_INFO info;
- is_console = !!::GetConsoleScreenBufferInfo(hstdout, &info);
- default_attributes = info.wAttributes;
-#else
- if (cmdline->HasSwitch(switches::kColor))
- is_console = true;
- else
- is_console = isatty(fileno(stdout));
-#endif
-}
-
-#if !defined(OS_WIN)
-void WriteToStdOut(const std::string& output) {
- size_t written_bytes = fwrite(output.data(), 1, output.size(), stdout);
- DCHECK_EQ(output.size(), written_bytes);
-}
-#endif // !defined(OS_WIN)
-
-void OutputMarkdownDec(TextDecoration dec) {
- // The markdown rendering turns "dim" text to italics and any
- // other colored text to bold.
-
-#if defined(OS_WIN)
- DWORD written = 0;
- if (dec == DECORATION_DIM)
- ::WriteFile(hstdout, "*", 1, &written, nullptr);
- else if (dec != DECORATION_NONE)
- ::WriteFile(hstdout, "**", 2, &written, nullptr);
-#else
- if (dec == DECORATION_DIM)
- WriteToStdOut("*");
- else if (dec != DECORATION_NONE)
- WriteToStdOut("**");
-#endif
-}
-
-} // namespace
-
-#if defined(OS_WIN)
-
-void OutputString(const std::string& output, TextDecoration dec) {
- EnsureInitialized();
- DWORD written = 0;
-
- if (is_markdown) {
- OutputMarkdownDec(dec);
- } else if (is_console) {
- switch (dec) {
- case DECORATION_NONE:
- break;
- case DECORATION_DIM:
- ::SetConsoleTextAttribute(hstdout, FOREGROUND_INTENSITY);
- break;
- case DECORATION_RED:
- ::SetConsoleTextAttribute(hstdout,
- FOREGROUND_RED | FOREGROUND_INTENSITY);
- break;
- case DECORATION_GREEN:
- // Keep green non-bold.
- ::SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN);
- break;
- case DECORATION_BLUE:
- ::SetConsoleTextAttribute(hstdout,
- FOREGROUND_BLUE | FOREGROUND_INTENSITY);
- break;
- case DECORATION_YELLOW:
- ::SetConsoleTextAttribute(hstdout,
- FOREGROUND_RED | FOREGROUND_GREEN);
- break;
- }
- }
-
- std::string tmpstr = output;
- if (is_markdown && dec == DECORATION_YELLOW) {
- // https://code.google.com/p/gitiles/issues/detail?id=77
- // Gitiles will replace "--" with an em dash in non-code text.
- // Figuring out all instances of this might be difficult, but we can
- // at least escape the instances where this shows up in a heading.
- base::ReplaceSubstringsAfterOffset(&tmpstr, 0, "--", "\\--");
- }
- ::WriteFile(hstdout, tmpstr.c_str(), static_cast<DWORD>(tmpstr.size()),
- &written, nullptr);
-
- if (is_markdown) {
- OutputMarkdownDec(dec);
- } else if (is_console) {
- ::SetConsoleTextAttribute(hstdout, default_attributes);
- }
-}
-
-#else
-
-void OutputString(const std::string& output, TextDecoration dec) {
- EnsureInitialized();
- if (is_markdown) {
- OutputMarkdownDec(dec);
- } else if (is_console) {
- switch (dec) {
- case DECORATION_NONE:
- break;
- case DECORATION_DIM:
- WriteToStdOut("\e[2m");
- break;
- case DECORATION_RED:
- WriteToStdOut("\e[31m\e[1m");
- break;
- case DECORATION_GREEN:
- WriteToStdOut("\e[32m");
- break;
- case DECORATION_BLUE:
- WriteToStdOut("\e[34m\e[1m");
- break;
- case DECORATION_YELLOW:
- WriteToStdOut("\e[33m\e[1m");
- break;
- }
- }
-
- std::string tmpstr = output;
- if (is_markdown && dec == DECORATION_YELLOW) {
- // https://code.google.com/p/gitiles/issues/detail?id=77
- // Gitiles will replace "--" with an em dash in non-code text.
- // Figuring out all instances of this might be difficult, but we can
- // at least escape the instances where this shows up in a heading.
- base::ReplaceSubstringsAfterOffset(&tmpstr, 0, "--", "\\--");
- }
- WriteToStdOut(tmpstr.data());
-
- if (is_markdown) {
- OutputMarkdownDec(dec);
- } else if (is_console && dec != DECORATION_NONE) {
- WriteToStdOut("\e[0m");
- }
-}
-
-#endif
-
-void PrintSectionHelp(const std::string& line,
- const std::string& topic,
- const std::string& tag) {
- EnsureInitialized();
-
- if (is_markdown) {
- OutputString("* [" + line + "](#" + tag + ")\n");
- } else if (topic.size()) {
- OutputString("\n" + line + " (type \"gn help " + topic +
- "\" for more help):\n");
- } else {
- OutputString("\n" + line + ":\n");
- }
-}
-
-void PrintShortHelp(const std::string& line) {
- EnsureInitialized();
-
- size_t colon_offset = line.find(':');
- size_t first_normal = 0;
- if (colon_offset != std::string::npos) {
- if (is_markdown) {
- OutputString(" * [" + line + "](#" + line.substr(0, colon_offset) +
- ")\n");
- } else {
- OutputString(" " + line.substr(0, colon_offset), DECORATION_YELLOW);
- first_normal = colon_offset;
- }
- } else if (is_markdown) {
- OutputString(" * [" + line + "](" + line + ")\n");
- }
-
- if (is_markdown)
- return;
-
- // See if the colon is followed by a " [" and if so, dim the contents of [ ].
- if (first_normal > 0 &&
- line.size() > first_normal + 2 &&
- line[first_normal + 1] == ' ' && line[first_normal + 2] == '[') {
- size_t begin_bracket = first_normal + 2;
- OutputString(": ");
- first_normal = line.find(']', begin_bracket);
- if (first_normal == std::string::npos)
- first_normal = line.size();
- else
- first_normal++;
- OutputString(line.substr(begin_bracket, first_normal - begin_bracket),
- DECORATION_DIM);
- }
-
- OutputString(line.substr(first_normal) + "\n");
-}
-
-void PrintLongHelp(const std::string& text, const std::string& tag) {
- EnsureInitialized();
-
- bool first_header = true;
- bool in_body = false;
- std::size_t empty_lines = 0;
- for (const std::string& line : base::SplitString(
- text, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL)) {
- // Check for a heading line.
- if (!line.empty() && line[0] != ' ') {
- // New paragraph, just skip any trailing empty lines.
- empty_lines = 0;
-
- if (is_markdown) {
- // GN's block-level formatting is converted to markdown as follows:
- // * The first heading is treated as an H3.
- // * Subsequent heading are treated as H4s.
- // * Any other text is wrapped in a code block and displayed as-is.
- //
- // Span-level formatting (the decorations) is converted inside
- // OutputString().
- if (in_body) {
- OutputString("```\n\n", DECORATION_NONE);
- in_body = false;
- }
-
- if (first_header) {
- std::string the_tag = tag;
- if (the_tag.size() == 0) {
- if (line.substr(0, 2) == "gn") {
- the_tag = line.substr(3, line.substr(3).find(' '));
- } else {
- the_tag = line.substr(0, line.find(':'));
- }
- }
- OutputString("### <a name=\"" + the_tag + "\"></a>", DECORATION_NONE);
- first_header = false;
- } else {
- OutputString("#### ", DECORATION_NONE);
- }
- }
-
- // Highlight up to the colon (if any).
- size_t chars_to_highlight = line.find(':');
- if (chars_to_highlight == std::string::npos)
- chars_to_highlight = line.size();
-
- OutputString(line.substr(0, chars_to_highlight), DECORATION_YELLOW);
- OutputString(line.substr(chars_to_highlight));
- OutputString("\n");
- continue;
- } else if (is_markdown && !line.empty() && !in_body) {
- OutputString("```\n", DECORATION_NONE);
- in_body = true;
- }
-
- // We buffer empty lines, so we can skip them if needed
- // (i.e. new paragraph body, end of final paragraph body).
- if (in_body && is_markdown) {
- if (!line.empty() && empty_lines != 0) {
- OutputString(std::string(empty_lines, '\n'));
- empty_lines = 0;
- } else if (line.empty()) {
- ++empty_lines;
- continue;
- }
- }
-
- // Check for a comment.
- TextDecoration dec = DECORATION_NONE;
- for (const auto& elem : line) {
- if (elem == '#' && !is_markdown) {
- // Got a comment, draw dimmed.
- dec = DECORATION_DIM;
- break;
- } else if (elem != ' ') {
- break;
- }
- }
-
- OutputString(line + "\n", dec);
- }
-
- if (is_markdown && in_body)
- OutputString("```\n");
-}
-
diff --git a/chromium/tools/gn/standard_out.h b/chromium/tools/gn/standard_out.h
deleted file mode 100644
index f2bb733b6bd..00000000000
--- a/chromium/tools/gn/standard_out.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_STANDARD_OUT_H_
-#define TOOLS_GN_STANDARD_OUT_H_
-
-#include <string>
-
-enum TextDecoration {
- DECORATION_NONE = 0,
- DECORATION_DIM,
- DECORATION_RED,
- DECORATION_GREEN,
- DECORATION_BLUE,
- DECORATION_YELLOW
-};
-
-void OutputString(const std::string& output,
- TextDecoration dec = DECORATION_NONE);
-
-// If printing markdown, this generates table-of-contents entries with
-// links to the actual help; otherwise, prints a one-line description.
-void PrintSectionHelp(const std::string& line,
- const std::string& topic,
- const std::string& tag);
-
-// Prints a line for a command, assuming there is a colon. Everything before
-// the colon is the command (and is highlighted). After the colon if there is
-// a square bracket, the contents of the bracket is dimmed.
-//
-// The line is indented 2 spaces.
-void PrintShortHelp(const std::string& line);
-
-// Rules:
-// - Lines beginning with non-whitespace are highlighted up to the first
-// colon (or the whole line if not).
-// - Lines whose first non-whitespace character is a # are dimmed.
-void PrintLongHelp(const std::string& text, const std::string& tag = "");
-
-#endif // TOOLS_GN_STANDARD_OUT_H_
diff --git a/chromium/tools/gn/string_utils.cc b/chromium/tools/gn/string_utils.cc
deleted file mode 100644
index 5e8068111a5..00000000000
--- a/chromium/tools/gn/string_utils.cc
+++ /dev/null
@@ -1,345 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/string_utils.h"
-
-#include <stddef.h>
-#include <cctype>
-
-#include "base/strings/string_number_conversions.h"
-#include "tools/gn/err.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parser.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/token.h"
-#include "tools/gn/tokenizer.h"
-#include "tools/gn/value.h"
-
-namespace {
-
-// Constructs an Err indicating a range inside a string. We assume that the
-// token has quotes around it that are not counted by the offset.
-Err ErrInsideStringToken(const Token& token, size_t offset, size_t size,
- const std::string& msg,
- const std::string& help = std::string()) {
- // The "+1" is skipping over the " at the beginning of the token.
- int int_offset = static_cast<int>(offset);
- Location begin_loc(token.location().file(),
- token.location().line_number(),
- token.location().column_number() + int_offset + 1,
- token.location().byte() + int_offset + 1);
- Location end_loc(
- token.location().file(),
- token.location().line_number(),
- token.location().column_number() + int_offset + 1 +
- static_cast<int>(size),
- token.location().byte() + int_offset + 1 + static_cast<int>(size));
- return Err(LocationRange(begin_loc, end_loc), msg, help);
-}
-
-// Notes about expression interpolation. This is based loosly on Dart but is
-// slightly less flexible. In Dart, seeing the ${ in a string is something
-// the toplevel parser knows about, and it will recurse into the block
-// treating it as a first-class {...} block. So even things like this work:
-// "hello ${"foo}"*2+"bar"}" => "hello foo}foo}bar"
-// (you can see it did not get confused by the nested strings or the nested "}"
-// inside the block).
-//
-// This is cool but complicates the parser for almost no benefit for this
-// non-general-purpose programming language. The main reason expressions are
-// supported here at all are to support "${scope.variable}" and "${list[0]}",
-// neither of which have any of these edge-cases.
-//
-// In this simplified approach, we search for the terminating '}' and execute
-// the result. This means we can't support any expressions with embedded '}'
-// or '"'. To keep people from getting confusing about what's supported and
-// what's not, only identifier and accessor expressions are allowed (neither
-// of these run into any of these edge-cases).
-bool AppendInterpolatedExpression(Scope* scope,
- const Token& token,
- const char* input,
- size_t begin_offset,
- size_t end_offset,
- std::string* output,
- Err* err) {
- SourceFile empty_source_file; // Prevent most vexing parse.
- InputFile input_file(empty_source_file);
- input_file.SetContents(
- std::string(&input[begin_offset], end_offset - begin_offset));
-
- // Tokenize.
- std::vector<Token> tokens = Tokenizer::Tokenize(&input_file, err);
- if (err->has_error()) {
- // The error will point into our temporary buffer, rewrite it to refer
- // to the original token. This will make the location information less
- // precise, but generally there won't be complicated things in string
- // interpolations.
- *err = ErrInsideStringToken(token, begin_offset, end_offset - begin_offset,
- err->message(), err->help_text());
- return false;
- }
-
- // Parse.
- std::unique_ptr<ParseNode> node = Parser::ParseExpression(tokens, err);
- if (err->has_error()) {
- // Rewrite error as above.
- *err = ErrInsideStringToken(token, begin_offset, end_offset - begin_offset,
- err->message(), err->help_text());
- return false;
- }
- if (!(node->AsIdentifier() || node->AsAccessor())) {
- *err = ErrInsideStringToken(token, begin_offset, end_offset - begin_offset,
- "Invalid string interpolation.",
- "The thing inside the ${} must be an identifier ${foo},\n"
- "a scope access ${foo.bar}, or a list access ${foo[0]}.");
- return false;
- }
-
- // Evaluate.
- Value result = node->Execute(scope, err);
- if (err->has_error()) {
- // Rewrite error as above.
- *err = ErrInsideStringToken(token, begin_offset, end_offset - begin_offset,
- err->message(), err->help_text());
- return false;
- }
-
- output->append(result.ToString(false));
- return true;
-}
-
-bool AppendInterpolatedIdentifier(Scope* scope,
- const Token& token,
- const char* input,
- size_t begin_offset,
- size_t end_offset,
- std::string* output,
- Err* err) {
- base::StringPiece identifier(&input[begin_offset],
- end_offset - begin_offset);
- const Value* value = scope->GetValue(identifier, true);
- if (!value) {
- // We assume the input points inside the token.
- *err = ErrInsideStringToken(
- token, identifier.data() - token.value().data() - 1, identifier.size(),
- "Undefined identifier in string expansion.",
- std::string("\"") + identifier + "\" is not currently in scope.");
- return false;
- }
-
- output->append(value->ToString(false));
- return true;
-}
-
-// Handles string interpolations: $identifier and ${expression}
-//
-// |*i| is the index into |input| after the $. This will be updated to point to
-// the last character consumed on success. The token is the original string
-// to blame on failure.
-//
-// On failure, returns false and sets the error. On success, appends the
-// result of the interpolation to |*output|.
-bool AppendStringInterpolation(Scope* scope,
- const Token& token,
- const char* input, size_t size,
- size_t* i,
- std::string* output,
- Err* err) {
- size_t dollars_index = *i - 1;
-
- if (input[*i] == '{') {
- // Bracketed expression.
- (*i)++;
- size_t begin_offset = *i;
-
- // Find the closing } and check for non-identifier chars. Don't need to
- // bother checking for the more-restricted first character of an identifier
- // since the {} unambiguously denotes the range, and identifiers with
- // invalid names just won't be found later.
- bool has_non_ident_chars = false;
- while (*i < size && input[*i] != '}') {
- has_non_ident_chars |= Tokenizer::IsIdentifierContinuingChar(input[*i]);
- (*i)++;
- }
- if (*i == size) {
- *err = ErrInsideStringToken(token, dollars_index, *i - dollars_index,
- "Unterminated ${...");
- return false;
- }
-
- // In the common case, the thing inside the {} will actually be a
- // simple identifier. Avoid all the complicated parsing of accessors
- // in this case.
- if (!has_non_ident_chars) {
- return AppendInterpolatedIdentifier(scope, token, input, begin_offset,
- *i, output, err);
- }
- return AppendInterpolatedExpression(scope, token, input, begin_offset, *i,
- output, err);
- }
-
- // Simple identifier.
- // The first char of an identifier is more restricted.
- if (!Tokenizer::IsIdentifierFirstChar(input[*i])) {
- *err = ErrInsideStringToken(
- token, dollars_index, *i - dollars_index + 1,
- "$ not followed by an identifier char.",
- "It you want a literal $ use \"\\$\".");
- return false;
- }
- size_t begin_offset = *i;
- (*i)++;
-
- // Find the first non-identifier char following the string.
- while (*i < size && Tokenizer::IsIdentifierContinuingChar(input[*i]))
- (*i)++;
- size_t end_offset = *i;
- (*i)--; // Back up to mark the last character consumed.
- return AppendInterpolatedIdentifier(scope, token, input, begin_offset,
- end_offset, output, err);
-}
-
-// Handles a hex literal: $0xFF
-//
-// |*i| is the index into |input| after the $. This will be updated to point to
-// the last character consumed on success. The token is the original string
-// to blame on failure.
-//
-// On failure, returns false and sets the error. On success, appends the
-// char with the given hex value to |*output|.
-bool AppendHexByte(Scope* scope,
- const Token& token,
- const char* input, size_t size,
- size_t* i,
- std::string* output,
- Err* err) {
- size_t dollars_index = *i - 1;
- // "$0" is already known to exist.
- if (*i + 3 >= size || input[*i + 1] != 'x' || !std::isxdigit(input[*i + 2]) ||
- !std::isxdigit(input[*i + 3])) {
- *err = ErrInsideStringToken(
- token, dollars_index, *i - dollars_index + 1,
- "Invalid hex character. Hex values must look like 0xFF.");
- return false;
- }
- int value = 0;
- if (!base::HexStringToInt(base::StringPiece(&input[*i + 2], 2), &value)) {
- *err = ErrInsideStringToken(token, dollars_index, *i - dollars_index + 1,
- "Could not convert hex value.");
- return false;
- }
- *i += 3;
- output->push_back(value);
- return true;
-}
-
-} // namespace
-
-bool ExpandStringLiteral(Scope* scope,
- const Token& literal,
- Value* result,
- Err* err) {
- DCHECK(literal.type() == Token::STRING);
- DCHECK(literal.value().size() > 1); // Should include quotes.
- DCHECK(result->type() == Value::STRING); // Should be already set.
-
- // The token includes the surrounding quotes, so strip those off.
- const char* input = &literal.value().data()[1];
- size_t size = literal.value().size() - 2;
-
- std::string& output = result->string_value();
- output.reserve(size);
- for (size_t i = 0; i < size; i++) {
- if (input[i] == '\\') {
- if (i < size - 1) {
- switch (input[i + 1]) {
- case '\\':
- case '"':
- case '$':
- output.push_back(input[i + 1]);
- i++;
- continue;
- default: // Everything else has no meaning: pass the literal.
- break;
- }
- }
- output.push_back(input[i]);
- } else if (input[i] == '$') {
- i++;
- if (i == size) {
- *err = ErrInsideStringToken(literal, i - 1, 1, "$ at end of string.",
- "I was expecting an identifier, 0xFF, or {...} after the $.");
- return false;
- }
- if (input[i] == '0') {
- if (!AppendHexByte(scope, literal, input, size, &i, &output, err))
- return false;
- } else if (!AppendStringInterpolation(scope, literal, input, size, &i,
- &output, err))
- return false;
- } else {
- output.push_back(input[i]);
- }
- }
- return true;
-}
-
-size_t EditDistance(const base::StringPiece& s1,
- const base::StringPiece& s2,
- size_t max_edit_distance) {
- // The algorithm implemented below is the "classic"
- // dynamic-programming algorithm for computing the Levenshtein
- // distance, which is described here:
- //
- // http://en.wikipedia.org/wiki/Levenshtein_distance
- //
- // Although the algorithm is typically described using an m x n
- // array, only one row plus one element are used at a time, so this
- // implementation just keeps one vector for the row. To update one entry,
- // only the entries to the left, top, and top-left are needed. The left
- // entry is in row[x-1], the top entry is what's in row[x] from the last
- // iteration, and the top-left entry is stored in previous.
- size_t m = s1.size();
- size_t n = s2.size();
-
- std::vector<size_t> row(n + 1);
- for (size_t i = 1; i <= n; ++i)
- row[i] = i;
-
- for (size_t y = 1; y <= m; ++y) {
- row[0] = y;
- size_t best_this_row = row[0];
-
- size_t previous = y - 1;
- for (size_t x = 1; x <= n; ++x) {
- size_t old_row = row[x];
- row[x] = std::min(previous + (s1[y - 1] == s2[x - 1] ? 0u : 1u),
- std::min(row[x - 1], row[x]) + 1u);
- previous = old_row;
- best_this_row = std::min(best_this_row, row[x]);
- }
-
- if (max_edit_distance && best_this_row > max_edit_distance)
- return max_edit_distance + 1;
- }
-
- return row[n];
-}
-
-base::StringPiece SpellcheckString(
- const base::StringPiece& text,
- const std::vector<base::StringPiece>& words) {
- const size_t kMaxValidEditDistance = 3u;
-
- size_t min_distance = kMaxValidEditDistance + 1u;
- base::StringPiece result;
- for (base::StringPiece word : words) {
- size_t distance = EditDistance(word, text, kMaxValidEditDistance);
- if (distance < min_distance) {
- min_distance = distance;
- result = word;
- }
- }
- return result;
-}
diff --git a/chromium/tools/gn/string_utils.h b/chromium/tools/gn/string_utils.h
deleted file mode 100644
index 744714a754a..00000000000
--- a/chromium/tools/gn/string_utils.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_STRING_UTILS_H_
-#define TOOLS_GN_STRING_UTILS_H_
-
-#include <vector>
-
-#include "base/strings/string_piece.h"
-
-class Err;
-class Scope;
-class Token;
-class Value;
-
-inline std::string operator+(const std::string& a, const base::StringPiece& b) {
- std::string ret;
- ret.reserve(a.size() + b.size());
- ret.assign(a);
- ret.append(b.data(), b.size());
- return ret;
-}
-
-inline std::string operator+(const base::StringPiece& a, const std::string& b) {
- std::string ret;
- ret.reserve(a.size() + b.size());
- ret.assign(a.data(), a.size());
- ret.append(b);
- return ret;
-}
-
-// Unescapes and expands variables in the given literal, writing the result
-// to the given value. On error, sets |err| and returns false.
-bool ExpandStringLiteral(Scope* scope,
- const Token& literal,
- Value* result,
- Err* err);
-
-// Returns the minimum number of inserts, deleted, and replacements of
-// characters needed to transform s1 to s2, or max_edit_distance + 1 if
-// transforming s1 into s2 isn't possible in at most max_edit_distance steps.
-size_t EditDistance(const base::StringPiece& s1,
- const base::StringPiece& s2,
- size_t max_edit_distance);
-
-// Given a string |text| and a vector of correctly-spelled strings |words|,
-// returns the first string in |words| closest to |text|, or an empty
-// StringPiece if none of the strings in |words| is close.
-base::StringPiece SpellcheckString(const base::StringPiece& text,
- const std::vector<base::StringPiece>& words);
-
-#endif // TOOLS_GN_STRING_UTILS_H_
diff --git a/chromium/tools/gn/string_utils_unittest.cc b/chromium/tools/gn/string_utils_unittest.cc
deleted file mode 100644
index 3e87c777654..00000000000
--- a/chromium/tools/gn/string_utils_unittest.cc
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/string_utils.h"
-
-#include <stdint.h>
-
-#include <memory>
-#include <utility>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/err.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/token.h"
-#include "tools/gn/value.h"
-
-namespace {
-
-bool CheckExpansionCase(const char* input, const char* expected, bool success) {
- Scope scope(static_cast<const Settings*>(nullptr));
- int64_t one = 1;
- scope.SetValue("one", Value(nullptr, one), nullptr);
- scope.SetValue("onestring", Value(nullptr, "one"), nullptr);
-
- // Nested scope called "onescope" with a value "one" inside it.
- std::unique_ptr<Scope> onescope =
- std::make_unique<Scope>(static_cast<const Settings*>(nullptr));
- onescope->SetValue("one", Value(nullptr, one), nullptr);
- scope.SetValue("onescope", Value(nullptr, std::move(onescope)), nullptr);
-
- // List called "onelist" with one value that maps to 1.
- Value onelist(nullptr, Value::LIST);
- onelist.list_value().push_back(Value(nullptr, one));
- scope.SetValue("onelist", onelist, nullptr);
-
- // Construct the string token, which includes the quotes.
- std::string literal_string;
- literal_string.push_back('"');
- literal_string.append(input);
- literal_string.push_back('"');
- Token literal(Location(), Token::STRING, literal_string);
-
- Value result(nullptr, Value::STRING);
- Err err;
- bool ret = ExpandStringLiteral(&scope, literal, &result, &err);
-
- // Err and return value should agree.
- EXPECT_NE(ret, err.has_error());
-
- if (ret != success)
- return false;
-
- if (!success)
- return true; // Don't check result on failure.
- printf("%s\n", result.string_value().c_str());
- return result.string_value() == expected;
-}
-
-} // namespace
-
-TEST(StringUtils, ExpandStringLiteralIdentifier) {
- EXPECT_TRUE(CheckExpansionCase("", "", true));
- EXPECT_TRUE(CheckExpansionCase("hello", "hello", true));
- EXPECT_TRUE(CheckExpansionCase("hello #$one", "hello #1", true));
- EXPECT_TRUE(CheckExpansionCase("hello #$one/two", "hello #1/two", true));
- EXPECT_TRUE(CheckExpansionCase("hello #${one}", "hello #1", true));
- EXPECT_TRUE(CheckExpansionCase("hello #${one}one", "hello #1one", true));
- EXPECT_TRUE(CheckExpansionCase("hello #${one}$one", "hello #11", true));
- EXPECT_TRUE(CheckExpansionCase("$onestring${one}$one", "one11", true));
- EXPECT_TRUE(CheckExpansionCase("$onescope", "{\n one = 1\n}", true));
- EXPECT_TRUE(CheckExpansionCase("$onelist", "[1]", true));
-
- // Hex values
- EXPECT_TRUE(CheckExpansionCase("$0x0AA", "\x0A""A", true));
- EXPECT_TRUE(CheckExpansionCase("$0x0a$0xfF", "\x0A\xFF", true));
-
- // Errors
- EXPECT_TRUE(CheckExpansionCase("hello #$", nullptr, false));
- EXPECT_TRUE(CheckExpansionCase("hello #$%", nullptr, false));
- EXPECT_TRUE(CheckExpansionCase("hello #${", nullptr, false));
- EXPECT_TRUE(CheckExpansionCase("hello #${}", nullptr, false));
- EXPECT_TRUE(CheckExpansionCase("hello #$nonexistant", nullptr, false));
- EXPECT_TRUE(CheckExpansionCase("hello #${unterminated", nullptr, false));
- EXPECT_TRUE(CheckExpansionCase("hex truncated: $0", nullptr, false));
- EXPECT_TRUE(CheckExpansionCase("hex truncated: $0x", nullptr, false));
- EXPECT_TRUE(CheckExpansionCase("hex truncated: $0x0", nullptr, false));
- EXPECT_TRUE(CheckExpansionCase("hex with bad char: $0a", nullptr, false));
- EXPECT_TRUE(CheckExpansionCase("hex with bad char: $0x1z", nullptr, false));
- EXPECT_TRUE(CheckExpansionCase("hex with bad char: $0xz1", nullptr, false));
-
- // Unknown backslash values aren't special.
- EXPECT_TRUE(CheckExpansionCase("\\", "\\", true));
- EXPECT_TRUE(CheckExpansionCase("\\b", "\\b", true));
-
- // Backslashes escape some special things. \"\$\\ -> "$\ Note that gtest
- // doesn't like this escape sequence so we have to put it out-of-line.
- const char* in = "\\\"\\$\\\\";
- const char* out = "\"$\\";
- EXPECT_TRUE(CheckExpansionCase(in, out, true));
-}
-
-TEST(StringUtils, ExpandStringLiteralExpression) {
- // Accessing the scope.
- EXPECT_TRUE(CheckExpansionCase("hello #${onescope.one}", "hello #1", true));
- EXPECT_TRUE(CheckExpansionCase("hello #${onescope.two}", nullptr, false));
-
- // Accessing the list.
- EXPECT_TRUE(CheckExpansionCase("hello #${onelist[0]}", "hello #1", true));
- EXPECT_TRUE(CheckExpansionCase("hello #${onelist[1]}", nullptr, false));
-
- // Trying some other (otherwise valid) expressions should fail.
- EXPECT_TRUE(CheckExpansionCase("${1 + 2}", nullptr, false));
- EXPECT_TRUE(CheckExpansionCase("${print(1)}", nullptr, false));
-}
-
-TEST(StringUtils, EditDistance) {
- EXPECT_EQ(3u, EditDistance("doom melon", "dune melon", 100));
- EXPECT_EQ(2u, EditDistance("doom melon", "dune melon", 1));
-
- EXPECT_EQ(2u, EditDistance("ab", "ba", 100));
- EXPECT_EQ(2u, EditDistance("ba", "ab", 100));
-
- EXPECT_EQ(2u, EditDistance("ananas", "banana", 100));
- EXPECT_EQ(2u, EditDistance("banana", "ananas", 100));
-
- EXPECT_EQ(2u, EditDistance("unclear", "nuclear", 100));
- EXPECT_EQ(2u, EditDistance("nuclear", "unclear", 100));
-
- EXPECT_EQ(3u, EditDistance("chrome", "chromium", 100));
- EXPECT_EQ(3u, EditDistance("chromium", "chrome", 100));
-
- EXPECT_EQ(4u, EditDistance("", "abcd", 100));
- EXPECT_EQ(4u, EditDistance("abcd", "", 100));
-
- EXPECT_EQ(4u, EditDistance("xxx", "xxxxxxx", 100));
- EXPECT_EQ(4u, EditDistance("xxxxxxx", "xxx", 100));
-
- EXPECT_EQ(7u, EditDistance("yyy", "xxxxxxx", 100));
- EXPECT_EQ(7u, EditDistance("xxxxxxx", "yyy", 100));
-}
-
-TEST(StringUtils, SpellcheckString) {
- std::vector<base::StringPiece> words;
- words.push_back("your");
- words.push_back("bravado");
- words.push_back("won\'t");
- words.push_back("help");
- words.push_back("you");
- words.push_back("now");
-
- EXPECT_EQ("help", SpellcheckString("halp", words));
-
- // barbados has an edit distance of 4 from bravado, so there's no suggestion.
- EXPECT_TRUE(SpellcheckString("barbados", words).empty());
-}
diff --git a/chromium/tools/gn/substitution_list.cc b/chromium/tools/gn/substitution_list.cc
deleted file mode 100644
index a0fa00f4e18..00000000000
--- a/chromium/tools/gn/substitution_list.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/substitution_list.h"
-
-#include <stddef.h>
-#include <string.h>
-
-#include "tools/gn/value.h"
-
-SubstitutionList::SubstitutionList() = default;
-
-SubstitutionList::SubstitutionList(const SubstitutionList& other) = default;
-
-SubstitutionList::~SubstitutionList() = default;
-
-bool SubstitutionList::Parse(const Value& value, Err* err) {
- if (!value.VerifyTypeIs(Value::LIST, err))
- return false;
-
- const std::vector<Value>& input_list = value.list_value();
- list_.resize(input_list.size());
- for (size_t i = 0; i < input_list.size(); i++) {
- if (!list_[i].Parse(input_list[i], err))
- return false;
- }
-
- SubstitutionBits bits;
- FillRequiredTypes(&bits);
- bits.FillVector(&required_types_);
- return true;
-}
-
-bool SubstitutionList::Parse(const std::vector<std::string>& values,
- const ParseNode* origin,
- Err* err) {
- list_.resize(values.size());
- for (size_t i = 0; i < values.size(); i++) {
- if (!list_[i].Parse(values[i], origin, err))
- return false;
- }
-
- SubstitutionBits bits;
- FillRequiredTypes(&bits);
- bits.FillVector(&required_types_);
- return true;
-}
-
-SubstitutionList SubstitutionList::MakeForTest(
- const char* a,
- const char* b,
- const char* c) {
- std::vector<std::string> input_strings;
- input_strings.push_back(a);
- if (b)
- input_strings.push_back(b);
- if (c)
- input_strings.push_back(c);
-
- Err err;
- SubstitutionList result;
- result.Parse(input_strings, nullptr, &err);
- return result;
-}
-
-void SubstitutionList::FillRequiredTypes(SubstitutionBits* bits) const {
- for (const auto& item : list_)
- item.FillRequiredTypes(bits);
-}
diff --git a/chromium/tools/gn/substitution_list.h b/chromium/tools/gn/substitution_list.h
deleted file mode 100644
index eaf8a614bd6..00000000000
--- a/chromium/tools/gn/substitution_list.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_SUBSTITUTION_LIST_H_
-#define TOOLS_GN_SUBSTITUTION_LIST_H_
-
-#include <string>
-#include <vector>
-
-#include "tools/gn/substitution_pattern.h"
-
-// Represents a list of strings with {{substitution_patterns}} in them.
-class SubstitutionList {
- public:
- SubstitutionList();
- SubstitutionList(const SubstitutionList& other);
- ~SubstitutionList();
-
- bool Parse(const Value& value, Err* err);
- bool Parse(const std::vector<std::string>& values,
- const ParseNode* origin,
- Err* err);
-
- // Makes a SubstitutionList from the given hardcoded patterns.
- static SubstitutionList MakeForTest(
- const char* a,
- const char* b = nullptr,
- const char* c = nullptr);
-
- const std::vector<SubstitutionPattern>& list() const { return list_; }
-
- // Returns a list of all substitution types used by the patterns in this
- // list, with the exception of LITERAL.
- const std::vector<SubstitutionType>& required_types() const {
- return required_types_;
- }
-
- void FillRequiredTypes(SubstitutionBits* bits) const;
-
- private:
- std::vector<SubstitutionPattern> list_;
-
- std::vector<SubstitutionType> required_types_;
-};
-
-#endif // TOOLS_GN_SUBSTITUTION_LIST_H_
diff --git a/chromium/tools/gn/substitution_pattern.cc b/chromium/tools/gn/substitution_pattern.cc
deleted file mode 100644
index 756200cd0aa..00000000000
--- a/chromium/tools/gn/substitution_pattern.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/substitution_pattern.h"
-
-#include <stddef.h>
-
-#include "base/strings/string_number_conversions.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/value.h"
-
-SubstitutionPattern::Subrange::Subrange()
- : type(SUBSTITUTION_LITERAL) {
-}
-
-SubstitutionPattern::Subrange::Subrange(SubstitutionType t,
- const std::string& l)
- : type(t),
- literal(l) {
-}
-
-SubstitutionPattern::Subrange::~Subrange() = default;
-
-SubstitutionPattern::SubstitutionPattern() : origin_(nullptr) {
-}
-
-SubstitutionPattern::SubstitutionPattern(const SubstitutionPattern& other) =
- default;
-
-SubstitutionPattern::~SubstitutionPattern() = default;
-
-bool SubstitutionPattern::Parse(const Value& value, Err* err) {
- if (!value.VerifyTypeIs(Value::STRING, err))
- return false;
- return Parse(value.string_value(), value.origin(), err);
-}
-
-bool SubstitutionPattern::Parse(const std::string& str,
- const ParseNode* origin,
- Err* err) {
- DCHECK(ranges_.empty()); // Should only be called once.
-
- size_t cur = 0;
- while (true) {
- size_t next = str.find("{{", cur);
-
- // Pick up everything from the previous spot to here as a literal.
- if (next == std::string::npos) {
- if (cur != str.size())
- ranges_.push_back(Subrange(SUBSTITUTION_LITERAL, str.substr(cur)));
- break;
- } else if (next > cur) {
- ranges_.push_back(
- Subrange(SUBSTITUTION_LITERAL, str.substr(cur, next - cur)));
- }
-
- // Find which specific pattern this corresponds to.
- bool found_match = false;
- for (size_t i = SUBSTITUTION_FIRST_PATTERN;
- i < SUBSTITUTION_NUM_TYPES; i++) {
- const char* cur_pattern = kSubstitutionNames[i];
- size_t cur_len = strlen(cur_pattern);
- if (str.compare(next, cur_len, cur_pattern) == 0) {
- ranges_.push_back(Subrange(static_cast<SubstitutionType>(i)));
- cur = next + cur_len;
- found_match = true;
- break;
- }
- }
-
- // Expect all occurrances of {{ to resolve to a pattern.
- if (!found_match) {
- // Could make this error message more friendly if it comes up a lot. But
- // most people will not be writing substitution patterns and the code
- // to exactly indicate the error location is tricky.
- *err = Err(origin, "Unknown substitution pattern",
- "Found a {{ at offset " + base::NumberToString(next) +
- " and did not find a known substitution following it.");
- ranges_.clear();
- return false;
- }
- }
-
- origin_ = origin;
-
- // Fill required types vector.
- SubstitutionBits bits;
- FillRequiredTypes(&bits);
- bits.FillVector(&required_types_);
- return true;
-}
-
-// static
-SubstitutionPattern SubstitutionPattern::MakeForTest(const char* str) {
- Err err;
- SubstitutionPattern pattern;
- CHECK(pattern.Parse(str, nullptr, &err)) << err.message();
- return pattern;
-}
-
-std::string SubstitutionPattern::AsString() const {
- std::string result;
- for (const auto& elem : ranges_) {
- if (elem.type == SUBSTITUTION_LITERAL)
- result.append(elem.literal);
- else
- result.append(kSubstitutionNames[elem.type]);
- }
- return result;
-}
-
-void SubstitutionPattern::FillRequiredTypes(SubstitutionBits* bits) const {
- for (const auto& elem : ranges_) {
- if (elem.type != SUBSTITUTION_LITERAL)
- bits->used[static_cast<size_t>(elem.type)] = true;
- }
-}
-
-bool SubstitutionPattern::IsInOutputDir(const BuildSettings* build_settings,
- Err* err) const {
- if (ranges_.empty()) {
- *err = Err(origin_, "This is empty but I was expecting an output file.");
- return false;
- }
-
- if (ranges_[0].type == SUBSTITUTION_LITERAL) {
- // If the first thing is a literal, it must start with the output dir.
- if (!EnsureStringIsInOutputDir(
- build_settings->build_dir(),
- ranges_[0].literal, origin_, err))
- return false;
- } else {
- // Otherwise, the first subrange must be a pattern that expands to
- // something in the output directory.
- if (!SubstitutionIsInOutputDir(ranges_[0].type)) {
- *err = Err(origin_,
- "File is not inside output directory.",
- "The given file should be in the output directory. Normally you\n"
- "would specify\n\"$target_out_dir/foo\" or "
- "\"{{source_gen_dir}}/foo\".");
- return false;
- }
- }
-
- return true;
-}
diff --git a/chromium/tools/gn/substitution_pattern.h b/chromium/tools/gn/substitution_pattern.h
deleted file mode 100644
index 538980660fc..00000000000
--- a/chromium/tools/gn/substitution_pattern.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_SUBSTITUTION_PATTERN_H_
-#define TOOLS_GN_SUBSTITUTION_PATTERN_H_
-
-#include <string>
-#include <vector>
-
-#include "tools/gn/substitution_type.h"
-
-class BuildSettings;
-class Err;
-class ParseNode;
-class Value;
-
-// Represents a string with {{substitution_patterns}} in them.
-class SubstitutionPattern {
- public:
- struct Subrange {
- Subrange();
- explicit Subrange(SubstitutionType t, const std::string& l = std::string());
- ~Subrange();
-
- inline bool operator==(const Subrange& other) const {
- return type == other.type && literal == other.literal;
- }
-
- SubstitutionType type;
-
- // When type_ == LITERAL, this specifies the literal.
- std::string literal;
- };
-
- SubstitutionPattern();
- SubstitutionPattern(const SubstitutionPattern& other);
- ~SubstitutionPattern();
-
- // Parses the given string and fills in the pattern. The pattern must only
- // be initialized once. On failure, returns false and sets the error.
- bool Parse(const Value& value, Err* err);
- bool Parse(const std::string& str, const ParseNode* origin, Err* err);
-
- // Makes a pattern given a hardcoded string. Will assert if the string is
- // not a valid pattern.
- static SubstitutionPattern MakeForTest(const char* str);
-
- // Returns the pattern as a string with substitutions in them.
- std::string AsString() const;
-
- // Sets the bits in the given vector corresponding to the substitutions used
- // by this pattern. SUBSTITUTION_LITERAL is ignored.
- void FillRequiredTypes(SubstitutionBits* bits) const;
-
- // Checks whether this pattern resolves to something in the output directory
- // for the given build settings. If not, returns false and fills in the given
- // error.
- bool IsInOutputDir(const BuildSettings* build_settings,
- Err* err) const;
-
- // Returns a vector listing the substitutions used by this pattern, not
- // counting SUBSTITUTION_LITERAL.
- const std::vector<SubstitutionType>& required_types() const {
- return required_types_;
- }
-
- const std::vector<Subrange>& ranges() const { return ranges_; }
- bool empty() const { return ranges_.empty(); }
-
- private:
- std::vector<Subrange> ranges_;
- const ParseNode* origin_;
-
- std::vector<SubstitutionType> required_types_;
-};
-
-#endif // TOOLS_GN_SUBSTITUTION_PATTERN_H_
diff --git a/chromium/tools/gn/substitution_pattern_unittest.cc b/chromium/tools/gn/substitution_pattern_unittest.cc
deleted file mode 100644
index 9f606af0e7b..00000000000
--- a/chromium/tools/gn/substitution_pattern_unittest.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/err.h"
-#include "tools/gn/substitution_pattern.h"
-
-TEST(SubstitutionPattern, ParseLiteral) {
- SubstitutionPattern pattern;
- Err err;
- EXPECT_TRUE(pattern.Parse("This is a literal", nullptr, &err));
- EXPECT_FALSE(err.has_error());
- ASSERT_EQ(1u, pattern.ranges().size());
- EXPECT_EQ(SUBSTITUTION_LITERAL, pattern.ranges()[0].type);
- EXPECT_EQ("This is a literal", pattern.ranges()[0].literal);
-}
-
-TEST(SubstitutionPattern, ParseComplex) {
- SubstitutionPattern pattern;
- Err err;
- EXPECT_TRUE(pattern.Parse(
- "AA{{source}}{{source_name_part}}BB{{source_file_part}}", nullptr, &err));
- EXPECT_FALSE(err.has_error());
- ASSERT_EQ(5u, pattern.ranges().size());
-
- EXPECT_EQ(SUBSTITUTION_LITERAL, pattern.ranges()[0].type);
- EXPECT_EQ("AA", pattern.ranges()[0].literal);
- EXPECT_EQ(SUBSTITUTION_SOURCE, pattern.ranges()[1].type);
- EXPECT_EQ(SUBSTITUTION_SOURCE_NAME_PART, pattern.ranges()[2].type);
- EXPECT_EQ(SUBSTITUTION_LITERAL, pattern.ranges()[3].type);
- EXPECT_EQ("BB", pattern.ranges()[3].literal);
- EXPECT_EQ(SUBSTITUTION_SOURCE_FILE_PART, pattern.ranges()[4].type);
-}
-
-TEST(SubstitutionPattern, ParseErrors) {
- SubstitutionPattern pattern;
- Err err;
- EXPECT_FALSE(pattern.Parse("AA{{source", nullptr, &err));
- EXPECT_TRUE(err.has_error());
-
- err = Err();
- EXPECT_FALSE(pattern.Parse("{{source_of_evil}}", nullptr, &err));
- EXPECT_TRUE(err.has_error());
-
- err = Err();
- EXPECT_FALSE(pattern.Parse("{{source{{source}}", nullptr, &err));
- EXPECT_TRUE(err.has_error());
-}
diff --git a/chromium/tools/gn/substitution_type.cc b/chromium/tools/gn/substitution_type.cc
deleted file mode 100644
index 14bdcdc8dfc..00000000000
--- a/chromium/tools/gn/substitution_type.cc
+++ /dev/null
@@ -1,264 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/substitution_type.h"
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#include "tools/gn/err.h"
-
-const char* kSubstitutionNames[SUBSTITUTION_NUM_TYPES] = {
- "<<literal>>", // SUBSTITUTION_LITERAL
-
- "{{source}}", // SUBSTITUTION_SOURCE
- "{{output}}", // SUBSTITUTION_OUTPUT
-
- "{{source_name_part}}", // SUBSTITUTION_NAME_PART
- "{{source_file_part}}", // SUBSTITUTION_FILE_PART
- "{{source_dir}}", // SUBSTITUTION_SOURCE_DIR
- "{{source_root_relative_dir}}", // SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR
- "{{source_gen_dir}}", // SUBSTITUTION_SOURCE_GEN_DIR
- "{{source_out_dir}}", // SUBSTITUTION_SOURCE_OUT_DIR
- "{{source_target_relative}}", // SUBSTITUTION_SOURCE_TARGET_RELATIVE
-
- "{{label}}", // SUBSTITUTION_LABEL
- "{{label_name}}", // SUBSTITUTION_LABEL_NAME
- "{{root_gen_dir}}", // SUBSTITUTION_ROOT_GEN_DIR
- "{{root_out_dir}}", // SUBSTITUTION_ROOT_OUT_DIR
- "{{target_gen_dir}}", // SUBSTITUTION_TARGET_GEN_DIR
- "{{target_out_dir}}", // SUBSTITUTION_TARGET_OUT_DIR
- "{{target_output_name}}", // SUBSTITUTION_TARGET_OUTPUT_NAME
-
- "{{asmflags}}", // SUBSTITUTION_ASMFLAGS
- "{{cflags}}", // SUBSTITUTION_CFLAGS
- "{{cflags_c}}", // SUBSTITUTION_CFLAGS_C
- "{{cflags_cc}}", // SUBSTITUTION_CFLAGS_CC
- "{{cflags_objc}}", // SUBSTITUTION_CFLAGS_OBJC
- "{{cflags_objcc}}", // SUBSTITUTION_CFLAGS_OBJCC
- "{{defines}}", // SUBSTITUTION_DEFINES
- "{{include_dirs}}", // SUBSTITUTION_INCLUDE_DIRS
-
- "{{inputs}}", // SUBSTITUTION_LINKER_INPUTS
- "{{inputs_newline}}", // SUBSTITUTION_LINKER_INPUTS_NEWLINE
- "{{ldflags}}", // SUBSTITUTION_LDFLAGS
- "{{libs}}", // SUBSTITUTION_LIBS
- "{{output_dir}}", // SUBSTITUTION_OUTPUT_DIR
- "{{output_extension}}", // SUBSTITUTION_OUTPUT_EXTENSION
- "{{solibs}}", // SUBSTITUTION_SOLIBS
-
- "{{arflags}}", // SUBSTITUTION_ARFLAGS
-
- "{{bundle_root_dir}}", // SUBSTITUTION_BUNDLE_ROOT_DIR
- "{{bundle_contents_dir}}", // SUBSTITUTION_BUNDLE_CONTENTS_DIR
- "{{bundle_resources_dir}}", // SUBSTITUTION_BUNDLE_RESOURCES_DIR
- "{{bundle_executable_dir}}", // SUBSTITUTION_BUNDLE_EXECUTABLE_DIR
- "{{bundle_plugins_dir}}", // SUBSTITUTION_BUNDLE_PLUGINS_DIR
- "{{bundle_product_type}}", // SUBSTITUTION_BUNDLE_PRODUCT_TYPE
- "{{bundle_partial_info_plist}}", // SUBSTITUTION_BUNDLE_PARTIAL_INFO_PLIST,
-
- "{{response_file_name}}", // SUBSTITUTION_RSP_FILE_NAME
-};
-
-const char* kSubstitutionNinjaNames[SUBSTITUTION_NUM_TYPES] = {
- nullptr, // SUBSTITUTION_LITERAL
-
- "in", // SUBSTITUTION_SOURCE
- "out", // SUBSTITUTION_OUTPUT
-
- "source_name_part", // SUBSTITUTION_NAME_PART
- "source_file_part", // SUBSTITUTION_FILE_PART
- "source_dir", // SUBSTITUTION_SOURCE_DIR
- "source_root_relative_dir", // SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR
- "source_gen_dir", // SUBSTITUTION_SOURCE_GEN_DIR
- "source_out_dir", // SUBSTITUTION_SOURCE_OUT_DIR
- "source_target_relative", // SUBSTITUTION_SOURCE_TARGET_RELATIVE
-
- "label", // SUBSTITUTION_LABEL
- "label_name", // SUBSTITUTION_LABEL_NAME
- "root_gen_dir", // SUBSTITUTION_ROOT_GEN_DIR
- "root_out_dir", // SUBSTITUTION_ROOT_OUT_DIR
- "target_gen_dir", // SUBSTITUTION_TARGET_GEN_DIR
- "target_out_dir", // SUBSTITUTION_TARGET_OUT_DIR
- "target_output_name", // SUBSTITUTION_TARGET_OUTPUT_NAME
-
- "asmflags", // SUBSTITUTION_ASMFLAGS
- "cflags", // SUBSTITUTION_CFLAGS
- "cflags_c", // SUBSTITUTION_CFLAGS_C
- "cflags_cc", // SUBSTITUTION_CFLAGS_CC
- "cflags_objc", // SUBSTITUTION_CFLAGS_OBJC
- "cflags_objcc", // SUBSTITUTION_CFLAGS_OBJCC
- "defines", // SUBSTITUTION_DEFINES
- "include_dirs", // SUBSTITUTION_INCLUDE_DIRS
-
- // LINKER_INPUTS expands to the same Ninja var as SUBSTITUTION_SOURCE. These
- // are used in different contexts and are named differently to keep things
- // clear, but they both expand to the "set of input files" for a build rule.
- "in", // SUBSTITUTION_LINKER_INPUTS
- "in_newline", // SUBSTITUTION_LINKER_INPUTS_NEWLINE
- "ldflags", // SUBSTITUTION_LDFLAGS
- "libs", // SUBSTITUTION_LIBS
- "output_dir", // SUBSTITUTION_OUTPUT_DIR
- "output_extension", // SUBSTITUTION_OUTPUT_EXTENSION
- "solibs", // SUBSTITUTION_SOLIBS
-
- "arflags", // SUBSTITUTION_ARFLAGS
-
- "bundle_root_dir", // SUBSTITUTION_BUNDLE_ROOT_DIR
- "bundle_contents_dir", // SUBSTITUTION_BUNDLE_CONTENTS_DIR
- "bundle_resources_dir", // SUBSTITUTION_BUNDLE_RESOURCES_DIR
- "bundle_executable_dir", // SUBSTITUTION_BUNDLE_EXECUTABLE_DIR
- "bundle_plugins_dir", // SUBSTITUTION_BUNDLE_PLUGINS_DIR
- "product_type", // SUBSTITUTION_BUNDLE_PRODUCT_TYPE
- "partial_info_plist", // SUBSTITUTION_BUNDLE_PARTIAL_INFO_PLIST
-
- "rspfile", // SUBSTITUTION_RSP_FILE_NAME
-};
-
-SubstitutionBits::SubstitutionBits() : used() {
-}
-
-void SubstitutionBits::MergeFrom(const SubstitutionBits& other) {
- for (size_t i = 0; i < SUBSTITUTION_NUM_TYPES; i++)
- used[i] |= other.used[i];
-}
-
-void SubstitutionBits::FillVector(std::vector<SubstitutionType>* vect) const {
- for (size_t i = SUBSTITUTION_FIRST_PATTERN; i < SUBSTITUTION_NUM_TYPES; i++) {
- if (used[i])
- vect->push_back(static_cast<SubstitutionType>(i));
- }
-}
-
-bool SubstitutionIsInOutputDir(SubstitutionType type) {
- return type == SUBSTITUTION_SOURCE_GEN_DIR ||
- type == SUBSTITUTION_SOURCE_OUT_DIR ||
- type == SUBSTITUTION_ROOT_GEN_DIR ||
- type == SUBSTITUTION_ROOT_OUT_DIR ||
- type == SUBSTITUTION_TARGET_GEN_DIR ||
- type == SUBSTITUTION_TARGET_OUT_DIR;
-}
-
-bool SubstitutionIsInBundleDir(SubstitutionType type) {
- return type == SUBSTITUTION_BUNDLE_ROOT_DIR ||
- type == SUBSTITUTION_BUNDLE_CONTENTS_DIR ||
- type == SUBSTITUTION_BUNDLE_RESOURCES_DIR ||
- type == SUBSTITUTION_BUNDLE_EXECUTABLE_DIR ||
- type == SUBSTITUTION_BUNDLE_PLUGINS_DIR;
-}
-
-bool IsValidBundleDataSubstitution(SubstitutionType type) {
- return type == SUBSTITUTION_LITERAL ||
- type == SUBSTITUTION_SOURCE_NAME_PART ||
- type == SUBSTITUTION_SOURCE_FILE_PART ||
- type == SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR ||
- type == SUBSTITUTION_BUNDLE_ROOT_DIR ||
- type == SUBSTITUTION_BUNDLE_CONTENTS_DIR ||
- type == SUBSTITUTION_BUNDLE_RESOURCES_DIR ||
- type == SUBSTITUTION_BUNDLE_EXECUTABLE_DIR ||
- type == SUBSTITUTION_BUNDLE_PLUGINS_DIR;
-}
-
-bool IsValidSourceSubstitution(SubstitutionType type) {
- return type == SUBSTITUTION_LITERAL ||
- type == SUBSTITUTION_SOURCE ||
- type == SUBSTITUTION_SOURCE_NAME_PART ||
- type == SUBSTITUTION_SOURCE_FILE_PART ||
- type == SUBSTITUTION_SOURCE_DIR ||
- type == SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR ||
- type == SUBSTITUTION_SOURCE_GEN_DIR ||
- type == SUBSTITUTION_SOURCE_OUT_DIR ||
- type == SUBSTITUTION_SOURCE_TARGET_RELATIVE;
-}
-
-bool IsValidScriptArgsSubstitution(SubstitutionType type) {
- return IsValidSourceSubstitution(type) ||
- type == SUBSTITUTION_RSP_FILE_NAME;
-}
-
-bool IsValidToolSubstitution(SubstitutionType type) {
- return type == SUBSTITUTION_LITERAL ||
- type == SUBSTITUTION_OUTPUT ||
- type == SUBSTITUTION_LABEL ||
- type == SUBSTITUTION_LABEL_NAME ||
- type == SUBSTITUTION_ROOT_GEN_DIR ||
- type == SUBSTITUTION_ROOT_OUT_DIR ||
- type == SUBSTITUTION_TARGET_GEN_DIR ||
- type == SUBSTITUTION_TARGET_OUT_DIR ||
- type == SUBSTITUTION_TARGET_OUTPUT_NAME;
-}
-
-bool IsValidCompilerSubstitution(SubstitutionType type) {
- return IsValidToolSubstitution(type) ||
- IsValidSourceSubstitution(type) ||
- type == SUBSTITUTION_SOURCE ||
- type == SUBSTITUTION_ASMFLAGS ||
- type == SUBSTITUTION_CFLAGS ||
- type == SUBSTITUTION_CFLAGS_C ||
- type == SUBSTITUTION_CFLAGS_CC ||
- type == SUBSTITUTION_CFLAGS_OBJC ||
- type == SUBSTITUTION_CFLAGS_OBJCC ||
- type == SUBSTITUTION_DEFINES ||
- type == SUBSTITUTION_INCLUDE_DIRS;
-}
-
-bool IsValidCompilerOutputsSubstitution(SubstitutionType type) {
- // All tool types except "output" (which would be infinitely recursive).
- return (IsValidToolSubstitution(type) && type != SUBSTITUTION_OUTPUT) ||
- IsValidSourceSubstitution(type);
-}
-
-bool IsValidLinkerSubstitution(SubstitutionType type) {
- return IsValidToolSubstitution(type) ||
- type == SUBSTITUTION_LINKER_INPUTS ||
- type == SUBSTITUTION_LINKER_INPUTS_NEWLINE ||
- type == SUBSTITUTION_LDFLAGS ||
- type == SUBSTITUTION_LIBS ||
- type == SUBSTITUTION_OUTPUT_DIR ||
- type == SUBSTITUTION_OUTPUT_EXTENSION ||
- type == SUBSTITUTION_SOLIBS;
-}
-
-bool IsValidLinkerOutputsSubstitution(SubstitutionType type) {
- // All valid compiler outputs plus the output extension.
- return IsValidCompilerOutputsSubstitution(type) ||
- type == SUBSTITUTION_OUTPUT_DIR ||
- type == SUBSTITUTION_OUTPUT_EXTENSION;
-}
-
-bool IsValidALinkSubstitution(SubstitutionType type) {
- return IsValidToolSubstitution(type) ||
- type == SUBSTITUTION_LINKER_INPUTS ||
- type == SUBSTITUTION_LINKER_INPUTS_NEWLINE ||
- type == SUBSTITUTION_ARFLAGS ||
- type == SUBSTITUTION_OUTPUT_DIR ||
- type == SUBSTITUTION_OUTPUT_EXTENSION;
-}
-
-bool IsValidCopySubstitution(SubstitutionType type) {
- return IsValidToolSubstitution(type) ||
- type == SUBSTITUTION_SOURCE;
-}
-
-bool IsValidCompileXCassetsSubstitution(SubstitutionType type) {
- return IsValidToolSubstitution(type) || type == SUBSTITUTION_LINKER_INPUTS ||
- type == SUBSTITUTION_BUNDLE_PRODUCT_TYPE ||
- type == SUBSTITUTION_BUNDLE_PARTIAL_INFO_PLIST;
-}
-
-bool EnsureValidSubstitutions(const std::vector<SubstitutionType>& types,
- bool (*is_valid_subst)(SubstitutionType),
- const ParseNode* origin,
- Err* err) {
- for (SubstitutionType type : types) {
- if (!is_valid_subst(type)) {
- *err = Err(origin, "Invalid substitution type.",
- "The substitution " + std::string(kSubstitutionNames[type]) +
- " isn't valid for something\n"
- "operating on a source file such as this.");
- return false;
- }
- }
- return true;
-}
diff --git a/chromium/tools/gn/substitution_type.h b/chromium/tools/gn/substitution_type.h
deleted file mode 100644
index bb3c803d4fa..00000000000
--- a/chromium/tools/gn/substitution_type.h
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_SUBSTITUTION_TYPE_H_
-#define TOOLS_GN_SUBSTITUTION_TYPE_H_
-
-#include <vector>
-
-class Err;
-class ParseNode;
-
-// Keep kSubstitutionNames, kSubstitutionNinjaNames and the
-// IsValid*Substitution functions in sync if you change anything here.
-enum SubstitutionType {
- SUBSTITUTION_LITERAL = 0,
-
- // The index of the first pattern. To loop overal all patterns, go from here
- // until NUM_TYPES.
- SUBSTITUTION_FIRST_PATTERN,
-
- // These map to Ninja's {in} and {out} variables.
- SUBSTITUTION_SOURCE = SUBSTITUTION_FIRST_PATTERN, // {{source}}
- SUBSTITUTION_OUTPUT, // {{output}}
-
- // Valid for all compiler tools.
- SUBSTITUTION_SOURCE_NAME_PART, // {{source_name_part}}
- SUBSTITUTION_SOURCE_FILE_PART, // {{source_file_part}}
- SUBSTITUTION_SOURCE_DIR, // {{source_dir}}
- SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR, // {{root_relative_dir}}
- SUBSTITUTION_SOURCE_GEN_DIR, // {{source_gen_dir}}
- SUBSTITUTION_SOURCE_OUT_DIR, // {{source_out_dir}}
- SUBSTITUTION_SOURCE_TARGET_RELATIVE, // {{source_target_relative}}
-
- // Valid for all compiler and linker tools. These depend on the target and
- // do not vary on a per-file basis.
- SUBSTITUTION_LABEL, // {{label}}
- SUBSTITUTION_LABEL_NAME, // {{label_name}}
- SUBSTITUTION_ROOT_GEN_DIR, // {{root_gen_dir}}
- SUBSTITUTION_ROOT_OUT_DIR, // {{root_out_dir}}
- SUBSTITUTION_TARGET_GEN_DIR, // {{target_gen_dir}}
- SUBSTITUTION_TARGET_OUT_DIR, // {{target_out_dir}}
- SUBSTITUTION_TARGET_OUTPUT_NAME, // {{target_output_name}}
-
- // Valid for compiler tools.
- SUBSTITUTION_ASMFLAGS, // {{asmflags}}
- SUBSTITUTION_CFLAGS, // {{cflags}}
- SUBSTITUTION_CFLAGS_C, // {{cflags_c}}
- SUBSTITUTION_CFLAGS_CC, // {{cflags_cc}}
- SUBSTITUTION_CFLAGS_OBJC, // {{cflags_objc}}
- SUBSTITUTION_CFLAGS_OBJCC, // {{cflags_objcc}}
- SUBSTITUTION_DEFINES, // {{defines}}
- SUBSTITUTION_INCLUDE_DIRS, // {{include_dirs}}
-
- // Valid for linker tools.
- SUBSTITUTION_LINKER_INPUTS, // {{inputs}}
- SUBSTITUTION_LINKER_INPUTS_NEWLINE, // {{inputs_newline}}
- SUBSTITUTION_LDFLAGS, // {{ldflags}}
- SUBSTITUTION_LIBS, // {{libs}}
- SUBSTITUTION_OUTPUT_DIR, // {{output_dir}}
- SUBSTITUTION_OUTPUT_EXTENSION, // {{output_extension}}
- SUBSTITUTION_SOLIBS, // {{solibs}}
-
- // Valid for alink only.
- SUBSTITUTION_ARFLAGS, // {{arflags}}
-
- // Valid for bundle_data targets.
- SUBSTITUTION_BUNDLE_ROOT_DIR, // {{bundle_root_dir}}
- SUBSTITUTION_BUNDLE_CONTENTS_DIR, // {{bundle_contents_dir}}
- SUBSTITUTION_BUNDLE_RESOURCES_DIR, // {{bundle_resources_dir}}
- SUBSTITUTION_BUNDLE_EXECUTABLE_DIR, // {{bundle_executable_dir}}
- SUBSTITUTION_BUNDLE_PLUGINS_DIR, // {{bundle_plugins_dir}}
-
- // Valid for compile_xcassets tool.
- SUBSTITUTION_BUNDLE_PRODUCT_TYPE, // {{bundle_product_type}}
- SUBSTITUTION_BUNDLE_PARTIAL_INFO_PLIST, // {{bundle_partial_info_plist}}
-
- // Used only for the args of actions.
- SUBSTITUTION_RSP_FILE_NAME, // {{response_file_name}}
-
- SUBSTITUTION_NUM_TYPES // Must be last.
-};
-
-// An array of size SUBSTITUTION_NUM_TYPES that lists the names of the
-// substitution patterns, including the curly braces. So, for example,
-// kSubstitutionNames[SUBSTITUTION_SOURCE] == "{{source}}".
-extern const char* kSubstitutionNames[SUBSTITUTION_NUM_TYPES];
-
-// Ninja variables corresponding to each substitution. These do not include
-// the dollar sign.
-extern const char* kSubstitutionNinjaNames[SUBSTITUTION_NUM_TYPES];
-
-// A wrapper around an array if flags indicating whether a given substitution
-// type is required in some context. By convention, the LITERAL type bit is
-// not set.
-struct SubstitutionBits {
- SubstitutionBits();
-
- // Merges any bits set in the given "other" to this one. This object will
- // then be the union of all bits in the two lists.
- void MergeFrom(const SubstitutionBits& other);
-
- // Converts the substitution type bitfield (with a true set for each required
- // item) to a vector of the types listed. Does not include LITERAL.
- void FillVector(std::vector<SubstitutionType>* vect) const;
-
- bool used[SUBSTITUTION_NUM_TYPES];
-};
-
-// Returns true if the given substitution pattern references the output
-// directory. This is used to check strings that begin with a substitution to
-// verify that they produce a file in the output directory.
-bool SubstitutionIsInOutputDir(SubstitutionType type);
-
-// Returns true if the given substitution pattern references the bundle
-// directory. This is used to check strings that begin with a substitution to
-// verify that they produce a file in the bundle directory.
-bool SubstitutionIsInBundleDir(SubstitutionType type);
-
-// Returns true if the given substitution is valid for the named purpose.
-bool IsValidBundleDataSubstitution(SubstitutionType type);
-bool IsValidSourceSubstitution(SubstitutionType type);
-bool IsValidScriptArgsSubstitution(SubstitutionType type);
-
-// Both compiler and linker tools.
-bool IsValidToolSubstitution(SubstitutionType type);
-bool IsValidCompilerSubstitution(SubstitutionType type);
-bool IsValidCompilerOutputsSubstitution(SubstitutionType type);
-bool IsValidLinkerSubstitution(SubstitutionType type);
-bool IsValidLinkerOutputsSubstitution(SubstitutionType type);
-bool IsValidALinkSubstitution(SubstitutionType type);
-bool IsValidCopySubstitution(SubstitutionType type);
-bool IsValidCompileXCassetsSubstitution(SubstitutionType type);
-
-// Validates that each substitution type in the vector passes the given
-// is_valid_subst predicate. Returns true on success. On failure, fills in the
-// error object with an appropriate message and returns false.
-bool EnsureValidSubstitutions(
- const std::vector<SubstitutionType>& types,
- bool (*is_valid_subst)(SubstitutionType),
- const ParseNode* origin,
- Err* err);
-
-#endif // TOOLS_GN_SUBSTITUTION_TYPE_H_
diff --git a/chromium/tools/gn/substitution_writer.cc b/chromium/tools/gn/substitution_writer.cc
deleted file mode 100644
index 19a4436e25d..00000000000
--- a/chromium/tools/gn/substitution_writer.cc
+++ /dev/null
@@ -1,608 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/substitution_writer.h"
-
-#include "tools/gn/build_settings.h"
-#include "tools/gn/escape.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/output_file.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/string_utils.h"
-#include "tools/gn/substitution_list.h"
-#include "tools/gn/substitution_pattern.h"
-#include "tools/gn/target.h"
-
-namespace {
-
-// Sets the given directory string to the destination, trimming any trailing
-// slash from the directory (SourceDirs and OutputFiles representing
-// directories will end in a trailing slash). If the directory is empty,
-// it will be replaced with a ".".
-void SetDirOrDotWithNoSlash(const std::string& dir, std::string* dest) {
- if (!dir.empty() && dir[dir.size() - 1] == '/')
- dest->assign(dir.data(), dir.size() - 1);
- else
- dest->assign(dir);
-
- if (dest->empty())
- dest->push_back('.');
-}
-
-} // namespace
-
-const char kSourceExpansion_Help[] =
- R"(How Source Expansion Works
-
- Source expansion is used for the action_foreach and copy target types to map
- source file names to output file names or arguments.
-
- To perform source expansion in the outputs, GN maps every entry in the
- sources to every entry in the outputs list, producing the cross product of
- all combinations, expanding placeholders (see below).
-
- Source expansion in the args works similarly, but performing the placeholder
- substitution produces a different set of arguments for each invocation of the
- script.
-
- If no placeholders are found, the outputs or args list will be treated as a
- static list of literal file names that do not depend on the sources.
-
- See "gn help copy" and "gn help action_foreach" for more on how this is
- applied.
-
-Placeholders
-
- This section discusses only placeholders for actions. There are other
- placeholders used in the definition of tools. See "gn help tool" for those.
-
- {{source}}
- The name of the source file including directory (*). This will generally
- be used for specifying inputs to a script in the "args" variable.
- "//foo/bar/baz.txt" => "../../foo/bar/baz.txt"
-
- {{source_file_part}}
- The file part of the source including the extension.
- "//foo/bar/baz.txt" => "baz.txt"
-
- {{source_name_part}}
- The filename part of the source file with no directory or extension. This
- will generally be used for specifying a transformation from a source file
- to a destination file with the same name but different extension.
- "//foo/bar/baz.txt" => "baz"
-
- {{source_dir}}
- The directory (*) containing the source file with no trailing slash.
- "//foo/bar/baz.txt" => "../../foo/bar"
-
- {{source_root_relative_dir}}
- The path to the source file's directory relative to the source root, with
- no leading "//" or trailing slashes. If the path is system-absolute,
- (beginning in a single slash) this will just return the path with no
- trailing slash. This value will always be the same, regardless of whether
- it appears in the "outputs" or "args" section.
- "//foo/bar/baz.txt" => "foo/bar"
-
- {{source_gen_dir}}
- The generated file directory (*) corresponding to the source file's path.
- This will be different than the target's generated file directory if the
- source file is in a different directory than the BUILD.gn file.
- "//foo/bar/baz.txt" => "gen/foo/bar"
-
- {{source_out_dir}}
- The object file directory (*) corresponding to the source file's path,
- relative to the build directory. this us be different than the target's
- out directory if the source file is in a different directory than the
- build.gn file.
- "//foo/bar/baz.txt" => "obj/foo/bar"
-
- {{source_target_relative}}
- The path to the source file relative to the target's directory. This will
- generally be used for replicating the source directory layout in the
- output directory. This can only be used in actions and it is an error to
- use in process_file_template where there is no "target".
- "//foo/bar/baz.txt" => "baz.txt"
-
-(*) Note on directories
-
- Paths containing directories (except the source_root_relative_dir) will be
- different depending on what context the expansion is evaluated in. Generally
- it should "just work" but it means you can't concatenate strings containing
- these values with reasonable results.
-
- Details: source expansions can be used in the "outputs" variable, the "args"
- variable, and in calls to "process_file_template". The "args" are passed to a
- script which is run from the build directory, so these directories will
- relative to the build directory for the script to find. In the other cases,
- the directories will be source- absolute (begin with a "//") because the
- results of those expansions will be handled by GN internally.
-
-Examples
-
- Non-varying outputs:
- action("hardcoded_outputs") {
- sources = [ "input1.idl", "input2.idl" ]
- outputs = [ "$target_out_dir/output1.dat",
- "$target_out_dir/output2.dat" ]
- }
- The outputs in this case will be the two literal files given.
-
- Varying outputs:
- action_foreach("varying_outputs") {
- sources = [ "input1.idl", "input2.idl" ]
- outputs = [ "{{source_gen_dir}}/{{source_name_part}}.h",
- "{{source_gen_dir}}/{{source_name_part}}.cc" ]
- }
- Performing source expansion will result in the following output names:
- //out/Debug/obj/mydirectory/input1.h
- //out/Debug/obj/mydirectory/input1.cc
- //out/Debug/obj/mydirectory/input2.h
- //out/Debug/obj/mydirectory/input2.cc
-)";
-
-// static
-void SubstitutionWriter::WriteWithNinjaVariables(
- const SubstitutionPattern& pattern,
- const EscapeOptions& escape_options,
- std::ostream& out) {
- // The result needs to be quoted as if it was one string, but the $ for
- // the inserted Ninja variables can't be escaped. So write to a buffer with
- // no quoting, and then quote the whole thing if necessary.
- EscapeOptions no_quoting(escape_options);
- no_quoting.inhibit_quoting = true;
-
- bool needs_quotes = false;
- std::string result;
- for (const auto& range : pattern.ranges()) {
- if (range.type == SUBSTITUTION_LITERAL) {
- result.append(EscapeString(range.literal, no_quoting, &needs_quotes));
- } else {
- result.append("${");
- result.append(kSubstitutionNinjaNames[range.type]);
- result.append("}");
- }
- }
-
- if (needs_quotes && !escape_options.inhibit_quoting)
- out << "\"" << result << "\"";
- else
- out << result;
-}
-
-// static
-void SubstitutionWriter::GetListAsSourceFiles(
- const SubstitutionList& list,
- std::vector<SourceFile>* output) {
- for (const auto& pattern : list.list()) {
- CHECK(pattern.ranges().size() == 1 &&
- pattern.ranges()[0].type == SUBSTITUTION_LITERAL)
- << "The substitution pattern \""
- << pattern.AsString()
- << "\" was expected to be a literal with no {{substitutions}}.";
- const std::string& literal = pattern.ranges()[0].literal;
- CHECK(literal.size() >= 1 && literal[0] == '/')
- << "The result of the pattern \""
- << pattern.AsString()
- << "\" was not an absolute path.";
- output->push_back(SourceFile(literal));
- }
-}
-
-// static
-void SubstitutionWriter::GetListAsOutputFiles(
- const Settings* settings,
- const SubstitutionList& list,
- std::vector<OutputFile>* output) {
- std::vector<SourceFile> output_as_sources;
- GetListAsSourceFiles(list, &output_as_sources);
- for (const auto& file : output_as_sources)
- output->push_back(OutputFile(settings->build_settings(), file));
-}
-
-// static
-SourceFile SubstitutionWriter::ApplyPatternToSource(
- const Target* target,
- const Settings* settings,
- const SubstitutionPattern& pattern,
- const SourceFile& source) {
- std::string result_value = ApplyPatternToSourceAsString(
- target, settings, pattern, source);
- CHECK(!result_value.empty() && result_value[0] == '/')
- << "The result of the pattern \""
- << pattern.AsString()
- << "\" was not a path beginning in \"/\" or \"//\".";
- return SourceFile(SourceFile::SWAP_IN, &result_value);
-}
-
-// static
-std::string SubstitutionWriter::ApplyPatternToSourceAsString(
- const Target* target,
- const Settings* settings,
- const SubstitutionPattern& pattern,
- const SourceFile& source) {
- std::string result_value;
- for (const auto& subrange : pattern.ranges()) {
- if (subrange.type == SUBSTITUTION_LITERAL) {
- result_value.append(subrange.literal);
- } else {
- result_value.append(
- GetSourceSubstitution(target, settings, source, subrange.type,
- OUTPUT_ABSOLUTE, SourceDir()));
- }
- }
- return result_value;
-}
-
-// static
-OutputFile SubstitutionWriter::ApplyPatternToSourceAsOutputFile(
- const Target* target,
- const Settings* settings,
- const SubstitutionPattern& pattern,
- const SourceFile& source) {
- SourceFile result_as_source = ApplyPatternToSource(
- target, settings, pattern, source);
- return OutputFile(settings->build_settings(), result_as_source);
-}
-
-// static
-void SubstitutionWriter::ApplyListToSource(
- const Target* target,
- const Settings* settings,
- const SubstitutionList& list,
- const SourceFile& source,
- std::vector<SourceFile>* output) {
- for (const auto& item : list.list())
- output->push_back(ApplyPatternToSource(target, settings, item, source));
-}
-
-// static
-void SubstitutionWriter::ApplyListToSourceAsString(
- const Target* target,
- const Settings* settings,
- const SubstitutionList& list,
- const SourceFile& source,
- std::vector<std::string>* output) {
- for (const auto& item : list.list())
- output->push_back(ApplyPatternToSourceAsString(
- target, settings, item, source));
-}
-
-// static
-void SubstitutionWriter::ApplyListToSourceAsOutputFile(
- const Target* target,
- const Settings* settings,
- const SubstitutionList& list,
- const SourceFile& source,
- std::vector<OutputFile>* output) {
- for (const auto& item : list.list())
- output->push_back(ApplyPatternToSourceAsOutputFile(
- target, settings, item, source));
-}
-
-// static
-void SubstitutionWriter::ApplyListToSources(
- const Target* target,
- const Settings* settings,
- const SubstitutionList& list,
- const std::vector<SourceFile>& sources,
- std::vector<SourceFile>* output) {
- output->clear();
- for (const auto& source : sources)
- ApplyListToSource(target, settings, list, source, output);
-}
-
-// static
-void SubstitutionWriter::ApplyListToSourcesAsString(
- const Target* target,
- const Settings* settings,
- const SubstitutionList& list,
- const std::vector<SourceFile>& sources,
- std::vector<std::string>* output) {
- output->clear();
- for (const auto& source : sources)
- ApplyListToSourceAsString(target, settings, list, source, output);
-}
-
-// static
-void SubstitutionWriter::ApplyListToSourcesAsOutputFile(
- const Target* target,
- const Settings* settings,
- const SubstitutionList& list,
- const std::vector<SourceFile>& sources,
- std::vector<OutputFile>* output) {
- output->clear();
- for (const auto& source : sources)
- ApplyListToSourceAsOutputFile(target, settings, list, source, output);
-}
-
-// static
-void SubstitutionWriter::WriteNinjaVariablesForSource(
- const Target* target,
- const Settings* settings,
- const SourceFile& source,
- const std::vector<SubstitutionType>& types,
- const EscapeOptions& escape_options,
- std::ostream& out) {
- for (const auto& type : types) {
- // Don't write SOURCE since that just maps to Ninja's $in variable, which
- // is implicit in the rule. RESPONSE_FILE_NAME is written separately
- // only when writing target rules since it can never be used in any
- // other context (like process_file_template).
- if (type != SUBSTITUTION_SOURCE && type != SUBSTITUTION_RSP_FILE_NAME) {
- out << " " << kSubstitutionNinjaNames[type] << " = ";
- EscapeStringToStream(
- out,
- GetSourceSubstitution(target, settings, source, type,
- OUTPUT_RELATIVE,
- settings->build_settings()->build_dir()),
- escape_options);
- out << std::endl;
- }
- }
-}
-
-// static
-std::string SubstitutionWriter::GetSourceSubstitution(
- const Target* target,
- const Settings* settings,
- const SourceFile& source,
- SubstitutionType type,
- OutputStyle output_style,
- const SourceDir& relative_to) {
- std::string to_rebase;
- switch (type) {
- case SUBSTITUTION_SOURCE:
- if (source.is_system_absolute())
- return source.value();
- to_rebase = source.value();
- break;
-
- case SUBSTITUTION_SOURCE_NAME_PART:
- return FindFilenameNoExtension(&source.value()).as_string();
-
- case SUBSTITUTION_SOURCE_FILE_PART:
- return source.GetName();
-
- case SUBSTITUTION_SOURCE_DIR:
- if (source.is_system_absolute())
- return DirectoryWithNoLastSlash(source.GetDir());
- to_rebase = DirectoryWithNoLastSlash(source.GetDir());
- break;
-
- case SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR:
- if (source.is_system_absolute())
- return DirectoryWithNoLastSlash(source.GetDir());
- return RebasePath(
- DirectoryWithNoLastSlash(source.GetDir()), SourceDir("//"),
- settings->build_settings()->root_path_utf8());
-
- case SUBSTITUTION_SOURCE_GEN_DIR:
- to_rebase = DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir(
- BuildDirContext(settings), source.GetDir(), BuildDirType::GEN));
- break;
-
- case SUBSTITUTION_SOURCE_OUT_DIR:
- to_rebase = DirectoryWithNoLastSlash(GetSubBuildDirAsSourceDir(
- BuildDirContext(settings), source.GetDir(), BuildDirType::OBJ));
- break;
-
- case SUBSTITUTION_SOURCE_TARGET_RELATIVE:
- if (target) {
- return RebasePath(source.value(), target->label().dir(),
- settings->build_settings()->root_path_utf8());
- }
- NOTREACHED()
- << "Cannot use substitution " << kSubstitutionNames[type]
- << " without target";
- return std::string();
-
- default:
- NOTREACHED()
- << "Unsupported substitution for this function: "
- << kSubstitutionNames[type];
- return std::string();
- }
-
- // If we get here, the result is a path that should be made relative or
- // absolute according to the output_style. Other cases (just file name or
- // extension extraction) will have been handled via early return above.
- if (output_style == OUTPUT_ABSOLUTE)
- return to_rebase;
- return RebasePath(to_rebase, relative_to,
- settings->build_settings()->root_path_utf8());
-}
-
-// static
-OutputFile SubstitutionWriter::ApplyPatternToTargetAsOutputFile(
- const Target* target,
- const Tool* tool,
- const SubstitutionPattern& pattern) {
- std::string result_value;
- for (const auto& subrange : pattern.ranges()) {
- if (subrange.type == SUBSTITUTION_LITERAL) {
- result_value.append(subrange.literal);
- } else {
- std::string subst;
- CHECK(GetTargetSubstitution(target, subrange.type, &subst));
- result_value.append(subst);
- }
- }
- return OutputFile(result_value);
-}
-
-// static
-void SubstitutionWriter::ApplyListToTargetAsOutputFile(
- const Target* target,
- const Tool* tool,
- const SubstitutionList& list,
- std::vector<OutputFile>* output) {
- for (const auto& item : list.list())
- output->push_back(ApplyPatternToTargetAsOutputFile(target, tool, item));
-}
-
-// static
-bool SubstitutionWriter::GetTargetSubstitution(
- const Target* target,
- SubstitutionType type,
- std::string* result) {
- switch (type) {
- case SUBSTITUTION_LABEL:
- // Only include the toolchain for non-default toolchains.
- *result = target->label().GetUserVisibleName(
- !target->settings()->is_default());
- break;
- case SUBSTITUTION_LABEL_NAME:
- *result = target->label().name();
- break;
- case SUBSTITUTION_ROOT_GEN_DIR:
- SetDirOrDotWithNoSlash(
- GetBuildDirAsOutputFile(BuildDirContext(target),
- BuildDirType::GEN).value(),
- result);
- break;
- case SUBSTITUTION_ROOT_OUT_DIR:
- SetDirOrDotWithNoSlash(
- target->settings()->toolchain_output_subdir().value(),
- result);
- break;
- case SUBSTITUTION_TARGET_GEN_DIR:
- SetDirOrDotWithNoSlash(
- GetBuildDirForTargetAsOutputFile(target, BuildDirType::GEN).value(),
- result);
- break;
- case SUBSTITUTION_TARGET_OUT_DIR:
- SetDirOrDotWithNoSlash(
- GetBuildDirForTargetAsOutputFile(target, BuildDirType::OBJ).value(),
- result);
- break;
- case SUBSTITUTION_TARGET_OUTPUT_NAME:
- *result = target->GetComputedOutputName();
- break;
- default:
- return false;
- }
- return true;
-}
-
-// static
-std::string SubstitutionWriter::GetTargetSubstitution(
- const Target* target,
- SubstitutionType type) {
- std::string result;
- GetTargetSubstitution(target, type, &result);
- return result;
-}
-
-// static
-OutputFile SubstitutionWriter::ApplyPatternToCompilerAsOutputFile(
- const Target* target,
- const SourceFile& source,
- const SubstitutionPattern& pattern) {
- OutputFile result;
- for (const auto& subrange : pattern.ranges()) {
- if (subrange.type == SUBSTITUTION_LITERAL) {
- result.value().append(subrange.literal);
- } else {
- result.value().append(
- GetCompilerSubstitution(target, source, subrange.type));
- }
- }
- return result;
-}
-
-// static
-void SubstitutionWriter::ApplyListToCompilerAsOutputFile(
- const Target* target,
- const SourceFile& source,
- const SubstitutionList& list,
- std::vector<OutputFile>* output) {
- for (const auto& item : list.list())
- output->push_back(ApplyPatternToCompilerAsOutputFile(target, source, item));
-}
-
-// static
-std::string SubstitutionWriter::GetCompilerSubstitution(
- const Target* target,
- const SourceFile& source,
- SubstitutionType type) {
- // First try the common tool ones.
- std::string result;
- if (GetTargetSubstitution(target, type, &result))
- return result;
-
- // Fall-through to the source ones.
- return GetSourceSubstitution(
- target, target->settings(), source, type, OUTPUT_RELATIVE,
- target->settings()->build_settings()->build_dir());
-}
-
-// static
-OutputFile SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
- const Target* target,
- const Tool* tool,
- const SubstitutionPattern& pattern) {
- OutputFile result;
- for (const auto& subrange : pattern.ranges()) {
- if (subrange.type == SUBSTITUTION_LITERAL) {
- result.value().append(subrange.literal);
- } else {
- result.value().append(GetLinkerSubstitution(target, tool, subrange.type));
- }
- }
- return result;
-}
-
-// static
-void SubstitutionWriter::ApplyListToLinkerAsOutputFile(
- const Target* target,
- const Tool* tool,
- const SubstitutionList& list,
- std::vector<OutputFile>* output) {
- for (const auto& item : list.list())
- output->push_back(ApplyPatternToLinkerAsOutputFile(target, tool, item));
-}
-
-// static
-std::string SubstitutionWriter::GetLinkerSubstitution(
- const Target* target,
- const Tool* tool,
- SubstitutionType type) {
- // First try the common tool ones.
- std::string result;
- if (GetTargetSubstitution(target, type, &result))
- return result;
-
- // Fall-through to the linker-specific ones.
- switch (type) {
- case SUBSTITUTION_OUTPUT_DIR:
- // Use the target's value if there is one (it will have no expansion
- // patterns since it can directly use GN variables to compute whatever
- // path it wants), or the tool's default (which will contain further
- // expansions).
- if (target->output_dir().is_null()) {
- return ApplyPatternToLinkerAsOutputFile(
- target, tool, tool->default_output_dir()).value();
- }
- SetDirOrDotWithNoSlash(RebasePath(
- target->output_dir().value(),
- target->settings()->build_settings()->build_dir()),
- &result);
- return result;
-
- case SUBSTITUTION_OUTPUT_EXTENSION:
- // Use the extension provided on the target if specified, otherwise
- // fall back on the default. Note that the target's output extension
- // does not include the dot but the tool's does.
- if (!target->output_extension_set())
- return tool->default_output_extension();
- if (target->output_extension().empty())
- return std::string(); // Explicitly set to no extension.
- return std::string(".") + target->output_extension();
-
- default:
- NOTREACHED();
- return std::string();
- }
-}
diff --git a/chromium/tools/gn/substitution_writer.h b/chromium/tools/gn/substitution_writer.h
deleted file mode 100644
index 92f09c4866f..00000000000
--- a/chromium/tools/gn/substitution_writer.h
+++ /dev/null
@@ -1,254 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_SUBSTITUTION_WRITER_H_
-#define TOOLS_GN_SUBSTITUTION_WRITER_H_
-
-#include <iosfwd>
-#include <vector>
-
-#include "tools/gn/substitution_type.h"
-
-struct EscapeOptions;
-class OutputFile;
-class Settings;
-class SourceDir;
-class SourceFile;
-class SubstitutionList;
-class SubstitutionPattern;
-class Target;
-class Tool;
-
-// Help text for script source expansion.
-extern const char kSourceExpansion_Help[];
-
-// This class handles writing or applying substitution patterns to strings.
-//
-// There are several different uses:
-//
-// - Source substitutions: These are used to compute action_foreach
-// outputs and arguments. Functions are provided to expand these in terms
-// of both OutputFiles (for writing Ninja files) as well as SourceFiles
-// (for computing lists used by code).
-//
-// - Target substitutions: These are specific to the target+tool combination
-// and are shared between the compiler and linker ones. It includes things
-// like the target_gen_dir.
-//
-// - Compiler substitutions: These are used to compute compiler outputs.
-// It includes all source substitutions (since they depend on the various
-// parts of the source file) as well as the target substitutions.
-//
-// - Linker substitutions: These are used to compute linker outputs. It
-// includes the target substitutions.
-//
-// The compiler and linker specific substitutions do NOT include the various
-// cflags, ldflags, libraries, etc. These are written by the ninja target
-// writer since they depend on traversing the dependency tree.
-//
-// The methods which take a target as an argument can accept null target
-// pointer if there is no target context, in which case the substitutions
-// requiring target context will not work.
-class SubstitutionWriter {
- public:
- enum OutputStyle {
- OUTPUT_ABSOLUTE, // Dirs will be absolute "//foo/bar".
- OUTPUT_RELATIVE, // Dirs will be relative to a given directory.
- };
-
- // Writes the pattern to the given stream with no special handling, and with
- // Ninja variables replacing the patterns.
- static void WriteWithNinjaVariables(
- const SubstitutionPattern& pattern,
- const EscapeOptions& escape_options,
- std::ostream& out);
-
- // NOP substitutions ---------------------------------------------------------
-
- // Converts the given SubstitutionList to OutputFiles assuming there are
- // no substitutions (it will assert if there are). This is used for cases
- // like actions where the outputs are explicit, but the list is stored as
- // a SubstitutionList.
- static void GetListAsSourceFiles(
- const SubstitutionList& list,
- std::vector<SourceFile>* output);
- static void GetListAsOutputFiles(
- const Settings* settings,
- const SubstitutionList& list,
- std::vector<OutputFile>* output);
-
- // Source substitutions -----------------------------------------------------
-
- // Applies the substitution pattern to a source file, returning the result
- // as either a string, a SourceFile or an OutputFile. If the result is
- // expected to be a SourceFile or an OutputFile, this will CHECK if the
- // result isn't in the correct directory. The caller should validate this
- // first (see for example IsFileInOuputDir).
- //
- // The target can be null (see class comment above).
- static SourceFile ApplyPatternToSource(
- const Target* target,
- const Settings* settings,
- const SubstitutionPattern& pattern,
- const SourceFile& source);
- static std::string ApplyPatternToSourceAsString(
- const Target* target,
- const Settings* settings,
- const SubstitutionPattern& pattern,
- const SourceFile& source);
- static OutputFile ApplyPatternToSourceAsOutputFile(
- const Target* target,
- const Settings* settings,
- const SubstitutionPattern& pattern,
- const SourceFile& source);
-
- // Applies the substitution list to a source, APPENDING the result to the
- // given output vector. It works this way so one can call multiple times to
- // apply to multiple files and create a list. The result can either be
- // SourceFiles or OutputFiles.
- //
- // The target can be null (see class comment above).
- static void ApplyListToSource(
- const Target* target,
- const Settings* settings,
- const SubstitutionList& list,
- const SourceFile& source,
- std::vector<SourceFile>* output);
- static void ApplyListToSourceAsString(
- const Target* target,
- const Settings* settings,
- const SubstitutionList& list,
- const SourceFile& source,
- std::vector<std::string>* output);
- static void ApplyListToSourceAsOutputFile(
- const Target* target,
- const Settings* settings,
- const SubstitutionList& list,
- const SourceFile& source,
- std::vector<OutputFile>* output);
-
- // Like ApplyListToSource but applies the list to all sources and replaces
- // rather than appends the output (this produces the complete output).
- //
- // The target can be null (see class comment above).
- static void ApplyListToSources(
- const Target* target,
- const Settings* settings,
- const SubstitutionList& list,
- const std::vector<SourceFile>& sources,
- std::vector<SourceFile>* output);
- static void ApplyListToSourcesAsString(
- const Target* target,
- const Settings* settings,
- const SubstitutionList& list,
- const std::vector<SourceFile>& sources,
- std::vector<std::string>* output);
- static void ApplyListToSourcesAsOutputFile(
- const Target* target,
- const Settings* settings,
- const SubstitutionList& list,
- const std::vector<SourceFile>& sources,
- std::vector<OutputFile>* output);
-
- // Given a list of source replacement types used, writes the Ninja variable
- // definitions for the given source file to use for those replacements. The
- // variables will be indented two spaces. Since this is for writing to
- // Ninja files, paths will be relative to the build dir, and no definition
- // for {{source}} will be written since that maps to Ninja's implicit $in
- // variable.
- //
- // The target can be null (see class comment above).
- static void WriteNinjaVariablesForSource(
- const Target* target,
- const Settings* settings,
- const SourceFile& source,
- const std::vector<SubstitutionType>& types,
- const EscapeOptions& escape_options,
- std::ostream& out);
-
- // Extracts the given type of substitution related to a source file from the
- // given source file. If output_style is OUTPUT_RELATIVE, relative_to
- // indicates the directory that the relative directories should be relative
- // to, otherwise it is ignored.
- //
- // The target can be null (see class comment above).
- static std::string GetSourceSubstitution(
- const Target* target,
- const Settings* settings,
- const SourceFile& source,
- SubstitutionType type,
- OutputStyle output_style,
- const SourceDir& relative_to);
-
- // Target substitutions ------------------------------------------------------
- //
- // Handles the target substitutions that apply to both compiler and linker
- // tools.
- static OutputFile ApplyPatternToTargetAsOutputFile(
- const Target* target,
- const Tool* tool,
- const SubstitutionPattern& pattern);
- static void ApplyListToTargetAsOutputFile(
- const Target* target,
- const Tool* tool,
- const SubstitutionList& list,
- std::vector<OutputFile>* output);
-
- // This function is slightly different than the other substitution getters
- // since it can handle failure (since it is designed to be used by the
- // compiler and linker ones which will fall through if it's not a common tool
- // one).
- static bool GetTargetSubstitution(
- const Target* target,
- SubstitutionType type,
- std::string* result);
- static std::string GetTargetSubstitution(
- const Target* target,
- SubstitutionType type);
-
- // Compiler substitutions ----------------------------------------------------
- //
- // A compiler substitution allows both source and tool substitutions. These
- // are used to compute output names for compiler tools.
-
- static OutputFile ApplyPatternToCompilerAsOutputFile(
- const Target* target,
- const SourceFile& source,
- const SubstitutionPattern& pattern);
- static void ApplyListToCompilerAsOutputFile(
- const Target* target,
- const SourceFile& source,
- const SubstitutionList& list,
- std::vector<OutputFile>* output);
-
- // Like GetSourceSubstitution but for strings based on the target or
- // toolchain. This type of result will always be relative to the build
- // directory.
- static std::string GetCompilerSubstitution(
- const Target* target,
- const SourceFile& source,
- SubstitutionType type);
-
- // Linker substitutions ------------------------------------------------------
-
- static OutputFile ApplyPatternToLinkerAsOutputFile(
- const Target* target,
- const Tool* tool,
- const SubstitutionPattern& pattern);
- static void ApplyListToLinkerAsOutputFile(
- const Target* target,
- const Tool* tool,
- const SubstitutionList& list,
- std::vector<OutputFile>* output);
-
- // Like GetSourceSubstitution but for strings based on the target or
- // toolchain. This type of result will always be relative to the build
- // directory.
- static std::string GetLinkerSubstitution(
- const Target* target,
- const Tool* tool,
- SubstitutionType type);
-};
-
-#endif // TOOLS_GN_SUBSTITUTION_WRITER_H_
diff --git a/chromium/tools/gn/substitution_writer_unittest.cc b/chromium/tools/gn/substitution_writer_unittest.cc
deleted file mode 100644
index d98d4cee5f5..00000000000
--- a/chromium/tools/gn/substitution_writer_unittest.cc
+++ /dev/null
@@ -1,337 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <sstream>
-
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/err.h"
-#include "tools/gn/escape.h"
-#include "tools/gn/substitution_list.h"
-#include "tools/gn/substitution_pattern.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/target.h"
-#include "tools/gn/test_with_scope.h"
-
-TEST(SubstitutionWriter, GetListAs) {
- TestWithScope setup;
-
- SubstitutionList list = SubstitutionList::MakeForTest(
- "//foo/bar/a.cc",
- "//foo/bar/b.cc");
-
- std::vector<SourceFile> sources;
- SubstitutionWriter::GetListAsSourceFiles(list, &sources);
- ASSERT_EQ(2u, sources.size());
- EXPECT_EQ("//foo/bar/a.cc", sources[0].value());
- EXPECT_EQ("//foo/bar/b.cc", sources[1].value());
-
- std::vector<OutputFile> outputs;
- SubstitutionWriter::GetListAsOutputFiles(setup.settings(), list, &outputs);
- ASSERT_EQ(2u, outputs.size());
- EXPECT_EQ("../../foo/bar/a.cc", outputs[0].value());
- EXPECT_EQ("../../foo/bar/b.cc", outputs[1].value());
-}
-
-TEST(SubstitutionWriter, ApplyPatternToSource) {
- TestWithScope setup;
-
- SubstitutionPattern pattern;
- Err err;
- ASSERT_TRUE(pattern.Parse("{{source_gen_dir}}/{{source_name_part}}.tmp",
- nullptr, &err));
-
- SourceFile result = SubstitutionWriter::ApplyPatternToSource(
- nullptr, setup.settings(), pattern, SourceFile("//foo/bar/myfile.txt"));
- ASSERT_EQ("//out/Debug/gen/foo/bar/myfile.tmp", result.value());
-}
-
-TEST(SubstitutionWriter, ApplyPatternToSourceAsOutputFile) {
- TestWithScope setup;
-
- SubstitutionPattern pattern;
- Err err;
- ASSERT_TRUE(pattern.Parse("{{source_gen_dir}}/{{source_name_part}}.tmp",
- nullptr, &err));
-
- OutputFile result = SubstitutionWriter::ApplyPatternToSourceAsOutputFile(
- nullptr, setup.settings(), pattern, SourceFile("//foo/bar/myfile.txt"));
- ASSERT_EQ("gen/foo/bar/myfile.tmp", result.value());
-}
-
-TEST(SubstitutionWriter, WriteNinjaVariablesForSource) {
- TestWithScope setup;
-
- std::vector<SubstitutionType> types;
- types.push_back(SUBSTITUTION_SOURCE);
- types.push_back(SUBSTITUTION_SOURCE_NAME_PART);
- types.push_back(SUBSTITUTION_SOURCE_DIR);
-
- EscapeOptions options;
- options.mode = ESCAPE_NONE;
-
- std::ostringstream out;
- SubstitutionWriter::WriteNinjaVariablesForSource(
- nullptr, setup.settings(), SourceFile("//foo/bar/baz.txt"), types,
- options, out);
-
- // The "source" should be skipped since that will expand to $in which is
- // implicit.
- EXPECT_EQ(
- " source_name_part = baz\n"
- " source_dir = ../../foo/bar\n",
- out.str());
-}
-
-TEST(SubstitutionWriter, WriteWithNinjaVariables) {
- Err err;
- SubstitutionPattern pattern;
- ASSERT_TRUE(pattern.Parse("-i {{source}} --out=bar\"{{source_name_part}}\".o",
- nullptr, &err));
- EXPECT_FALSE(err.has_error());
-
- EscapeOptions options;
- options.mode = ESCAPE_NONE;
-
- std::ostringstream out;
- SubstitutionWriter::WriteWithNinjaVariables(pattern, options, out);
-
- EXPECT_EQ(
- "-i ${in} --out=bar\"${source_name_part}\".o",
- out.str());
-}
-
-TEST(SubstitutionWriter, SourceSubstitutions) {
- TestWithScope setup;
- Err err;
-
- Target target(setup.settings(), Label(SourceDir("//foo/bar/"), "baz"));
- target.set_output_type(Target::STATIC_LIBRARY);
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- // Call to get substitutions relative to the build dir.
- #define GetRelSubst(str, what) \
- SubstitutionWriter::GetSourceSubstitution( \
- &target, \
- setup.settings(), \
- SourceFile(str), \
- what, \
- SubstitutionWriter::OUTPUT_RELATIVE, \
- setup.settings()->build_settings()->build_dir())
-
- // Call to get absolute directory substitutions.
- #define GetAbsSubst(str, what) \
- SubstitutionWriter::GetSourceSubstitution( \
- &target, \
- setup.settings(), \
- SourceFile(str), \
- what, \
- SubstitutionWriter::OUTPUT_ABSOLUTE, \
- SourceDir())
-
- // Try all possible templates with a normal looking string.
- EXPECT_EQ("../../foo/bar/baz.txt",
- GetRelSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE));
- EXPECT_EQ("//foo/bar/baz.txt",
- GetAbsSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE));
-
- EXPECT_EQ("baz",
- GetRelSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_NAME_PART));
- EXPECT_EQ("baz",
- GetAbsSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_NAME_PART));
-
- EXPECT_EQ("baz.txt",
- GetRelSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_FILE_PART));
- EXPECT_EQ("baz.txt",
- GetAbsSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_FILE_PART));
-
- EXPECT_EQ("../../foo/bar",
- GetRelSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_DIR));
- EXPECT_EQ("//foo/bar",
- GetAbsSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_DIR));
-
- EXPECT_EQ("foo/bar", GetRelSubst("//foo/bar/baz.txt",
- SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR));
- EXPECT_EQ("foo/bar", GetAbsSubst("//foo/bar/baz.txt",
- SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR));
-
- EXPECT_EQ("gen/foo/bar",
- GetRelSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_GEN_DIR));
- EXPECT_EQ("//out/Debug/gen/foo/bar",
- GetAbsSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_GEN_DIR));
-
- EXPECT_EQ("obj/foo/bar",
- GetRelSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_OUT_DIR));
- EXPECT_EQ("//out/Debug/obj/foo/bar",
- GetAbsSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_OUT_DIR));
-
- // Operations on an absolute path.
- EXPECT_EQ("/baz.txt", GetRelSubst("/baz.txt", SUBSTITUTION_SOURCE));
- EXPECT_EQ("/.", GetRelSubst("/baz.txt", SUBSTITUTION_SOURCE_DIR));
- EXPECT_EQ("gen/ABS_PATH",
- GetRelSubst("/baz.txt", SUBSTITUTION_SOURCE_GEN_DIR));
- EXPECT_EQ("obj/ABS_PATH",
- GetRelSubst("/baz.txt", SUBSTITUTION_SOURCE_OUT_DIR));
-#if defined(OS_WIN)
- EXPECT_EQ("gen/ABS_PATH/C",
- GetRelSubst("/C:/baz.txt", SUBSTITUTION_SOURCE_GEN_DIR));
- EXPECT_EQ("obj/ABS_PATH/C",
- GetRelSubst("/C:/baz.txt", SUBSTITUTION_SOURCE_OUT_DIR));
-#endif
-
- EXPECT_EQ(".",
- GetRelSubst("//baz.txt", SUBSTITUTION_SOURCE_ROOT_RELATIVE_DIR));
-
- EXPECT_EQ("baz.txt",
- GetRelSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_TARGET_RELATIVE));
- EXPECT_EQ("baz.txt",
- GetAbsSubst("//foo/bar/baz.txt", SUBSTITUTION_SOURCE_TARGET_RELATIVE));
-
- #undef GetAbsSubst
- #undef GetRelSubst
-}
-
-TEST(SubstitutionWriter, TargetSubstitutions) {
- TestWithScope setup;
- Err err;
-
- Target target(setup.settings(), Label(SourceDir("//foo/bar/"), "baz"));
- target.set_output_type(Target::STATIC_LIBRARY);
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- std::string result;
- EXPECT_TRUE(SubstitutionWriter::GetTargetSubstitution(
- &target, SUBSTITUTION_LABEL, &result));
- EXPECT_EQ("//foo/bar:baz", result);
-
- EXPECT_TRUE(SubstitutionWriter::GetTargetSubstitution(
- &target, SUBSTITUTION_LABEL_NAME, &result));
- EXPECT_EQ("baz", result);
-
- EXPECT_TRUE(SubstitutionWriter::GetTargetSubstitution(
- &target, SUBSTITUTION_ROOT_GEN_DIR, &result));
- EXPECT_EQ("gen", result);
-
- EXPECT_TRUE(SubstitutionWriter::GetTargetSubstitution(
- &target, SUBSTITUTION_ROOT_OUT_DIR, &result));
- EXPECT_EQ(".", result);
-
- EXPECT_TRUE(SubstitutionWriter::GetTargetSubstitution(
- &target, SUBSTITUTION_TARGET_GEN_DIR, &result));
- EXPECT_EQ("gen/foo/bar", result);
-
- EXPECT_TRUE(SubstitutionWriter::GetTargetSubstitution(
- &target, SUBSTITUTION_TARGET_OUT_DIR, &result));
- EXPECT_EQ("obj/foo/bar", result);
-
- EXPECT_TRUE(SubstitutionWriter::GetTargetSubstitution(
- &target, SUBSTITUTION_TARGET_OUTPUT_NAME, &result));
- EXPECT_EQ("libbaz", result);
-}
-
-TEST(SubstitutionWriter, CompilerSubstitutions) {
- TestWithScope setup;
- Err err;
-
- Target target(setup.settings(), Label(SourceDir("//foo/bar/"), "baz"));
- target.set_output_type(Target::STATIC_LIBRARY);
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- // The compiler substitution is just source + target combined. So test one
- // of each of those classes of things to make sure this is hooked up.
- EXPECT_EQ("file",
- SubstitutionWriter::GetCompilerSubstitution(
- &target, SourceFile("//foo/bar/file.txt"),
- SUBSTITUTION_SOURCE_NAME_PART));
- EXPECT_EQ("gen/foo/bar",
- SubstitutionWriter::GetCompilerSubstitution(
- &target, SourceFile("//foo/bar/file.txt"),
- SUBSTITUTION_TARGET_GEN_DIR));
-}
-
-TEST(SubstitutionWriter, LinkerSubstitutions) {
- TestWithScope setup;
- Err err;
-
- Target target(setup.settings(), Label(SourceDir("//foo/bar/"), "baz"));
- target.set_output_type(Target::SHARED_LIBRARY);
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- const Tool* tool = setup.toolchain()->GetToolForTargetFinalOutput(&target);
-
- // The compiler substitution is just target + OUTPUT_EXTENSION combined. So
- // test one target one plus the output extension.
- EXPECT_EQ(".so",
- SubstitutionWriter::GetLinkerSubstitution(
- &target, tool, SUBSTITUTION_OUTPUT_EXTENSION));
- EXPECT_EQ("gen/foo/bar",
- SubstitutionWriter::GetLinkerSubstitution(
- &target, tool, SUBSTITUTION_TARGET_GEN_DIR));
-
- // Test that we handle paths that end up in the root build dir properly
- // (no leading "./" or "/").
- SubstitutionPattern pattern;
- ASSERT_TRUE(pattern.Parse("{{root_out_dir}}/{{target_output_name}}.so",
- nullptr, &err));
-
- OutputFile output = SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
- &target, tool, pattern);
- EXPECT_EQ("./libbaz.so", output.value());
-
- // Output extensions can be overridden.
- target.set_output_extension("extension");
- EXPECT_EQ(".extension",
- SubstitutionWriter::GetLinkerSubstitution(
- &target, tool, SUBSTITUTION_OUTPUT_EXTENSION));
- target.set_output_extension("");
- EXPECT_EQ("",
- SubstitutionWriter::GetLinkerSubstitution(
- &target, tool, SUBSTITUTION_OUTPUT_EXTENSION));
-
- // Output directory is tested in a separate test below.
-}
-
-TEST(SubstitutionWriter, OutputDir) {
- TestWithScope setup;
- Err err;
-
- // This tool has an output directory pattern and uses that for the
- // output name.
- Tool tool;
- SubstitutionPattern out_dir_pattern;
- ASSERT_TRUE(out_dir_pattern.Parse("{{root_out_dir}}/{{target_output_name}}",
- nullptr, &err));
- tool.set_default_output_dir(out_dir_pattern);
- tool.SetComplete();
-
- // Default target with no output dir overrides.
- Target target(setup.settings(), Label(SourceDir("//foo/"), "baz"));
- target.set_output_type(Target::EXECUTABLE);
- target.SetToolchain(setup.toolchain());
- ASSERT_TRUE(target.OnResolved(&err));
-
- // The output should expand the default from the patterns in the tool.
- SubstitutionPattern output_name;
- ASSERT_TRUE(output_name.Parse("{{output_dir}}/{{target_output_name}}.exe",
- nullptr, &err));
- EXPECT_EQ("./baz/baz.exe",
- SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
- &target, &tool, output_name).value());
-
- // Override the output name to the root build dir.
- target.set_output_dir(SourceDir("//out/Debug/"));
- EXPECT_EQ("./baz.exe",
- SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
- &target, &tool, output_name).value());
-
- // Override the output name to a new subdirectory.
- target.set_output_dir(SourceDir("//out/Debug/foo/bar"));
- EXPECT_EQ("foo/bar/baz.exe",
- SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
- &target, &tool, output_name).value());
-}
diff --git a/chromium/tools/gn/switches.cc b/chromium/tools/gn/switches.cc
deleted file mode 100644
index 05c2a5befca..00000000000
--- a/chromium/tools/gn/switches.cc
+++ /dev/null
@@ -1,290 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/switches.h"
-
-namespace switches {
-
-const char kArgs[] = "args";
-const char kArgs_HelpShort[] =
- "--args: Specifies build arguments overrides.";
-const char kArgs_Help[] =
- R"(--args: Specifies build arguments overrides.
-
- See "gn help buildargs" for an overview of how build arguments work.
-
- Most operations take a build directory. The build arguments are taken from
- the previous build done in that directory. If a command specifies --args, it
- will override the previous arguments stored in the build directory, and use
- the specified ones.
-
- The args specified will be saved to the build directory for subsequent
- commands. Specifying --args="" will clear all build arguments.
-
-Formatting
-
- The value of the switch is interpreted in GN syntax. For typical usage of
- string arguments, you will need to be careful about escaping of quotes.
-
-Examples
-
- gn gen out/Default --args="foo=\"bar\""
-
- gn gen out/Default --args='foo="bar" enable=true blah=7'
-
- gn check out/Default --args=""
- Clears existing build args from the directory.
-
- gn desc out/Default --args="some_list=[1, false, \"foo\"]"
-)";
-
-#define COLOR_HELP_LONG \
- "--[no]color: Forces colored output on or off.\n"\
- "\n"\
- " Normally GN will try to detect whether it is outputting to a terminal\n"\
- " and will enable or disable color accordingly. Use of these switches\n"\
- " will override the default.\n"\
- "\n"\
- "Examples\n"\
- "\n"\
- " gn gen out/Default --color\n"\
- "\n"\
- " gn gen out/Default --nocolor\n"
-const char kColor[] = "color";
-const char kColor_HelpShort[] =
- "--color: Force colored output.";
-const char kColor_Help[] = COLOR_HELP_LONG;
-
-const char kDotfile[] = "dotfile";
-const char kDotfile_HelpShort[] =
- "--dotfile: Override the name of the \".gn\" file.";
-const char kDotfile_Help[] =
- R"(--dotfile: Override the name of the ".gn" file.
-
- Normally GN loads the ".gn"file from the source root for some basic
- configuration (see "gn help dotfile"). This flag allows you to
- use a different file.
-
- Note that this interacts with "--root" in a possibly incorrect way.
- It would be nice to test the edge cases and document or fix.
-)";
-
-const char kFailOnUnusedArgs[] = "fail-on-unused-args";
-const char kFailOnUnusedArgs_HelpShort[] =
- "--fail-on-unused-args: Treat unused build args as fatal errors.";
-const char kFailOnUnusedArgs_Help[] =
- R"(--fail-on-unused-args: Treat unused build args as fatal errors.
-
- If you set a value in a build's "gn args" and never use it in the build (in
- a declare_args() block), GN will normally print an error but not fail the
- build.
-
- In many cases engineers would use build args to enable or disable features
- that would sometimes get removed. It would by annoying to block work for
- typically benign problems. In Chrome in particular, flags might be configured
- for build bots in a separate infrastructure repository, or a declare_args
- block might be changed in a third party repository. Treating these errors as
- blocking forced complex multi- way patches to land what would otherwise be
- simple changes.
-
- In some cases, such concerns are not as important, and a mismatch in build
- flags between the invoker of the build and the build files represents a
- critical mismatch that should be immediately fixed. Such users can set this
- flag to force GN to fail in that case.
-)";
-
-const char kMarkdown[] = "markdown";
-const char kMarkdown_HelpShort[] =
- "--markdown: Write help output in the Markdown format.";
-const char kMarkdown_Help[] =
- "--markdown: Write help output in the Markdown format.\n";
-
-const char kNoColor[] = "nocolor";
-const char kNoColor_HelpShort[] =
- "--nocolor: Force non-colored output.";
-const char kNoColor_Help[] = COLOR_HELP_LONG;
-
-const char kScriptExecutable[] = "script-executable";
-const char kScriptExecutable_HelpShort[] =
- "--script-executable: Set the executable used to execute scripts.";
-const char kScriptExecutable_Help[] =
- R"(--script-executable: Set the executable used to execute scripts.
-
- By default GN searches the PATH for Python to execute scripts in action
- targets and exec_script calls. This flag allows the specification of a
- specific Python executable or potentially a different language
- interpreter.
-)";
-
-const char kQuiet[] = "q";
-const char kQuiet_HelpShort[] =
- "-q: Quiet mode. Don't print output on success.";
-const char kQuiet_Help[] =
- R"(-q: Quiet mode. Don't print output on success.
-
- This is useful when running as a part of another script.
-)";
-
-const char kRoot[] = "root";
-const char kRoot_HelpShort[] =
- "--root: Explicitly specify source root.";
-const char kRoot_Help[] =
- R"(--root: Explicitly specify source root.
-
- Normally GN will look up in the directory tree from the current directory to
- find a ".gn" file. The source root directory specifies the meaning of "//"
- beginning with paths, and the BUILD.gn file in that directory will be the
- first thing loaded.
-
- Specifying --root allows GN to do builds in a specific directory regardless
- of the current directory.
-
-Examples
-
- gn gen //out/Default --root=/home/baracko/src
-
- gn desc //out/Default --root="C:\Users\BObama\My Documents\foo"
-)";
-
-const char kRuntimeDepsListFile[] = "runtime-deps-list-file";
-const char kRuntimeDepsListFile_HelpShort[] =
- "--runtime-deps-list-file: Save runtime dependencies for targets in file.";
-const char kRuntimeDepsListFile_Help[] =
- R"(--runtime-deps-list-file: Save runtime dependencies for targets in file.
-
- --runtime-deps-list-file=<filename>
-
- Where <filename> is a text file consisting of the labels, one per line, of
- the targets for which runtime dependencies are desired.
-
- See "gn help runtime_deps" for a description of how runtime dependencies are
- computed.
-
-Runtime deps output file
-
- For each target requested, GN will write a separate runtime dependency file.
- The runtime dependency file will be in the output directory alongside the
- output file of the target, with a ".runtime_deps" extension. For example, if
- the target "//foo:bar" is listed in the input file, and that target produces
- an output file "bar.so", GN will create a file "bar.so.runtime_deps" in the
- build directory.
-
- If a source set, action, copy, or group is listed, the runtime deps file will
- correspond to the .stamp file corresponding to that target. This is probably
- not useful; the use-case for this feature is generally executable targets.
-
- The runtime dependency file will list one file per line, with no escaping.
- The files will be relative to the root_build_dir. The first line of the file
- will be the main output file of the target itself (in the above example,
- "bar.so").
-)";
-
-const char kThreads[] = "threads";
-const char kThreads_HelpShort[] =
- "--threads: Specify number of worker threads.";
-const char kThreads_Help[] =
- R"(--threads: Specify number of worker threads.
-
- GN runs many threads to load and run build files. This can make debugging
- challenging. Or you may want to experiment with different values to see how
- it affects performance.
-
- The parameter is the number of worker threads. This does not count the main
- thread (so there are always at least two).
-
-Examples
-
- gen gen out/Default --threads=1
-)";
-
-const char kTime[] = "time";
-const char kTime_HelpShort[] =
- "--time: Outputs a summary of how long everything took.";
-const char kTime_Help[] =
- R"(--time: Outputs a summary of how long everything took.
-
- Hopefully self-explanatory.
-
-Examples
-
- gn gen out/Default --time
-)";
-
-const char kTracelog[] = "tracelog";
-const char kTracelog_HelpShort[] =
- "--tracelog: Writes a Chrome-compatible trace log to the given file.";
-const char kTracelog_Help[] =
- R"(--tracelog: Writes a Chrome-compatible trace log to the given file.
-
- The trace log will show file loads, executions, scripts, and writes. This
- allows performance analysis of the generation step.
-
- To view the trace, open Chrome and navigate to "chrome://tracing/", then
- press "Load" and specify the file you passed to this parameter.
-
-Examples
-
- gn gen out/Default --tracelog=mytrace.trace
-)";
-
-const char kVerbose[] = "v";
-const char kVerbose_HelpShort[] =
- "-v: Verbose logging.";
-const char kVerbose_Help[] =
- R"(-v: Verbose logging.
-
- This will spew logging events to the console for debugging issues.
-
- Good luck!
-)";
-
-const char kVersion[] = "version";
-const char kVersion_HelpShort[] =
- "--version: Prints the GN version number and exits.";
-// It's impossible to see this since gn_main prints the version and exits
-// immediately if this switch is used.
-const char kVersion_Help[] = "";
-
-const char kAllToolchains[] = "all-toolchains";
-
-// -----------------------------------------------------------------------------
-
-SwitchInfo::SwitchInfo()
- : short_help(""),
- long_help("") {
-}
-
-SwitchInfo::SwitchInfo(const char* short_help, const char* long_help)
- : short_help(short_help),
- long_help(long_help) {
-}
-
-#define INSERT_VARIABLE(var) \
- info_map[k##var] = SwitchInfo(k##var##_HelpShort, k##var##_Help);
-
-const SwitchInfoMap& GetSwitches() {
- static SwitchInfoMap info_map;
- if (info_map.empty()) {
- INSERT_VARIABLE(Args)
- INSERT_VARIABLE(Color)
- INSERT_VARIABLE(Dotfile)
- INSERT_VARIABLE(FailOnUnusedArgs)
- INSERT_VARIABLE(Markdown)
- INSERT_VARIABLE(NoColor)
- INSERT_VARIABLE(Root)
- INSERT_VARIABLE(Quiet)
- INSERT_VARIABLE(RuntimeDepsListFile)
- INSERT_VARIABLE(ScriptExecutable)
- INSERT_VARIABLE(Threads)
- INSERT_VARIABLE(Time)
- INSERT_VARIABLE(Tracelog)
- INSERT_VARIABLE(Verbose)
- INSERT_VARIABLE(Version)
- }
- return info_map;
-}
-
-#undef INSERT_VARIABLE
-
-} // namespace switches
diff --git a/chromium/tools/gn/switches.h b/chromium/tools/gn/switches.h
deleted file mode 100644
index effaa25ed3c..00000000000
--- a/chromium/tools/gn/switches.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_SWITCHES_H_
-#define TOOLS_GN_SWITCHES_H_
-
-#include <map>
-
-#include "base/strings/string_piece.h"
-
-namespace switches {
-
-struct SwitchInfo {
- SwitchInfo();
- SwitchInfo(const char* short_help,
- const char* long_help);
-
- const char* short_help;
- const char* long_help;
-};
-
-typedef std::map<base::StringPiece, SwitchInfo> SwitchInfoMap;
-
-// Returns the mapping of all global switches.
-const SwitchInfoMap& GetSwitches();
-
-// This file contains global switches. If a command takes specific ones only
-// to that command, just put them in that command's .cc file.
-
-extern const char kArgs[];
-extern const char kArgs_HelpShort[];
-extern const char kArgs_Help[];
-
-extern const char kColor[];
-extern const char kColor_HelpShort[];
-extern const char kColor_Help[];
-
-extern const char kDotfile[];
-extern const char kDotfile_HelpShort[];
-extern const char kDotfile_Help[];
-
-extern const char kFailOnUnusedArgs[];
-extern const char kFailOnUnusedArgs_HelpShort[];
-extern const char kFailOnUnusedArgs_Help[];
-
-extern const char kMarkdown[];
-extern const char kMarkdown_HelpShort[];
-extern const char kMarkdown_Help[];
-
-extern const char kNoColor[];
-extern const char kNoColor_HelpShort[];
-extern const char kNoColor_Help[];
-
-extern const char kScriptExecutable[];
-extern const char kScriptExecutable_HelpShort[];
-extern const char kScriptExecutable_Help[];
-
-extern const char kQuiet[];
-extern const char kQuiet_HelpShort[];
-extern const char kQuiet_Help[];
-
-extern const char kRoot[];
-extern const char kRoot_HelpShort[];
-extern const char kRoot_Help[];
-
-extern const char kRuntimeDepsListFile[];
-extern const char kRuntimeDepsListFile_HelpShort[];
-extern const char kRuntimeDepsListFile_Help[];
-
-extern const char kThreads[];
-extern const char kThreads_HelpShort[];
-extern const char kThreads_Help[];
-
-extern const char kTime[];
-extern const char kTime_HelpShort[];
-extern const char kTime_Help[];
-
-extern const char kTracelog[];
-extern const char kTracelog_HelpShort[];
-extern const char kTracelog_Help[];
-
-extern const char kVerbose[];
-extern const char kVerbose_HelpShort[];
-extern const char kVerbose_Help[];
-
-extern const char kVersion[];
-extern const char kVersion_HelpShort[];
-extern const char kVersion_Help[];
-
-// This switch is used by several commands. It is here so it can be shared,
-// but it's documented in the individual commands it applies to rather than
-// globally.
-extern const char kAllToolchains[];
-#define ALL_TOOLCHAINS_SWITCH_HELP \
- " --all-toolchains\n" \
- " Normally only inputs in the default toolchain will be included.\n" \
- " This switch will turn on matching all toolchains.\n" \
- "\n" \
- " For example, a file is in a target might be compiled twice:\n" \
- " once in the default toolchain and once in a secondary one. Without\n" \
- " this flag, only the default toolchain one will be matched by\n" \
- " wildcards. With this flag, both will be matched.\n"
-
-} // namespace switches
-
-#endif // TOOLS_GN_SWITCHES_H_
diff --git a/chromium/tools/gn/target.cc b/chromium/tools/gn/target.cc
deleted file mode 100644
index d0714a8cbbc..00000000000
--- a/chromium/tools/gn/target.cc
+++ /dev/null
@@ -1,874 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/target.h"
-
-#include <stddef.h>
-
-#include "base/bind.h"
-#include "base/stl_util.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "tools/gn/config_values_extractors.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/source_file_type.h"
-#include "tools/gn/substitution_writer.h"
-#include "tools/gn/tool.h"
-#include "tools/gn/toolchain.h"
-#include "tools/gn/trace.h"
-
-namespace {
-
-typedef std::set<const Config*> ConfigSet;
-
-// Merges the public configs from the given target to the given config list.
-void MergePublicConfigsFrom(const Target* from_target,
- UniqueVector<LabelConfigPair>* dest) {
- const UniqueVector<LabelConfigPair>& pub = from_target->public_configs();
- dest->Append(pub.begin(), pub.end());
-}
-
-// Like MergePublicConfigsFrom above except does the "all dependent" ones. This
-// additionally adds all configs to the all_dependent_configs_ of the dest
-// target given in *all_dest.
-void MergeAllDependentConfigsFrom(const Target* from_target,
- UniqueVector<LabelConfigPair>* dest,
- UniqueVector<LabelConfigPair>* all_dest) {
- for (const auto& pair : from_target->all_dependent_configs()) {
- all_dest->push_back(pair);
- dest->push_back(pair);
- }
-}
-
-Err MakeTestOnlyError(const Target* from, const Target* to) {
- return Err(from->defined_from(), "Test-only dependency not allowed.",
- from->label().GetUserVisibleName(false) + "\n"
- "which is NOT marked testonly can't depend on\n" +
- to->label().GetUserVisibleName(false) + "\n"
- "which is marked testonly. Only targets with \"testonly = true\"\n"
- "can depend on other test-only targets.\n"
- "\n"
- "Either mark it test-only or don't do this dependency.");
-}
-
-// Set check_private_deps to true for the first invocation since a target
-// can see all of its dependencies. For recursive invocations this will be set
-// to false to follow only public dependency paths.
-//
-// Pass a pointer to an empty set for the first invocation. This will be used
-// to avoid duplicate checking.
-//
-// Checking of object files is optional because it is much slower. This allows
-// us to check targets for normal outputs, and then as a second pass check
-// object files (since we know it will be an error otherwise). This allows
-// us to avoid computing all object file names in the common case.
-bool EnsureFileIsGeneratedByDependency(const Target* target,
- const OutputFile& file,
- bool check_private_deps,
- bool consider_object_files,
- bool check_data_deps,
- std::set<const Target*>* seen_targets) {
- if (seen_targets->find(target) != seen_targets->end())
- return false; // Already checked this one and it's not found.
- seen_targets->insert(target);
-
- // Assume that we have relatively few generated inputs so brute-force
- // searching here is OK. If this becomes a bottleneck, consider storing
- // computed_outputs as a hash set.
- for (const OutputFile& cur : target->computed_outputs()) {
- if (file == cur)
- return true;
- }
-
- if (file == target->write_runtime_deps_output())
- return true;
-
- // Check binary target intermediate files if requested.
- if (consider_object_files && target->IsBinary()) {
- std::vector<OutputFile> source_outputs;
- for (const SourceFile& source : target->sources()) {
- Toolchain::ToolType tool_type;
- if (!target->GetOutputFilesForSource(source, &tool_type, &source_outputs))
- continue;
- if (base::ContainsValue(source_outputs, file))
- return true;
- }
- }
-
- if (check_data_deps) {
- check_data_deps = false; // Consider only direct data_deps.
- for (const auto& pair : target->data_deps()) {
- if (EnsureFileIsGeneratedByDependency(pair.ptr, file, false,
- consider_object_files,
- check_data_deps, seen_targets))
- return true; // Found a path.
- }
- }
-
- // Check all public dependencies (don't do data ones since those are
- // runtime-only).
- for (const auto& pair : target->public_deps()) {
- if (EnsureFileIsGeneratedByDependency(pair.ptr, file, false,
- consider_object_files,
- check_data_deps, seen_targets))
- return true; // Found a path.
- }
-
- // Only check private deps if requested.
- if (check_private_deps) {
- for (const auto& pair : target->private_deps()) {
- if (EnsureFileIsGeneratedByDependency(pair.ptr, file, false,
- consider_object_files,
- check_data_deps, seen_targets))
- return true; // Found a path.
- }
- if (target->output_type() == Target::CREATE_BUNDLE) {
- for (auto* dep : target->bundle_data().bundle_deps()) {
- if (EnsureFileIsGeneratedByDependency(dep, file, false,
- consider_object_files,
- check_data_deps, seen_targets))
- return true; // Found a path.
- }
- }
- }
- return false;
-}
-
-// check_this indicates if the given target should be matched against the
-// patterns. It should be set to false for the first call since assert_no_deps
-// shouldn't match the target itself.
-//
-// visited should point to an empty set, this will be used to prevent
-// multiple visits.
-//
-// *failure_path_str will be filled with a string describing the path of the
-// dependency failure, and failure_pattern will indicate the pattern in
-// assert_no that matched the target.
-//
-// Returns true if everything is OK. failure_path_str and failure_pattern_index
-// will be unchanged in this case.
-bool RecursiveCheckAssertNoDeps(const Target* target,
- bool check_this,
- const std::vector<LabelPattern>& assert_no,
- std::set<const Target*>* visited,
- std::string* failure_path_str,
- const LabelPattern** failure_pattern) {
- static const char kIndentPath[] = " ";
-
- if (visited->find(target) != visited->end())
- return true; // Already checked this target.
- visited->insert(target);
-
- if (check_this) {
- // Check this target against the given list of patterns.
- for (const LabelPattern& pattern : assert_no) {
- if (pattern.Matches(target->label())) {
- // Found a match.
- *failure_pattern = &pattern;
- *failure_path_str =
- kIndentPath + target->label().GetUserVisibleName(false);
- return false;
- }
- }
- }
-
- // Recursively check dependencies.
- for (const auto& pair : target->GetDeps(Target::DEPS_ALL)) {
- if (pair.ptr->output_type() == Target::EXECUTABLE)
- continue;
- if (!RecursiveCheckAssertNoDeps(pair.ptr, true, assert_no, visited,
- failure_path_str, failure_pattern)) {
- // To reconstruct the path, prepend the current target to the error.
- std::string prepend_path =
- kIndentPath + target->label().GetUserVisibleName(false) + " ->\n";
- failure_path_str->insert(0, prepend_path);
- return false;
- }
- }
-
- return true;
-}
-
-} // namespace
-
-const char kExecution_Help[] =
- R"(Build graph and execution overview
-
-Overall build flow
-
- 1. Look for ".gn" file (see "gn help dotfile") in the current directory and
- walk up the directory tree until one is found. Set this directory to be
- the "source root" and interpret this file to find the name of the build
- config file.
-
- 2. Execute the build config file identified by .gn to set up the global
- variables and default toolchain name. Any arguments, variables, defaults,
- etc. set up in this file will be visible to all files in the build.
-
- 3. Load the //BUILD.gn (in the source root directory).
-
- 4. Recursively evaluate rules and load BUILD.gn in other directories as
- necessary to resolve dependencies. If a BUILD file isn't found in the
- specified location, GN will look in the corresponding location inside
- the secondary_source defined in the dotfile (see "gn help dotfile").
-
- 5. When a target's dependencies are resolved, write out the `.ninja`
- file to disk.
-
- 6. When all targets are resolved, write out the root build.ninja file.
-
-Executing target definitions and templates
-
- Build files are loaded in parallel. This means it is impossible to
- interrogate a target from GN code for any information not derivable from its
- label (see "gn help label"). The exception is the get_target_outputs()
- function which requires the target being interrogated to have been defined
- previously in the same file.
-
- Targets are declared by their type and given a name:
-
- static_library("my_static_library") {
- ... target parameter definitions ...
- }
-
- There is also a generic "target" function for programmatically defined types
- (see "gn help target"). You can define new types using templates (see "gn
- help template"). A template defines some custom code that expands to one or
- more other targets.
-
- Before executing the code inside the target's { }, the target defaults are
- applied (see "gn help set_defaults"). It will inject implicit variable
- definitions that can be overridden by the target code as necessary. Typically
- this mechanism is used to inject a default set of configs that define the
- global compiler and linker flags.
-
-Which targets are built
-
- All targets encountered in the default toolchain (see "gn help toolchain")
- will have build rules generated for them, even if no other targets reference
- them. Their dependencies must resolve and they will be added to the implicit
- "all" rule (see "gn help ninja_rules").
-
- Targets in non-default toolchains will only be generated when they are
- required (directly or transitively) to build a target in the default
- toolchain.
-
- See also "gn help ninja_rules".
-
-Dependencies
-
- The only difference between "public_deps" and "deps" except for pushing
- configs around the build tree and allowing includes for the purposes of "gn
- check".
-
- A target's "data_deps" are guaranteed to be built whenever the target is
- built, but the ordering is not defined. The meaning of this is dependencies
- required at runtime. Currently data deps will be complete before the target
- is linked, but this is not semantically guaranteed and this is undesirable
- from a build performance perspective. Since we hope to change this in the
- future, do not rely on this behavior.
-)";
-
-Target::Target(const Settings* settings,
- const Label& label,
- const std::set<SourceFile>& build_dependency_files)
- : Item(settings, label, build_dependency_files),
- output_type_(UNKNOWN),
- output_prefix_override_(false),
- output_extension_set_(false),
- all_headers_public_(true),
- check_includes_(true),
- complete_static_lib_(false),
- testonly_(false),
- toolchain_(nullptr) {}
-
-Target::~Target() = default;
-
-// static
-const char* Target::GetStringForOutputType(OutputType type) {
- switch (type) {
- case UNKNOWN:
- return "unknown";
- case GROUP:
- return functions::kGroup;
- case EXECUTABLE:
- return functions::kExecutable;
- case LOADABLE_MODULE:
- return functions::kLoadableModule;
- case SHARED_LIBRARY:
- return functions::kSharedLibrary;
- case STATIC_LIBRARY:
- return functions::kStaticLibrary;
- case SOURCE_SET:
- return functions::kSourceSet;
- case COPY_FILES:
- return functions::kCopy;
- case ACTION:
- return functions::kAction;
- case ACTION_FOREACH:
- return functions::kActionForEach;
- case BUNDLE_DATA:
- return functions::kBundleData;
- case CREATE_BUNDLE:
- return functions::kCreateBundle;
- default:
- return "";
- }
-}
-
-Target* Target::AsTarget() {
- return this;
-}
-
-const Target* Target::AsTarget() const {
- return this;
-}
-
-bool Target::OnResolved(Err* err) {
- DCHECK(output_type_ != UNKNOWN);
- DCHECK(toolchain_) << "Toolchain should have been set before resolving.";
-
- ScopedTrace trace(TraceItem::TRACE_ON_RESOLVED, label());
- trace.SetToolchain(settings()->toolchain_label());
-
- // Copy this target's own dependent and public configs to the list of configs
- // applying to it.
- configs_.Append(all_dependent_configs_.begin(), all_dependent_configs_.end());
- MergePublicConfigsFrom(this, &configs_);
-
- // Copy public configs from all dependencies into the list of configs
- // applying to this target (configs_).
- PullDependentTargetConfigs();
-
- // Copies public dependencies' public configs to this target's public
- // configs. These configs have already been applied to this target by
- // PullDependentTargetConfigs above, along with the public configs from
- // private deps. This step re-exports them as public configs for targets that
- // depend on this one.
- for (const auto& dep : public_deps_) {
- if (dep.ptr->toolchain() == toolchain()) {
- public_configs_.Append(dep.ptr->public_configs().begin(),
- dep.ptr->public_configs().end());
- }
- }
-
- // Copy our own libs and lib_dirs to the final set. This will be from our
- // target and all of our configs. We do this specially since these must be
- // inherited through the dependency tree (other flags don't work this way).
- //
- // This needs to happen after we pull dependent target configs for the
- // public config's libs to be included here. And it needs to happen
- // before pulling the dependent target libs so the libs are in the correct
- // order (local ones first, then the dependency's).
- for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
- const ConfigValues& cur = iter.cur();
- all_lib_dirs_.append(cur.lib_dirs().begin(), cur.lib_dirs().end());
- all_libs_.append(cur.libs().begin(), cur.libs().end());
- }
-
- PullRecursiveBundleData();
- PullDependentTargetLibs();
- PullRecursiveHardDeps();
- if (!ResolvePrecompiledHeaders(err))
- return false;
-
- FillOutputFiles();
-
- if (!CheckVisibility(err))
- return false;
- if (!CheckTestonly(err))
- return false;
- if (!CheckAssertNoDeps(err))
- return false;
- CheckSourcesGenerated();
-
- if (!write_runtime_deps_output_.value().empty())
- g_scheduler->AddWriteRuntimeDepsTarget(this);
-
- return true;
-}
-
-bool Target::IsBinary() const {
- return output_type_ == EXECUTABLE ||
- output_type_ == SHARED_LIBRARY ||
- output_type_ == LOADABLE_MODULE ||
- output_type_ == STATIC_LIBRARY ||
- output_type_ == SOURCE_SET;
-}
-
-bool Target::IsLinkable() const {
- return output_type_ == STATIC_LIBRARY || output_type_ == SHARED_LIBRARY;
-}
-
-bool Target::IsFinal() const {
- return output_type_ == EXECUTABLE ||
- output_type_ == SHARED_LIBRARY ||
- output_type_ == LOADABLE_MODULE ||
- output_type_ == ACTION ||
- output_type_ == ACTION_FOREACH ||
- output_type_ == COPY_FILES ||
- output_type_ == CREATE_BUNDLE ||
- (output_type_ == STATIC_LIBRARY && complete_static_lib_);
-}
-
-DepsIteratorRange Target::GetDeps(DepsIterationType type) const {
- if (type == DEPS_LINKED) {
- return DepsIteratorRange(DepsIterator(
- &public_deps_, &private_deps_, nullptr));
- }
- // All deps.
- return DepsIteratorRange(DepsIterator(
- &public_deps_, &private_deps_, &data_deps_));
-}
-
-std::string Target::GetComputedOutputName() const {
- DCHECK(toolchain_)
- << "Toolchain must be specified before getting the computed output name.";
-
- const std::string& name = output_name_.empty() ? label().name()
- : output_name_;
-
- std::string result;
- const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this);
- if (tool) {
- // Only add the prefix if the name doesn't already have it and it's not
- // being overridden.
- if (!output_prefix_override_ &&
- !base::StartsWith(name, tool->output_prefix(),
- base::CompareCase::SENSITIVE))
- result = tool->output_prefix();
- }
- result.append(name);
- return result;
-}
-
-bool Target::SetToolchain(const Toolchain* toolchain, Err* err) {
- DCHECK(!toolchain_);
- DCHECK_NE(UNKNOWN, output_type_);
- toolchain_ = toolchain;
-
- const Tool* tool = toolchain->GetToolForTargetFinalOutput(this);
- if (tool)
- return true;
-
- // Tool not specified for this target type.
- if (err) {
- *err = Err(defined_from(), "This target uses an undefined tool.",
- base::StringPrintf(
- "The target %s\n"
- "of type \"%s\"\n"
- "uses toolchain %s\n"
- "which doesn't have the tool \"%s\" defined.\n\n"
- "Alas, I can not continue.",
- label().GetUserVisibleName(false).c_str(),
- GetStringForOutputType(output_type_),
- label().GetToolchainLabel().GetUserVisibleName(false).c_str(),
- Toolchain::ToolTypeToName(
- toolchain->GetToolTypeForTargetFinalOutput(this)).c_str()));
- }
- return false;
-}
-
-bool Target::GetOutputFilesForSource(const SourceFile& source,
- Toolchain::ToolType* computed_tool_type,
- std::vector<OutputFile>* outputs) const {
- outputs->clear();
- *computed_tool_type = Toolchain::TYPE_NONE;
-
- SourceFileType file_type = GetSourceFileType(source);
- if (file_type == SOURCE_UNKNOWN)
- return false;
- if (file_type == SOURCE_O) {
- // Object files just get passed to the output and not compiled.
- outputs->push_back(OutputFile(settings()->build_settings(), source));
- return true;
- }
-
- *computed_tool_type = toolchain_->GetToolTypeForSourceType(file_type);
- if (*computed_tool_type == Toolchain::TYPE_NONE)
- return false; // No tool for this file (it's a header file or something).
- const Tool* tool = toolchain_->GetTool(*computed_tool_type);
- if (!tool)
- return false; // Tool does not apply for this toolchain.file.
-
- // Figure out what output(s) this compiler produces.
- SubstitutionWriter::ApplyListToCompilerAsOutputFile(
- this, source, tool->outputs(), outputs);
- return !outputs->empty();
-}
-
-void Target::PullDependentTargetConfigs() {
- for (const auto& pair : GetDeps(DEPS_LINKED)) {
- if (pair.ptr->toolchain() == toolchain()) {
- MergeAllDependentConfigsFrom(pair.ptr, &configs_,
- &all_dependent_configs_);
- }
- }
- for (const auto& pair : GetDeps(DEPS_LINKED)) {
- if (pair.ptr->toolchain() == toolchain()) {
- MergePublicConfigsFrom(pair.ptr, &configs_);
- }
- }
-}
-
-void Target::PullDependentTargetLibsFrom(const Target* dep, bool is_public) {
- // Direct dependent libraries.
- if (dep->output_type() == STATIC_LIBRARY ||
- dep->output_type() == SHARED_LIBRARY ||
- dep->output_type() == SOURCE_SET)
- inherited_libraries_.Append(dep, is_public);
-
- if (dep->output_type() == SHARED_LIBRARY) {
- // Shared library dependendencies are inherited across public shared
- // library boundaries.
- //
- // In this case:
- // EXE -> INTERMEDIATE_SHLIB --[public]--> FINAL_SHLIB
- // The EXE will also link to to FINAL_SHLIB. The public dependeny means
- // that the EXE can use the headers in FINAL_SHLIB so the FINAL_SHLIB
- // will need to appear on EXE's link line.
- //
- // However, if the dependency is private:
- // EXE -> INTERMEDIATE_SHLIB --[private]--> FINAL_SHLIB
- // the dependency will not be propagated because INTERMEDIATE_SHLIB is
- // not granting permission to call functiosn from FINAL_SHLIB. If EXE
- // wants to use functions (and link to) FINAL_SHLIB, it will need to do
- // so explicitly.
- //
- // Static libraries and source sets aren't inherited across shared
- // library boundaries because they will be linked into the shared
- // library.
- inherited_libraries_.AppendPublicSharedLibraries(
- dep->inherited_libraries(), is_public);
- } else if (!dep->IsFinal()) {
- // The current target isn't linked, so propogate linked deps and
- // libraries up the dependency tree.
- inherited_libraries_.AppendInherited(dep->inherited_libraries(), is_public);
- } else if (dep->complete_static_lib()) {
- // Inherit only final targets through _complete_ static libraries.
- //
- // Inherited final libraries aren't linked into complete static libraries.
- // They are forwarded here so that targets that depend on complete
- // static libraries can link them in. Conversely, since complete static
- // libraries link in non-final targets they shouldn't be inherited.
- for (const auto& inherited :
- dep->inherited_libraries().GetOrderedAndPublicFlag()) {
- if (inherited.first->IsFinal()) {
- inherited_libraries_.Append(inherited.first,
- is_public && inherited.second);
- }
- }
- }
-
- // Library settings are always inherited across static library boundaries.
- if (!dep->IsFinal() || dep->output_type() == STATIC_LIBRARY) {
- all_lib_dirs_.append(dep->all_lib_dirs());
- all_libs_.append(dep->all_libs());
- }
-}
-
-void Target::PullDependentTargetLibs() {
- for (const auto& dep : public_deps_)
- PullDependentTargetLibsFrom(dep.ptr, true);
- for (const auto& dep : private_deps_)
- PullDependentTargetLibsFrom(dep.ptr, false);
-}
-
-void Target::PullRecursiveHardDeps() {
- for (const auto& pair : GetDeps(DEPS_LINKED)) {
- // Direct hard dependencies.
- if (hard_dep() || pair.ptr->hard_dep()) {
- recursive_hard_deps_.insert(pair.ptr);
- continue;
- }
-
- // If |pair.ptr| is binary target and |pair.ptr| has no public header,
- // |this| target does not need to have |pair.ptr|'s hard_deps as its
- // hard_deps to start compiles earlier.
- if (pair.ptr->IsBinary() && !pair.ptr->all_headers_public() &&
- pair.ptr->public_headers().empty()) {
- continue;
- }
-
- // Recursive hard dependencies of all dependencies.
- recursive_hard_deps_.insert(pair.ptr->recursive_hard_deps().begin(),
- pair.ptr->recursive_hard_deps().end());
- }
-}
-
-void Target::PullRecursiveBundleData() {
- for (const auto& pair : GetDeps(DEPS_LINKED)) {
- // Don't propagate bundle_data once they are added to a bundle.
- if (pair.ptr->output_type() == CREATE_BUNDLE)
- continue;
-
- // Don't propagate across toolchain.
- if (pair.ptr->toolchain() != toolchain())
- continue;
-
- // Direct dependency on a bundle_data target.
- if (pair.ptr->output_type() == BUNDLE_DATA)
- bundle_data_.AddBundleData(pair.ptr);
-
- // Recursive bundle_data informations from all dependencies.
- for (auto* target : pair.ptr->bundle_data().bundle_deps())
- bundle_data_.AddBundleData(target);
- }
-
- bundle_data_.OnTargetResolved(this);
-}
-
-void Target::FillOutputFiles() {
- const Tool* tool = toolchain_->GetToolForTargetFinalOutput(this);
- bool check_tool_outputs = false;
- switch (output_type_) {
- case GROUP:
- case BUNDLE_DATA:
- case CREATE_BUNDLE:
- case SOURCE_SET:
- case COPY_FILES:
- case ACTION:
- case ACTION_FOREACH: {
- // These don't get linked to and use stamps which should be the first
- // entry in the outputs. These stamps are named
- // "<target_out_dir>/<targetname>.stamp".
- dependency_output_file_ =
- GetBuildDirForTargetAsOutputFile(this, BuildDirType::OBJ);
- dependency_output_file_.value().append(GetComputedOutputName());
- dependency_output_file_.value().append(".stamp");
- break;
- }
- case EXECUTABLE:
- case LOADABLE_MODULE:
- // Executables and loadable modules don't get linked to, but the first
- // output is used for dependency management.
- CHECK_GE(tool->outputs().list().size(), 1u);
- check_tool_outputs = true;
- dependency_output_file_ =
- SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
- this, tool, tool->outputs().list()[0]);
-
- if (tool->runtime_outputs().list().empty()) {
- // Default to the first output for the runtime output.
- runtime_outputs_.push_back(dependency_output_file_);
- } else {
- SubstitutionWriter::ApplyListToLinkerAsOutputFile(
- this, tool, tool->runtime_outputs(), &runtime_outputs_);
- }
- break;
- case STATIC_LIBRARY:
- // Static libraries both have dependencies and linking going off of the
- // first output.
- CHECK(tool->outputs().list().size() >= 1);
- check_tool_outputs = true;
- link_output_file_ = dependency_output_file_ =
- SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
- this, tool, tool->outputs().list()[0]);
- break;
- case SHARED_LIBRARY:
- CHECK(tool->outputs().list().size() >= 1);
- check_tool_outputs = true;
- if (tool->link_output().empty() && tool->depend_output().empty()) {
- // Default behavior, use the first output file for both.
- link_output_file_ = dependency_output_file_ =
- SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
- this, tool, tool->outputs().list()[0]);
- } else {
- // Use the tool-specified ones.
- if (!tool->link_output().empty()) {
- link_output_file_ =
- SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
- this, tool, tool->link_output());
- }
- if (!tool->depend_output().empty()) {
- dependency_output_file_ =
- SubstitutionWriter::ApplyPatternToLinkerAsOutputFile(
- this, tool, tool->depend_output());
- }
- }
- if (tool->runtime_outputs().list().empty()) {
- // Default to the link output for the runtime output.
- runtime_outputs_.push_back(link_output_file_);
- } else {
- SubstitutionWriter::ApplyListToLinkerAsOutputFile(
- this, tool, tool->runtime_outputs(), &runtime_outputs_);
- }
- break;
- case UNKNOWN:
- default:
- NOTREACHED();
- }
-
- // Count anything generated from bundle_data dependencies.
- if (output_type_ == CREATE_BUNDLE)
- bundle_data_.GetOutputFiles(settings(), &computed_outputs_);
-
- // Count all outputs from this tool as something generated by this target.
- if (check_tool_outputs) {
- SubstitutionWriter::ApplyListToLinkerAsOutputFile(
- this, tool, tool->outputs(), &computed_outputs_);
-
- // Output names aren't canonicalized in the same way that source files
- // are. For example, the tool outputs often use
- // {{some_var}}/{{output_name}} which expands to "./foo", but this won't
- // match "foo" which is what we'll compute when converting a SourceFile to
- // an OutputFile.
- for (auto& out : computed_outputs_)
- NormalizePath(&out.value());
- }
-
- // Also count anything the target has declared to be an output.
- std::vector<SourceFile> outputs_as_sources;
- action_values_.GetOutputsAsSourceFiles(this, &outputs_as_sources);
- for (const SourceFile& out : outputs_as_sources)
- computed_outputs_.push_back(OutputFile(settings()->build_settings(), out));
-}
-
-bool Target::ResolvePrecompiledHeaders(Err* err) {
- // Precompiled headers are stored on a ConfigValues struct. This way, the
- // build can set all the precompiled header settings in a config and apply
- // it to many targets. Likewise, the precompiled header values may be
- // specified directly on a target.
- //
- // Unlike other values on configs which are lists that just get concatenated,
- // the precompiled header settings are unique values. We allow them to be
- // specified anywhere, but if they are specified in more than one place all
- // places must match.
-
- // Track where the current settings came from for issuing errors.
- const Label* pch_header_settings_from = NULL;
- if (config_values_.has_precompiled_headers())
- pch_header_settings_from = &label();
-
- for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
- if (!iter.GetCurrentConfig())
- continue; // Skip the one on the target itself.
-
- const Config* config = iter.GetCurrentConfig();
- const ConfigValues& cur = config->resolved_values();
- if (!cur.has_precompiled_headers())
- continue; // This one has no precompiled header info, skip.
-
- if (config_values_.has_precompiled_headers()) {
- // Already have a precompiled header values, the settings must match.
- if (config_values_.precompiled_header() != cur.precompiled_header() ||
- config_values_.precompiled_source() != cur.precompiled_source()) {
- *err = Err(defined_from(),
- "Precompiled header setting conflict.",
- "The target " + label().GetUserVisibleName(false) + "\n"
- "has conflicting precompiled header settings.\n"
- "\n"
- "From " + pch_header_settings_from->GetUserVisibleName(false) +
- "\n header: " + config_values_.precompiled_header() +
- "\n source: " + config_values_.precompiled_source().value() +
- "\n\n"
- "From " + config->label().GetUserVisibleName(false) +
- "\n header: " + cur.precompiled_header() +
- "\n source: " + cur.precompiled_source().value());
- return false;
- }
- } else {
- // Have settings from a config, apply them to ourselves.
- pch_header_settings_from = &config->label();
- config_values_.set_precompiled_header(cur.precompiled_header());
- config_values_.set_precompiled_source(cur.precompiled_source());
- }
- }
-
- return true;
-}
-
-bool Target::CheckVisibility(Err* err) const {
- for (const auto& pair : GetDeps(DEPS_ALL)) {
- if (!Visibility::CheckItemVisibility(this, pair.ptr, err))
- return false;
- }
- return true;
-}
-
-bool Target::CheckTestonly(Err* err) const {
- // If the current target is marked testonly, it can include both testonly
- // and non-testonly targets, so there's nothing to check.
- if (testonly())
- return true;
-
- // Verify no deps have "testonly" set.
- for (const auto& pair : GetDeps(DEPS_ALL)) {
- if (pair.ptr->testonly()) {
- *err = MakeTestOnlyError(this, pair.ptr);
- return false;
- }
- }
-
- return true;
-}
-
-bool Target::CheckAssertNoDeps(Err* err) const {
- if (assert_no_deps_.empty())
- return true;
-
- std::set<const Target*> visited;
- std::string failure_path_str;
- const LabelPattern* failure_pattern = nullptr;
-
- if (!RecursiveCheckAssertNoDeps(this, false, assert_no_deps_, &visited,
- &failure_path_str, &failure_pattern)) {
- *err = Err(defined_from(), "assert_no_deps failed.",
- label().GetUserVisibleName(false) +
- " has an assert_no_deps entry:\n " +
- failure_pattern->Describe() +
- "\nwhich fails for the dependency path:\n" +
- failure_path_str);
- return false;
- }
- return true;
-}
-
-void Target::CheckSourcesGenerated() const {
- // Checks that any inputs or sources to this target that are in the build
- // directory are generated by a target that this one transitively depends on
- // in some way. We already guarantee that all generated files are written
- // to the build dir.
- //
- // See Scheduler::AddUnknownGeneratedInput's declaration for more.
- for (const SourceFile& file : sources_)
- CheckSourceGenerated(file);
- for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
- for (const SourceFile& file : iter.cur().inputs())
- CheckSourceGenerated(file);
- }
- // TODO(agrieve): Check all_libs_ here as well (those that are source files).
- // http://crbug.com/571731
-}
-
-void Target::CheckSourceGenerated(const SourceFile& source) const {
- if (!IsStringInOutputDir(settings()->build_settings()->build_dir(),
- source.value()))
- return; // Not in output dir, this is OK.
-
- // Tell the scheduler about unknown files. This will be noted for later so
- // the list of files written by the GN build itself (often response files)
- // can be filtered out of this list.
- OutputFile out_file(settings()->build_settings(), source);
- std::set<const Target*> seen_targets;
- bool check_data_deps = false;
- bool consider_object_files = false;
- if (!EnsureFileIsGeneratedByDependency(this, out_file, true,
- consider_object_files, check_data_deps,
- &seen_targets)) {
- seen_targets.clear();
- // Allow dependency to be through data_deps for files generated by gn.
- check_data_deps = g_scheduler->IsFileGeneratedByWriteRuntimeDeps(out_file);
- // Check object files (much slower and very rare) only if the "normal"
- // output check failed.
- consider_object_files = !check_data_deps;
- if (!EnsureFileIsGeneratedByDependency(this, out_file, true,
- consider_object_files,
- check_data_deps, &seen_targets))
- g_scheduler->AddUnknownGeneratedInput(this, source);
- }
-}
diff --git a/chromium/tools/gn/target.h b/chromium/tools/gn/target.h
deleted file mode 100644
index ed8abd5145c..00000000000
--- a/chromium/tools/gn/target.h
+++ /dev/null
@@ -1,402 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_TARGET_H_
-#define TOOLS_GN_TARGET_H_
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/gtest_prod_util.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "tools/gn/action_values.h"
-#include "tools/gn/bundle_data.h"
-#include "tools/gn/config_values.h"
-#include "tools/gn/inherited_libraries.h"
-#include "tools/gn/item.h"
-#include "tools/gn/label_pattern.h"
-#include "tools/gn/label_ptr.h"
-#include "tools/gn/lib_file.h"
-#include "tools/gn/ordered_set.h"
-#include "tools/gn/output_file.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/toolchain.h"
-#include "tools/gn/unique_vector.h"
-
-class DepsIteratorRange;
-class Settings;
-class Toolchain;
-
-class Target : public Item {
- public:
- enum OutputType {
- UNKNOWN,
- GROUP,
- EXECUTABLE,
- SHARED_LIBRARY,
- LOADABLE_MODULE,
- STATIC_LIBRARY,
- SOURCE_SET,
- COPY_FILES,
- ACTION,
- ACTION_FOREACH,
- BUNDLE_DATA,
- CREATE_BUNDLE,
- };
-
- enum DepsIterationType {
- DEPS_ALL, // Iterates through all public, private, and data deps.
- DEPS_LINKED, // Iterates through all non-data dependencies.
- };
-
- typedef std::vector<SourceFile> FileList;
- typedef std::vector<std::string> StringVector;
-
- // We track the set of build files that may affect this target, please refer
- // to Scope for how this is determined.
- Target(const Settings* settings,
- const Label& label,
- const std::set<SourceFile>& build_dependency_files = {});
- ~Target() override;
-
- // Returns a string naming the output type.
- static const char* GetStringForOutputType(OutputType type);
-
- // Item overrides.
- Target* AsTarget() override;
- const Target* AsTarget() const override;
- bool OnResolved(Err* err) override;
-
- OutputType output_type() const { return output_type_; }
- void set_output_type(OutputType t) { output_type_ = t; }
-
- // True for targets that compile source code (all types of libaries and
- // executables).
- bool IsBinary() const;
-
- // Can be linked into other targets.
- bool IsLinkable() const;
-
- // True if the target links dependencies rather than propogated up the graph.
- // This is also true of action and copy steps even though they don't link
- // dependencies, because they also don't propogate libraries up.
- bool IsFinal() const;
-
- // Will be the empty string to use the target label as the output name.
- // See GetComputedOutputName().
- const std::string& output_name() const { return output_name_; }
- void set_output_name(const std::string& name) { output_name_ = name; }
-
- // Returns the output name for this target, which is the output_name if
- // specified, or the target label if not.
- //
- // Because this depends on the tool for this target, the toolchain must
- // have been set before calling.
- std::string GetComputedOutputName() const;
-
- bool output_prefix_override() const { return output_prefix_override_; }
- void set_output_prefix_override(bool prefix_override) {
- output_prefix_override_ = prefix_override;
- }
-
- // Desired output directory for the final output. This will be used for
- // the {{output_dir}} substitution in the tool if it is specified. If
- // is_null, the tool default will be used.
- const SourceDir& output_dir() const { return output_dir_; }
- void set_output_dir(const SourceDir& dir) { output_dir_ = dir; }
-
- // The output extension is really a tri-state: unset (output_extension_set
- // is false and the string is empty, meaning the default extension should be
- // used), the output extension is set but empty (output should have no
- // extension) and the output extension is set but nonempty (use the given
- // extension).
- const std::string& output_extension() const { return output_extension_; }
- void set_output_extension(const std::string& extension) {
- output_extension_ = extension;
- output_extension_set_ = true;
- }
- bool output_extension_set() const {
- return output_extension_set_;
- }
-
- const FileList& sources() const { return sources_; }
- FileList& sources() { return sources_; }
-
- // Set to true when all sources are public. This is the default. In this case
- // the public headers list should be empty.
- bool all_headers_public() const { return all_headers_public_; }
- void set_all_headers_public(bool p) { all_headers_public_ = p; }
-
- // When all_headers_public is false, this is the list of public headers. It
- // could be empty which would mean no headers are public.
- const FileList& public_headers() const { return public_headers_; }
- FileList& public_headers() { return public_headers_; }
-
- // Whether this target's includes should be checked by "gn check".
- bool check_includes() const { return check_includes_; }
- void set_check_includes(bool ci) { check_includes_ = ci; }
-
- // Whether this static_library target should have code linked in.
- bool complete_static_lib() const { return complete_static_lib_; }
- void set_complete_static_lib(bool complete) {
- DCHECK_EQ(STATIC_LIBRARY, output_type_);
- complete_static_lib_ = complete;
- }
-
- bool testonly() const { return testonly_; }
- void set_testonly(bool value) { testonly_ = value; }
-
- OutputFile write_runtime_deps_output() const {
- return write_runtime_deps_output_;
- }
- void set_write_runtime_deps_output(const OutputFile& value) {
- write_runtime_deps_output_ = value;
- }
-
- // Runtime dependencies. These are "file-like things" that can either be
- // directories or files. They do not need to exist, these are just passed as
- // runtime dependencies to external test systems as necessary.
- const std::vector<std::string>& data() const { return data_; }
- std::vector<std::string>& data() { return data_; }
-
- // Information about the bundle. Only valid for CREATE_BUNDLE target after
- // they have been resolved.
- const BundleData& bundle_data() const { return bundle_data_; }
- BundleData& bundle_data() { return bundle_data_; }
-
- // Returns true if targets depending on this one should have an order
- // dependency.
- bool hard_dep() const {
- return output_type_ == ACTION || output_type_ == ACTION_FOREACH ||
- output_type_ == COPY_FILES || output_type_ == CREATE_BUNDLE ||
- output_type_ == BUNDLE_DATA;
- }
-
- // Returns the iterator range which can be used in range-based for loops
- // to iterate over multiple types of deps in one loop:
- // for (const auto& pair : target->GetDeps(Target::DEPS_ALL)) ...
- DepsIteratorRange GetDeps(DepsIterationType type) const;
-
- // Linked private dependencies.
- const LabelTargetVector& private_deps() const { return private_deps_; }
- LabelTargetVector& private_deps() { return private_deps_; }
-
- // Linked public dependencies.
- const LabelTargetVector& public_deps() const { return public_deps_; }
- LabelTargetVector& public_deps() { return public_deps_; }
-
- // Non-linked dependencies.
- const LabelTargetVector& data_deps() const { return data_deps_; }
- LabelTargetVector& data_deps() { return data_deps_; }
-
- // List of configs that this class inherits settings from. Once a target is
- // resolved, this will also list all-dependent and public configs.
- const UniqueVector<LabelConfigPair>& configs() const { return configs_; }
- UniqueVector<LabelConfigPair>& configs() { return configs_; }
-
- // List of configs that all dependencies (direct and indirect) of this
- // target get. These configs are not added to this target. Note that due
- // to the way this is computed, there may be duplicates in this list.
- const UniqueVector<LabelConfigPair>& all_dependent_configs() const {
- return all_dependent_configs_;
- }
- UniqueVector<LabelConfigPair>& all_dependent_configs() {
- return all_dependent_configs_;
- }
-
- // List of configs that targets depending directly on this one get. These
- // configs are also added to this target.
- const UniqueVector<LabelConfigPair>& public_configs() const {
- return public_configs_;
- }
- UniqueVector<LabelConfigPair>& public_configs() {
- return public_configs_;
- }
-
- // Dependencies that can include files from this target.
- const std::set<Label>& allow_circular_includes_from() const {
- return allow_circular_includes_from_;
- }
- std::set<Label>& allow_circular_includes_from() {
- return allow_circular_includes_from_;
- }
-
- const InheritedLibraries& inherited_libraries() const {
- return inherited_libraries_;
- }
-
- // This config represents the configuration set directly on this target.
- ConfigValues& config_values() { return config_values_; }
- const ConfigValues& config_values() const { return config_values_; }
-
- ActionValues& action_values() { return action_values_; }
- const ActionValues& action_values() const { return action_values_; }
-
- const OrderedSet<SourceDir>& all_lib_dirs() const { return all_lib_dirs_; }
- const OrderedSet<LibFile>& all_libs() const { return all_libs_; }
-
- const std::set<const Target*>& recursive_hard_deps() const {
- return recursive_hard_deps_;
- }
-
- std::vector<LabelPattern>& friends() { return friends_; }
- const std::vector<LabelPattern>& friends() const { return friends_; }
-
- std::vector<LabelPattern>& assert_no_deps() { return assert_no_deps_; }
- const std::vector<LabelPattern>& assert_no_deps() const {
- return assert_no_deps_;
- }
-
- // The toolchain is only known once this target is resolved (all if its
- // dependencies are known). They will be null until then. Generally, this can
- // only be used during target writing.
- const Toolchain* toolchain() const { return toolchain_; }
-
- // Sets the toolchain. The toolchain must include a tool for this target
- // or the error will be set and the function will return false. Unusually,
- // this function's "err" output is optional since this is commonly used
- // frequently by unit tests which become needlessly verbose.
- bool SetToolchain(const Toolchain* toolchain, Err* err = nullptr);
-
- // Once this target has been resolved, all outputs from the target will be
- // listed here. This will include things listed in the "outputs" for an
- // action or a copy step, and the output library or executable file(s) from
- // binary targets.
- //
- // It will NOT include stamp files and object files.
- const std::vector<OutputFile>& computed_outputs() const {
- return computed_outputs_;
- }
-
- // Returns outputs from this target. The link output file is the one that
- // other targets link to when they depend on this target. This will only be
- // valid for libraries and will be empty for all other target types.
- //
- // The dependency output file is the file that should be used to express
- // a dependency on this one. It could be the same as the link output file
- // (this will be the case for static libraries). For shared libraries it
- // could be the same or different than the link output file, depending on the
- // system. For actions this will be the stamp file.
- //
- // These are only known once the target is resolved and will be empty before
- // that. This is a cache of the files to prevent every target that depends on
- // a given library from recomputing the same pattern.
- const OutputFile& link_output_file() const {
- return link_output_file_;
- }
- const OutputFile& dependency_output_file() const {
- return dependency_output_file_;
- }
-
- // The subset of computed_outputs that are considered runtime outputs.
- const std::vector<OutputFile>& runtime_outputs() const {
- return runtime_outputs_;
- }
-
- // Computes the set of output files resulting from compiling the given source
- // file. If the file can be compiled and the tool exists, fills the outputs
- // in and writes the tool type to computed_tool_type. If the file is not
- // compilable, returns false.
- //
- // The function can succeed with a "NONE" tool type for object files which
- // are just passed to the output. The output will always be overwritten, not
- // appended to.
- bool GetOutputFilesForSource(const SourceFile& source,
- Toolchain::ToolType* computed_tool_type,
- std::vector<OutputFile>* outputs) const;
-
- private:
- FRIEND_TEST_ALL_PREFIXES(TargetTest, ResolvePrecompiledHeaders);
-
- // Pulls necessary information from dependencies to this one when all
- // dependencies have been resolved.
- void PullDependentTargetConfigs();
- void PullDependentTargetLibsFrom(const Target* dep, bool is_public);
- void PullDependentTargetLibs();
- void PullRecursiveHardDeps();
- void PullRecursiveBundleData();
-
- // Fills the link and dependency output files when a target is resolved.
- void FillOutputFiles();
-
- // Checks precompiled headers from configs and makes sure the resulting
- // values are in config_values_.
- bool ResolvePrecompiledHeaders(Err* err);
-
- // Validates the given thing when a target is resolved.
- bool CheckVisibility(Err* err) const;
- bool CheckTestonly(Err* err) const;
- bool CheckAssertNoDeps(Err* err) const;
- void CheckSourcesGenerated() const;
- void CheckSourceGenerated(const SourceFile& source) const;
-
- OutputType output_type_;
- std::string output_name_;
- bool output_prefix_override_;
- SourceDir output_dir_;
- std::string output_extension_;
- bool output_extension_set_;
-
- FileList sources_;
- bool all_headers_public_;
- FileList public_headers_;
- bool check_includes_;
- bool complete_static_lib_;
- bool testonly_;
- std::vector<std::string> data_;
- BundleData bundle_data_;
- OutputFile write_runtime_deps_output_;
-
- LabelTargetVector private_deps_;
- LabelTargetVector public_deps_;
- LabelTargetVector data_deps_;
-
- // See getters for more info.
- UniqueVector<LabelConfigPair> configs_;
- UniqueVector<LabelConfigPair> all_dependent_configs_;
- UniqueVector<LabelConfigPair> public_configs_;
-
- std::set<Label> allow_circular_includes_from_;
-
- // Static libraries, shared libraries, and source sets from transitive deps
- // that need to be linked.
- InheritedLibraries inherited_libraries_;
-
- // These libs and dirs are inherited from statically linked deps and all
- // configs applying to this target.
- OrderedSet<SourceDir> all_lib_dirs_;
- OrderedSet<LibFile> all_libs_;
-
- // All hard deps from this target and all dependencies. Filled in when this
- // target is marked resolved. This will not include the current target.
- std::set<const Target*> recursive_hard_deps_;
-
- std::vector<LabelPattern> friends_;
- std::vector<LabelPattern> assert_no_deps_;
-
- // Used for all binary targets, and for inputs in regular targets. The
- // precompiled header values in this struct will be resolved to the ones to
- // use for this target, if precompiled headers are used.
- ConfigValues config_values_;
-
- // Used for action[_foreach] targets.
- ActionValues action_values_;
-
- // Toolchain used by this target. Null until target is resolved.
- const Toolchain* toolchain_;
-
- // Output files. Empty until the target is resolved.
- std::vector<OutputFile> computed_outputs_;
- OutputFile link_output_file_;
- OutputFile dependency_output_file_;
- std::vector<OutputFile> runtime_outputs_;
-
- DISALLOW_COPY_AND_ASSIGN(Target);
-};
-
-extern const char kExecution_Help[];
-
-#endif // TOOLS_GN_TARGET_H_
diff --git a/chromium/tools/gn/target_generator.cc b/chromium/tools/gn/target_generator.cc
deleted file mode 100644
index ab8572975d8..00000000000
--- a/chromium/tools/gn/target_generator.cc
+++ /dev/null
@@ -1,392 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/target_generator.h"
-
-#include <stddef.h>
-
-#include <memory>
-#include <utility>
-
-#include "tools/gn/action_target_generator.h"
-#include "tools/gn/binary_target_generator.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/bundle_data_target_generator.h"
-#include "tools/gn/config.h"
-#include "tools/gn/copy_target_generator.h"
-#include "tools/gn/create_bundle_target_generator.h"
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/group_target_generator.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/token.h"
-#include "tools/gn/value.h"
-#include "tools/gn/value_extractors.h"
-#include "tools/gn/variables.h"
-
-TargetGenerator::TargetGenerator(Target* target,
- Scope* scope,
- const FunctionCallNode* function_call,
- Err* err)
- : target_(target),
- scope_(scope),
- function_call_(function_call),
- err_(err) {
-}
-
-TargetGenerator::~TargetGenerator() = default;
-
-void TargetGenerator::Run() {
- // All target types use these.
- if (!FillDependentConfigs())
- return;
-
- if (!FillData())
- return;
-
- if (!FillDependencies())
- return;
-
- if (!FillTestonly())
- return;
-
- if (!FillAssertNoDeps())
- return;
-
- if (!Visibility::FillItemVisibility(target_, scope_, err_))
- return;
-
- if (!FillWriteRuntimeDeps())
- return;
-
- // Do type-specific generation.
- DoRun();
-}
-
-// static
-void TargetGenerator::GenerateTarget(Scope* scope,
- const FunctionCallNode* function_call,
- const std::vector<Value>& args,
- const std::string& output_type,
- Err* err) {
- // Name is the argument to the function.
- if (args.size() != 1u || args[0].type() != Value::STRING) {
- *err = Err(function_call,
- "Target generator requires one string argument.",
- "Otherwise I'm not sure what to call this target.");
- return;
- }
-
- // The location of the target is the directory name with no slash at the end.
- // FIXME(brettw) validate name.
- const Label& toolchain_label = ToolchainLabelForScope(scope);
- Label label(scope->GetSourceDir(), args[0].string_value(),
- toolchain_label.dir(), toolchain_label.name());
-
- if (g_scheduler->verbose_logging())
- g_scheduler->Log("Defining target", label.GetUserVisibleName(true));
-
- std::unique_ptr<Target> target = std::make_unique<Target>(
- scope->settings(), label, scope->build_dependency_files());
- target->set_defined_from(function_call);
-
- // Create and call out to the proper generator.
- if (output_type == functions::kBundleData) {
- BundleDataTargetGenerator generator(
- target.get(), scope, function_call, err);
- generator.Run();
- } else if (output_type == functions::kCreateBundle) {
- CreateBundleTargetGenerator generator(target.get(), scope, function_call,
- err);
- generator.Run();
- } else if (output_type == functions::kCopy) {
- CopyTargetGenerator generator(target.get(), scope, function_call, err);
- generator.Run();
- } else if (output_type == functions::kAction) {
- ActionTargetGenerator generator(target.get(), scope, function_call,
- Target::ACTION, err);
- generator.Run();
- } else if (output_type == functions::kActionForEach) {
- ActionTargetGenerator generator(target.get(), scope, function_call,
- Target::ACTION_FOREACH, err);
- generator.Run();
- } else if (output_type == functions::kExecutable) {
- BinaryTargetGenerator generator(target.get(), scope, function_call,
- Target::EXECUTABLE, err);
- generator.Run();
- } else if (output_type == functions::kGroup) {
- GroupTargetGenerator generator(target.get(), scope, function_call, err);
- generator.Run();
- } else if (output_type == functions::kLoadableModule) {
- BinaryTargetGenerator generator(target.get(), scope, function_call,
- Target::LOADABLE_MODULE, err);
- generator.Run();
- } else if (output_type == functions::kSharedLibrary) {
- BinaryTargetGenerator generator(target.get(), scope, function_call,
- Target::SHARED_LIBRARY, err);
- generator.Run();
- } else if (output_type == functions::kSourceSet) {
- BinaryTargetGenerator generator(target.get(), scope, function_call,
- Target::SOURCE_SET, err);
- generator.Run();
- } else if (output_type == functions::kStaticLibrary) {
- BinaryTargetGenerator generator(target.get(), scope, function_call,
- Target::STATIC_LIBRARY, err);
- generator.Run();
- } else {
- *err = Err(function_call, "Not a known target type",
- "I am very confused by the target type \"" + output_type + "\"");
- }
-
- if (err->has_error())
- return;
-
- // Save this target for the file.
- Scope::ItemVector* collector = scope->GetItemCollector();
- if (!collector) {
- *err = Err(function_call, "Can't define a target in this context.");
- return;
- }
- collector->push_back(std::move(target));
-}
-
-const BuildSettings* TargetGenerator::GetBuildSettings() const {
- return scope_->settings()->build_settings();
-}
-
-bool TargetGenerator::FillSources() {
- const Value* value = scope_->GetValue(variables::kSources, true);
- if (!value)
- return true;
-
- Target::FileList dest_sources;
- if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
- scope_->GetSourceDir(), &dest_sources, err_))
- return false;
- target_->sources().swap(dest_sources);
- return true;
-}
-
-bool TargetGenerator::FillPublic() {
- const Value* value = scope_->GetValue(variables::kPublic, true);
- if (!value)
- return true;
-
- // If the public headers are defined, don't default to public.
- target_->set_all_headers_public(false);
-
- Target::FileList dest_public;
- if (!ExtractListOfRelativeFiles(scope_->settings()->build_settings(), *value,
- scope_->GetSourceDir(), &dest_public, err_))
- return false;
- target_->public_headers().swap(dest_public);
- return true;
-}
-
-bool TargetGenerator::FillConfigs() {
- return FillGenericConfigs(variables::kConfigs, &target_->configs());
-}
-
-bool TargetGenerator::FillDependentConfigs() {
- if (!FillGenericConfigs(variables::kAllDependentConfigs,
- &target_->all_dependent_configs()))
- return false;
-
- if (!FillGenericConfigs(variables::kPublicConfigs,
- &target_->public_configs()))
- return false;
-
- return true;
-}
-
-bool TargetGenerator::FillData() {
- const Value* value = scope_->GetValue(variables::kData, true);
- if (!value)
- return true;
- if (!value->VerifyTypeIs(Value::LIST, err_))
- return false;
-
- const std::vector<Value>& input_list = value->list_value();
- std::vector<std::string>& output_list = target_->data();
- output_list.reserve(input_list.size());
-
- const SourceDir& dir = scope_->GetSourceDir();
- const std::string& root_path =
- scope_->settings()->build_settings()->root_path_utf8();
-
- for (size_t i = 0; i < input_list.size(); i++) {
- const Value& input = input_list[i];
- if (!input.VerifyTypeIs(Value::STRING, err_))
- return false;
- const std::string input_str = input.string_value();
-
- // Treat each input as either a file or a directory, depending on the
- // last character.
- bool as_dir = !input_str.empty() && input_str[input_str.size() - 1] == '/';
-
- std::string resolved =
- dir.ResolveRelativeAs(!as_dir, input, err_, root_path, &input_str);
- if (err_->has_error())
- return false;
-
- output_list.push_back(resolved);
- }
- return true;
-}
-
-bool TargetGenerator::FillDependencies() {
- if (!FillGenericDeps(variables::kDeps, &target_->private_deps()))
- return false;
- if (!FillGenericDeps(variables::kPublicDeps, &target_->public_deps()))
- return false;
- if (!FillGenericDeps(variables::kDataDeps, &target_->data_deps()))
- return false;
-
- // "data_deps" was previously named "datadeps". For backwards-compat, read
- // the old one if no "data_deps" were specified.
- if (!scope_->GetValue(variables::kDataDeps, false)) {
- if (!FillGenericDeps("datadeps", &target_->data_deps()))
- return false;
- }
-
- return true;
-}
-
-bool TargetGenerator::FillTestonly() {
- const Value* value = scope_->GetValue(variables::kTestonly, true);
- if (value) {
- if (!value->VerifyTypeIs(Value::BOOLEAN, err_))
- return false;
- target_->set_testonly(value->boolean_value());
- }
- return true;
-}
-
-bool TargetGenerator::FillAssertNoDeps() {
- const Value* value = scope_->GetValue(variables::kAssertNoDeps, true);
- if (value) {
- return ExtractListOfLabelPatterns(*value, scope_->GetSourceDir(),
- &target_->assert_no_deps(), err_);
- }
- return true;
-}
-
-bool TargetGenerator::FillOutputs(bool allow_substitutions) {
- const Value* value = scope_->GetValue(variables::kOutputs, true);
- if (!value)
- return true;
-
- SubstitutionList& outputs = target_->action_values().outputs();
- if (!outputs.Parse(*value, err_))
- return false;
-
- if (!allow_substitutions) {
- // Verify no substitutions were actually used.
- if (!outputs.required_types().empty()) {
- *err_ = Err(*value, "Source expansions not allowed here.",
- "The outputs of this target used source {{expansions}} but this "
- "target type\ndoesn't support them. Just express the outputs "
- "literally.");
- return false;
- }
- }
-
- // Check the substitutions used are valid for this purpose.
- if (!EnsureValidSubstitutions(outputs.required_types(),
- &IsValidSourceSubstitution,
- value->origin(), err_))
- return false;
-
- // Validate that outputs are in the output dir.
- CHECK(outputs.list().size() == value->list_value().size());
- for (size_t i = 0; i < outputs.list().size(); i++) {
- if (!EnsureSubstitutionIsInOutputDir(outputs.list()[i],
- value->list_value()[i]))
- return false;
- }
- return true;
-}
-
-bool TargetGenerator::FillCheckIncludes() {
- const Value* value = scope_->GetValue(variables::kCheckIncludes, true);
- if (!value)
- return true;
- if (!value->VerifyTypeIs(Value::BOOLEAN, err_))
- return false;
- target_->set_check_includes(value->boolean_value());
- return true;
-}
-
-bool TargetGenerator::EnsureSubstitutionIsInOutputDir(
- const SubstitutionPattern& pattern,
- const Value& original_value) {
- if (pattern.ranges().empty()) {
- // Pattern is empty, error out (this prevents weirdness below).
- *err_ = Err(original_value, "This has an empty value in it.");
- return false;
- }
-
- if (pattern.ranges()[0].type == SUBSTITUTION_LITERAL) {
- // If the first thing is a literal, it must start with the output dir.
- if (!EnsureStringIsInOutputDir(
- GetBuildSettings()->build_dir(),
- pattern.ranges()[0].literal, original_value.origin(), err_))
- return false;
- } else {
- // Otherwise, the first subrange must be a pattern that expands to
- // something in the output directory.
- if (!SubstitutionIsInOutputDir(pattern.ranges()[0].type)) {
- *err_ = Err(original_value,
- "File is not inside output directory.",
- "The given file should be in the output directory. Normally you\n"
- "would specify\n\"$target_out_dir/foo\" or "
- "\"{{source_gen_dir}}/foo\".");
- return false;
- }
- }
-
- return true;
-}
-
-bool TargetGenerator::FillGenericConfigs(const char* var_name,
- UniqueVector<LabelConfigPair>* dest) {
- const Value* value = scope_->GetValue(var_name, true);
- if (value) {
- ExtractListOfUniqueLabels(*value, scope_->GetSourceDir(),
- ToolchainLabelForScope(scope_), dest, err_);
- }
- return !err_->has_error();
-}
-
-bool TargetGenerator::FillGenericDeps(const char* var_name,
- LabelTargetVector* dest) {
- const Value* value = scope_->GetValue(var_name, true);
- if (value) {
- ExtractListOfLabels(*value, scope_->GetSourceDir(),
- ToolchainLabelForScope(scope_), dest, err_);
- }
- return !err_->has_error();
-}
-
-bool TargetGenerator::FillWriteRuntimeDeps() {
- const Value* value = scope_->GetValue(variables::kWriteRuntimeDeps, true);
- if (!value)
- return true;
-
- // Compute the file name and make sure it's in the output dir.
- SourceFile source_file = scope_->GetSourceDir().ResolveRelativeFile(
- *value, err_, GetBuildSettings()->root_path_utf8());
- if (err_->has_error())
- return false;
- if (!EnsureStringIsInOutputDir(GetBuildSettings()->build_dir(),
- source_file.value(), value->origin(), err_))
- return false;
- OutputFile output_file(GetBuildSettings(), source_file);
- target_->set_write_runtime_deps_output(output_file);
-
- return true;
-}
diff --git a/chromium/tools/gn/target_generator.h b/chromium/tools/gn/target_generator.h
deleted file mode 100644
index 549f2cd14c7..00000000000
--- a/chromium/tools/gn/target_generator.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_TARGET_GENERATOR_H_
-#define TOOLS_GN_TARGET_GENERATOR_H_
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "tools/gn/label_ptr.h"
-#include "tools/gn/unique_vector.h"
-
-class BuildSettings;
-class Err;
-class FunctionCallNode;
-class Scope;
-class SubstitutionPattern;
-class Value;
-
-// Fills the variables in a Target object from a Scope (the result of a script
-// execution). Target-type-specific derivations of this class will be used
-// for each different type of function call. This class implements the common
-// behavior.
-class TargetGenerator {
- public:
- TargetGenerator(Target* target,
- Scope* scope,
- const FunctionCallNode* function_call,
- Err* err);
- virtual ~TargetGenerator();
-
- void Run();
-
- // The function call is the parse tree node that invoked the target.
- // err() will be set on failure.
- static void GenerateTarget(Scope* scope,
- const FunctionCallNode* function_call,
- const std::vector<Value>& args,
- const std::string& output_type,
- Err* err);
-
- protected:
- // Derived classes implement this to do type-specific generation.
- virtual void DoRun() = 0;
-
- const BuildSettings* GetBuildSettings() const;
-
- bool FillSources();
- bool FillPublic();
- bool FillConfigs();
- bool FillOutputs(bool allow_substitutions);
- bool FillCheckIncludes();
-
- // Rrturns true if the given pattern will expand to a file in the output
- // directory. If not, returns false and sets the error, blaming the given
- // Value.
- bool EnsureSubstitutionIsInOutputDir(const SubstitutionPattern& pattern,
- const Value& original_value);
-
- Target* target_;
- Scope* scope_;
- const FunctionCallNode* function_call_;
- Err* err_;
-
- private:
- bool FillDependentConfigs(); // Includes all types of dependent configs.
- bool FillData();
- bool FillDependencies(); // Includes data dependencies.
- bool FillTestonly();
- bool FillAssertNoDeps();
- bool FillWriteRuntimeDeps();
-
- // Reads configs/deps from the given var name, and uses the given setting on
- // the target to save them.
- bool FillGenericConfigs(const char* var_name,
- UniqueVector<LabelConfigPair>* dest);
- bool FillGenericDeps(const char* var_name, LabelTargetVector* dest);
-
- DISALLOW_COPY_AND_ASSIGN(TargetGenerator);
-};
-
-#endif // TOOLS_GN_TARGET_GENERATOR_H_
diff --git a/chromium/tools/gn/target_unittest.cc b/chromium/tools/gn/target_unittest.cc
deleted file mode 100644
index 31d3382406f..00000000000
--- a/chromium/tools/gn/target_unittest.cc
+++ /dev/null
@@ -1,1051 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/target.h"
-
-#include <memory>
-#include <utility>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/config.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/test_with_scheduler.h"
-#include "tools/gn/test_with_scope.h"
-#include "tools/gn/toolchain.h"
-
-namespace {
-
-// Asserts that the current global scheduler has a single unknown generated
-// file with the given name from the given target.
-void AssertSchedulerHasOneUnknownFileMatching(const Target* target,
- const SourceFile& file) {
- auto unknown = g_scheduler->GetUnknownGeneratedInputs();
- ASSERT_EQ(1u, unknown.size()); // Should be one unknown file.
- auto found = unknown.find(file);
- ASSERT_TRUE(found != unknown.end()) << file.value();
- EXPECT_TRUE(target == found->second)
- << "Target doesn't match. Expected\n "
- << target->label().GetUserVisibleName(false)
- << "\nBut got\n " << found->second->label().GetUserVisibleName(false);
-}
-
-} // namespace
-
-using TargetTest = TestWithScheduler;
-
-// Tests that lib[_dir]s are inherited across deps boundaries for static
-// libraries but not executables.
-TEST_F(TargetTest, LibInheritance) {
- TestWithScope setup;
- Err err;
-
- const LibFile lib("foo");
- const SourceDir libdir("/foo_dir/");
-
- // Leaf target with ldflags set.
- TestTarget z(setup, "//foo:z", Target::STATIC_LIBRARY);
- z.config_values().libs().push_back(lib);
- z.config_values().lib_dirs().push_back(libdir);
- ASSERT_TRUE(z.OnResolved(&err));
-
- // All lib[_dir]s should be set when target is resolved.
- ASSERT_EQ(1u, z.all_libs().size());
- EXPECT_EQ(lib, z.all_libs()[0]);
- ASSERT_EQ(1u, z.all_lib_dirs().size());
- EXPECT_EQ(libdir, z.all_lib_dirs()[0]);
-
- // Shared library target should inherit the libs from the static library
- // and its own. Its own flag should be before the inherited one.
- const LibFile second_lib("bar");
- const SourceDir second_libdir("/bar_dir/");
- TestTarget shared(setup, "//foo:shared", Target::SHARED_LIBRARY);
- shared.config_values().libs().push_back(second_lib);
- shared.config_values().lib_dirs().push_back(second_libdir);
- shared.private_deps().push_back(LabelTargetPair(&z));
- ASSERT_TRUE(shared.OnResolved(&err));
-
- ASSERT_EQ(2u, shared.all_libs().size());
- EXPECT_EQ(second_lib, shared.all_libs()[0]);
- EXPECT_EQ(lib, shared.all_libs()[1]);
- ASSERT_EQ(2u, shared.all_lib_dirs().size());
- EXPECT_EQ(second_libdir, shared.all_lib_dirs()[0]);
- EXPECT_EQ(libdir, shared.all_lib_dirs()[1]);
-
- // Executable target shouldn't get either by depending on shared.
- TestTarget exec(setup, "//foo:exec", Target::EXECUTABLE);
- exec.private_deps().push_back(LabelTargetPair(&shared));
- ASSERT_TRUE(exec.OnResolved(&err));
- EXPECT_EQ(0u, exec.all_libs().size());
- EXPECT_EQ(0u, exec.all_lib_dirs().size());
-}
-
-// Test all_dependent_configs and public_config inheritance.
-TEST_F(TargetTest, DependentConfigs) {
- TestWithScope setup;
- Err err;
-
- // Set up a dependency chain of a -> b -> c
- TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
- TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
- TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
- a.private_deps().push_back(LabelTargetPair(&b));
- b.private_deps().push_back(LabelTargetPair(&c));
-
- // Normal non-inherited config.
- Config config(setup.settings(), Label(SourceDir("//foo/"), "config"));
- ASSERT_TRUE(config.OnResolved(&err));
- c.configs().push_back(LabelConfigPair(&config));
-
- // All dependent config.
- Config all(setup.settings(), Label(SourceDir("//foo/"), "all"));
- ASSERT_TRUE(all.OnResolved(&err));
- c.all_dependent_configs().push_back(LabelConfigPair(&all));
-
- // Direct dependent config.
- Config direct(setup.settings(), Label(SourceDir("//foo/"), "direct"));
- ASSERT_TRUE(direct.OnResolved(&err));
- c.public_configs().push_back(LabelConfigPair(&direct));
-
- ASSERT_TRUE(c.OnResolved(&err));
- ASSERT_TRUE(b.OnResolved(&err));
- ASSERT_TRUE(a.OnResolved(&err));
-
- // B should have gotten both dependent configs from C.
- ASSERT_EQ(2u, b.configs().size());
- EXPECT_EQ(&all, b.configs()[0].ptr);
- EXPECT_EQ(&direct, b.configs()[1].ptr);
- ASSERT_EQ(1u, b.all_dependent_configs().size());
- EXPECT_EQ(&all, b.all_dependent_configs()[0].ptr);
-
- // A should have just gotten the "all" dependent config from C.
- ASSERT_EQ(1u, a.configs().size());
- EXPECT_EQ(&all, a.configs()[0].ptr);
- EXPECT_EQ(&all, a.all_dependent_configs()[0].ptr);
-
- // Making an an alternate A and B with B forwarding the direct dependents.
- TestTarget a_fwd(setup, "//foo:a_fwd", Target::EXECUTABLE);
- TestTarget b_fwd(setup, "//foo:b_fwd", Target::STATIC_LIBRARY);
- a_fwd.private_deps().push_back(LabelTargetPair(&b_fwd));
- b_fwd.private_deps().push_back(LabelTargetPair(&c));
-
- ASSERT_TRUE(b_fwd.OnResolved(&err));
- ASSERT_TRUE(a_fwd.OnResolved(&err));
-
- // A_fwd should now have both configs.
- ASSERT_EQ(1u, a_fwd.configs().size());
- EXPECT_EQ(&all, a_fwd.configs()[0].ptr);
- ASSERT_EQ(1u, a_fwd.all_dependent_configs().size());
- EXPECT_EQ(&all, a_fwd.all_dependent_configs()[0].ptr);
-}
-
-// Tests that dependent configs don't propagate between toolchains.
-TEST_F(TargetTest, NoDependentConfigsBetweenToolchains) {
- TestWithScope setup;
- Err err;
-
- // Create another toolchain.
- Toolchain other_toolchain(setup.settings(),
- Label(SourceDir("//other/"), "toolchain"));
- TestWithScope::SetupToolchain(&other_toolchain);
-
- // Set up a dependency chain of |a| -> |b| -> |c| where |a| has a different
- // toolchain.
- Target a(setup.settings(),
- Label(SourceDir("//foo/"), "a", other_toolchain.label().dir(),
- other_toolchain.label().name()));
- a.set_output_type(Target::EXECUTABLE);
- EXPECT_TRUE(a.SetToolchain(&other_toolchain, &err));
- TestTarget b(setup, "//foo:b", Target::EXECUTABLE);
- TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
- a.private_deps().push_back(LabelTargetPair(&b));
- b.private_deps().push_back(LabelTargetPair(&c));
-
- // All dependent config.
- Config all_dependent(setup.settings(), Label(SourceDir("//foo/"), "all"));
- ASSERT_TRUE(all_dependent.OnResolved(&err));
- c.all_dependent_configs().push_back(LabelConfigPair(&all_dependent));
-
- // Public config.
- Config public_config(setup.settings(), Label(SourceDir("//foo/"), "public"));
- ASSERT_TRUE(public_config.OnResolved(&err));
- c.public_configs().push_back(LabelConfigPair(&public_config));
-
- // Another public config.
- Config public_config2(setup.settings(),
- Label(SourceDir("//foo/"), "public2"));
- ASSERT_TRUE(public_config2.OnResolved(&err));
- b.public_configs().push_back(LabelConfigPair(&public_config2));
-
- ASSERT_TRUE(c.OnResolved(&err));
- ASSERT_TRUE(b.OnResolved(&err));
- ASSERT_TRUE(a.OnResolved(&err));
-
- // B should have gotten the configs from C.
- ASSERT_EQ(3u, b.configs().size());
- EXPECT_EQ(&public_config2, b.configs()[0].ptr);
- EXPECT_EQ(&all_dependent, b.configs()[1].ptr);
- EXPECT_EQ(&public_config, b.configs()[2].ptr);
- ASSERT_EQ(1u, b.all_dependent_configs().size());
- EXPECT_EQ(&all_dependent, b.all_dependent_configs()[0].ptr);
-
- // A should not have gotten any configs from B or C.
- ASSERT_EQ(0u, a.configs().size());
- ASSERT_EQ(0u, a.all_dependent_configs().size());
-}
-
-TEST_F(TargetTest, InheritLibs) {
- TestWithScope setup;
- Err err;
-
- // Create a dependency chain:
- // A (executable) -> B (shared lib) -> C (static lib) -> D (source set)
- TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
- TestTarget b(setup, "//foo:b", Target::SHARED_LIBRARY);
- TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
- TestTarget d(setup, "//foo:d", Target::SOURCE_SET);
- a.private_deps().push_back(LabelTargetPair(&b));
- b.private_deps().push_back(LabelTargetPair(&c));
- c.private_deps().push_back(LabelTargetPair(&d));
-
- ASSERT_TRUE(d.OnResolved(&err));
- ASSERT_TRUE(c.OnResolved(&err));
- ASSERT_TRUE(b.OnResolved(&err));
- ASSERT_TRUE(a.OnResolved(&err));
-
- // C should have D in its inherited libs.
- std::vector<const Target*> c_inherited = c.inherited_libraries().GetOrdered();
- ASSERT_EQ(1u, c_inherited.size());
- EXPECT_EQ(&d, c_inherited[0]);
-
- // B should have C and D in its inherited libs.
- std::vector<const Target*> b_inherited = b.inherited_libraries().GetOrdered();
- ASSERT_EQ(2u, b_inherited.size());
- EXPECT_EQ(&c, b_inherited[0]);
- EXPECT_EQ(&d, b_inherited[1]);
-
- // A should have B in its inherited libs, but not any others (the shared
- // library will include the static library and source set).
- std::vector<const Target*> a_inherited = a.inherited_libraries().GetOrdered();
- ASSERT_EQ(1u, a_inherited.size());
- EXPECT_EQ(&b, a_inherited[0]);
-}
-
-TEST_F(TargetTest, InheritCompleteStaticLib) {
- TestWithScope setup;
- Err err;
-
- // Create a dependency chain:
- // A (executable) -> B (complete static lib) -> C (source set)
- TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
- TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
- b.set_complete_static_lib(true);
-
- const LibFile lib("foo");
- const SourceDir lib_dir("/foo_dir/");
- TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
- c.config_values().libs().push_back(lib);
- c.config_values().lib_dirs().push_back(lib_dir);
-
- a.public_deps().push_back(LabelTargetPair(&b));
- b.public_deps().push_back(LabelTargetPair(&c));
-
- ASSERT_TRUE(c.OnResolved(&err));
- ASSERT_TRUE(b.OnResolved(&err));
- ASSERT_TRUE(a.OnResolved(&err));
-
- // B should have C in its inherited libs.
- std::vector<const Target*> b_inherited = b.inherited_libraries().GetOrdered();
- ASSERT_EQ(1u, b_inherited.size());
- EXPECT_EQ(&c, b_inherited[0]);
-
- // A should have B in its inherited libs, but not any others (the complete
- // static library will include the source set).
- std::vector<const Target*> a_inherited = a.inherited_libraries().GetOrdered();
- ASSERT_EQ(1u, a_inherited.size());
- EXPECT_EQ(&b, a_inherited[0]);
-
- // A should inherit the libs and lib_dirs from the C.
- ASSERT_EQ(1u, a.all_libs().size());
- EXPECT_EQ(lib, a.all_libs()[0]);
- ASSERT_EQ(1u, a.all_lib_dirs().size());
- EXPECT_EQ(lib_dir, a.all_lib_dirs()[0]);
-}
-
-TEST_F(TargetTest, InheritCompleteStaticLibStaticLibDeps) {
- TestWithScope setup;
- Err err;
-
- // Create a dependency chain:
- // A (executable) -> B (complete static lib) -> C (static lib)
- TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
- TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
- b.set_complete_static_lib(true);
- TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
- a.public_deps().push_back(LabelTargetPair(&b));
- b.public_deps().push_back(LabelTargetPair(&c));
-
- ASSERT_TRUE(c.OnResolved(&err));
- ASSERT_TRUE(b.OnResolved(&err));
- ASSERT_TRUE(a.OnResolved(&err));
-
- // B should have C in its inherited libs.
- std::vector<const Target*> b_inherited = b.inherited_libraries().GetOrdered();
- ASSERT_EQ(1u, b_inherited.size());
- EXPECT_EQ(&c, b_inherited[0]);
-
- // A should have B in its inherited libs, but not any others (the complete
- // static library will include the static library).
- std::vector<const Target*> a_inherited = a.inherited_libraries().GetOrdered();
- ASSERT_EQ(1u, a_inherited.size());
- EXPECT_EQ(&b, a_inherited[0]);
-}
-
-TEST_F(TargetTest, InheritCompleteStaticLibInheritedCompleteStaticLibDeps) {
- TestWithScope setup;
- Err err;
-
- // Create a dependency chain:
- // A (executable) -> B (complete static lib) -> C (complete static lib)
- TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
- TestTarget b(setup, "//foo:b", Target::STATIC_LIBRARY);
- b.set_complete_static_lib(true);
- TestTarget c(setup, "//foo:c", Target::STATIC_LIBRARY);
- c.set_complete_static_lib(true);
-
- a.private_deps().push_back(LabelTargetPair(&b));
- b.private_deps().push_back(LabelTargetPair(&c));
-
- ASSERT_TRUE(c.OnResolved(&err));
- ASSERT_TRUE(b.OnResolved(&err));
- ASSERT_TRUE(a.OnResolved(&err));
-
- // B should have C in its inherited libs.
- std::vector<const Target*> b_inherited = b.inherited_libraries().GetOrdered();
- ASSERT_EQ(1u, b_inherited.size());
- EXPECT_EQ(&c, b_inherited[0]);
-
- // A should have B and C in its inherited libs.
- std::vector<const Target*> a_inherited = a.inherited_libraries().GetOrdered();
- ASSERT_EQ(2u, a_inherited.size());
- EXPECT_EQ(&b, a_inherited[0]);
- EXPECT_EQ(&c, a_inherited[1]);
-}
-
-TEST_F(TargetTest, NoActionDepPropgation) {
- TestWithScope setup;
- Err err;
-
- // Create a dependency chain:
- // A (exe) -> B (action) -> C (source_set)
- {
- TestTarget a(setup, "//foo:a", Target::EXECUTABLE);
- TestTarget b(setup, "//foo:b", Target::ACTION);
- TestTarget c(setup, "//foo:c", Target::SOURCE_SET);
-
- a.private_deps().push_back(LabelTargetPair(&b));
- b.private_deps().push_back(LabelTargetPair(&c));
-
- ASSERT_TRUE(c.OnResolved(&err));
- ASSERT_TRUE(b.OnResolved(&err));
- ASSERT_TRUE(a.OnResolved(&err));
-
- // The executable should not have inherited the source set across the
- // action.
- std::vector<const Target*> libs = a.inherited_libraries().GetOrdered();
- ASSERT_TRUE(libs.empty());
- }
-}
-
-TEST_F(TargetTest, GetComputedOutputName) {
- TestWithScope setup;
- Err err;
-
- // Basic target with no prefix (executable type tool in the TestWithScope has
- // no prefix) or output name.
- TestTarget basic(setup, "//foo:bar", Target::EXECUTABLE);
- ASSERT_TRUE(basic.OnResolved(&err));
- EXPECT_EQ("bar", basic.GetComputedOutputName());
-
- // Target with no prefix but an output name.
- TestTarget with_name(setup, "//foo:bar", Target::EXECUTABLE);
- with_name.set_output_name("myoutput");
- ASSERT_TRUE(with_name.OnResolved(&err));
- EXPECT_EQ("myoutput", with_name.GetComputedOutputName());
-
- // Target with a "lib" prefix (the static library tool in the TestWithScope
- // should specify a "lib" output prefix).
- TestTarget with_prefix(setup, "//foo:bar", Target::STATIC_LIBRARY);
- ASSERT_TRUE(with_prefix.OnResolved(&err));
- EXPECT_EQ("libbar", with_prefix.GetComputedOutputName());
-
- // Target with a "lib" prefix that already has it applied. The prefix should
- // not duplicate something already in the target name.
- TestTarget dup_prefix(setup, "//foo:bar", Target::STATIC_LIBRARY);
- dup_prefix.set_output_name("libbar");
- ASSERT_TRUE(dup_prefix.OnResolved(&err));
- EXPECT_EQ("libbar", dup_prefix.GetComputedOutputName());
-
- // Target with an output prefix override should not have a prefix.
- TestTarget override_prefix(setup, "//foo:bar", Target::SHARED_LIBRARY);
- override_prefix.set_output_prefix_override(true);
- ASSERT_TRUE(dup_prefix.OnResolved(&err));
- EXPECT_EQ("bar", override_prefix.GetComputedOutputName());
-}
-
-// Test visibility failure case.
-TEST_F(TargetTest, VisibilityFails) {
- TestWithScope setup;
- Err err;
-
- TestTarget b(setup, "//private:b", Target::STATIC_LIBRARY);
- b.visibility().SetPrivate(b.label().dir());
- ASSERT_TRUE(b.OnResolved(&err));
-
- // Make a target depending on "b". The dependency must have an origin to mark
- // it as user-set so we check visibility. This check should fail.
- TestTarget a(setup, "//app:a", Target::EXECUTABLE);
- a.private_deps().push_back(LabelTargetPair(&b));
- IdentifierNode origin; // Dummy origin.
- a.private_deps()[0].origin = &origin;
- ASSERT_FALSE(a.OnResolved(&err));
-}
-
-// Test visibility with a single data_dep.
-TEST_F(TargetTest, VisibilityDatadeps) {
- TestWithScope setup;
- Err err;
-
- TestTarget b(setup, "//public:b", Target::STATIC_LIBRARY);
- ASSERT_TRUE(b.OnResolved(&err));
-
- // Make a target depending on "b". The dependency must have an origin to mark
- // it as user-set so we check visibility. This check should fail.
- TestTarget a(setup, "//app:a", Target::EXECUTABLE);
- a.data_deps().push_back(LabelTargetPair(&b));
- IdentifierNode origin; // Dummy origin.
- a.data_deps()[0].origin = &origin;
- ASSERT_TRUE(a.OnResolved(&err)) << err.help_text();
-}
-
-// Tests that A -> Group -> B where the group is visible from A but B isn't,
-// passes visibility even though the group's deps get expanded into A.
-TEST_F(TargetTest, VisibilityGroup) {
- TestWithScope setup;
- Err err;
-
- IdentifierNode origin; // Dummy origin.
-
- // B has private visibility. This lets the group see it since the group is in
- // the same directory.
- TestTarget b(setup, "//private:b", Target::STATIC_LIBRARY);
- b.visibility().SetPrivate(b.label().dir());
- ASSERT_TRUE(b.OnResolved(&err));
-
- // The group has public visibility and depends on b.
- TestTarget g(setup, "//public:g", Target::GROUP);
- g.private_deps().push_back(LabelTargetPair(&b));
- g.private_deps()[0].origin = &origin;
- ASSERT_TRUE(b.OnResolved(&err));
-
- // Make a target depending on "g". This should succeed.
- TestTarget a(setup, "//app:a", Target::EXECUTABLE);
- a.private_deps().push_back(LabelTargetPair(&g));
- a.private_deps()[0].origin = &origin;
- ASSERT_TRUE(a.OnResolved(&err));
-}
-
-// Verifies that only testonly targets can depend on other testonly targets.
-// Many of the above dependency checking cases covered the non-testonly
-// case.
-TEST_F(TargetTest, Testonly) {
- TestWithScope setup;
- Err err;
-
- // "testlib" is a test-only library.
- TestTarget testlib(setup, "//test:testlib", Target::STATIC_LIBRARY);
- testlib.set_testonly(true);
- ASSERT_TRUE(testlib.OnResolved(&err));
-
- // "test" is a test-only executable depending on testlib, this is OK.
- TestTarget test(setup, "//test:test", Target::EXECUTABLE);
- test.set_testonly(true);
- test.private_deps().push_back(LabelTargetPair(&testlib));
- ASSERT_TRUE(test.OnResolved(&err));
-
- // "product" is a non-test depending on testlib. This should fail.
- TestTarget product(setup, "//app:product", Target::EXECUTABLE);
- product.set_testonly(false);
- product.private_deps().push_back(LabelTargetPair(&testlib));
- ASSERT_FALSE(product.OnResolved(&err));
-}
-
-TEST_F(TargetTest, PublicConfigs) {
- TestWithScope setup;
- Err err;
-
- Label pub_config_label(SourceDir("//a/"), "pubconfig");
- Config pub_config(setup.settings(), pub_config_label);
- LibFile lib_name("testlib");
- pub_config.own_values().libs().push_back(lib_name);
- ASSERT_TRUE(pub_config.OnResolved(&err));
-
- // This is the destination target that has a public config.
- TestTarget dest(setup, "//a:a", Target::SOURCE_SET);
- dest.public_configs().push_back(LabelConfigPair(&pub_config));
- ASSERT_TRUE(dest.OnResolved(&err));
-
- // This target has a public dependency on dest.
- TestTarget pub(setup, "//a:pub", Target::SOURCE_SET);
- pub.public_deps().push_back(LabelTargetPair(&dest));
- ASSERT_TRUE(pub.OnResolved(&err));
-
- // Depending on the target with the public dependency should forward dest's
- // to the current target.
- TestTarget dep_on_pub(setup, "//a:dop", Target::SOURCE_SET);
- dep_on_pub.private_deps().push_back(LabelTargetPair(&pub));
- ASSERT_TRUE(dep_on_pub.OnResolved(&err));
- ASSERT_EQ(1u, dep_on_pub.configs().size());
- EXPECT_EQ(&pub_config, dep_on_pub.configs()[0].ptr);
-
- // Libs have special handling, check that they were forwarded from the
- // public config to all_libs.
- ASSERT_EQ(1u, dep_on_pub.all_libs().size());
- ASSERT_EQ(lib_name, dep_on_pub.all_libs()[0]);
-
- // This target has a private dependency on dest for forwards configs.
- TestTarget forward(setup, "//a:f", Target::SOURCE_SET);
- forward.private_deps().push_back(LabelTargetPair(&dest));
- ASSERT_TRUE(forward.OnResolved(&err));
-}
-
-// Tests that configs are ordered properly between local and pulled ones.
-TEST_F(TargetTest, ConfigOrdering) {
- TestWithScope setup;
- Err err;
-
- // Make Dep1. It has all_dependent_configs and public_configs.
- TestTarget dep1(setup, "//:dep1", Target::SOURCE_SET);
- Label dep1_all_config_label(SourceDir("//"), "dep1_all_config");
- Config dep1_all_config(setup.settings(), dep1_all_config_label);
- ASSERT_TRUE(dep1_all_config.OnResolved(&err));
- dep1.all_dependent_configs().push_back(LabelConfigPair(&dep1_all_config));
-
- Label dep1_public_config_label(SourceDir("//"), "dep1_public_config");
- Config dep1_public_config(setup.settings(), dep1_public_config_label);
- ASSERT_TRUE(dep1_public_config.OnResolved(&err));
- dep1.public_configs().push_back(LabelConfigPair(&dep1_public_config));
- ASSERT_TRUE(dep1.OnResolved(&err));
-
- // Make Dep2 with the same structure.
- TestTarget dep2(setup, "//:dep2", Target::SOURCE_SET);
- Label dep2_all_config_label(SourceDir("//"), "dep2_all_config");
- Config dep2_all_config(setup.settings(), dep2_all_config_label);
- ASSERT_TRUE(dep2_all_config.OnResolved(&err));
- dep2.all_dependent_configs().push_back(LabelConfigPair(&dep2_all_config));
-
- Label dep2_public_config_label(SourceDir("//"), "dep2_public_config");
- Config dep2_public_config(setup.settings(), dep2_public_config_label);
- ASSERT_TRUE(dep2_public_config.OnResolved(&err));
- dep2.public_configs().push_back(LabelConfigPair(&dep2_public_config));
- ASSERT_TRUE(dep2.OnResolved(&err));
-
- // This target depends on both previous targets.
- TestTarget target(setup, "//:foo", Target::SOURCE_SET);
- target.private_deps().push_back(LabelTargetPair(&dep1));
- target.private_deps().push_back(LabelTargetPair(&dep2));
-
- // It also has a private and public config.
- Label public_config_label(SourceDir("//"), "public");
- Config public_config(setup.settings(), public_config_label);
- ASSERT_TRUE(public_config.OnResolved(&err));
- target.public_configs().push_back(LabelConfigPair(&public_config));
-
- Label private_config_label(SourceDir("//"), "private");
- Config private_config(setup.settings(), private_config_label);
- ASSERT_TRUE(private_config.OnResolved(&err));
- target.configs().push_back(LabelConfigPair(&private_config));
-
- // Resolve to get the computed list of configs applying.
- ASSERT_TRUE(target.OnResolved(&err));
- const auto& computed = target.configs();
-
- // Order should be:
- // 1. local private
- // 2. local public
- // 3. inherited all dependent
- // 4. inherited public
- ASSERT_EQ(6u, computed.size());
- EXPECT_EQ(private_config_label, computed[0].label);
- EXPECT_EQ(public_config_label, computed[1].label);
- EXPECT_EQ(dep1_all_config_label, computed[2].label);
- EXPECT_EQ(dep2_all_config_label, computed[3].label);
- EXPECT_EQ(dep1_public_config_label, computed[4].label);
- EXPECT_EQ(dep2_public_config_label, computed[5].label);
-}
-
-// Tests that different link/depend outputs work for solink tools.
-TEST_F(TargetTest, LinkAndDepOutputs) {
- TestWithScope setup;
- Err err;
-
- Toolchain toolchain(setup.settings(), Label(SourceDir("//tc/"), "tc"));
-
- std::unique_ptr<Tool> solink_tool = std::make_unique<Tool>();
- solink_tool->set_output_prefix("lib");
- solink_tool->set_default_output_extension(".so");
-
- const char kLinkPattern[] =
- "{{root_out_dir}}/{{target_output_name}}{{output_extension}}";
- SubstitutionPattern link_output = SubstitutionPattern::MakeForTest(
- kLinkPattern);
- solink_tool->set_link_output(link_output);
-
- const char kDependPattern[] =
- "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.TOC";
- SubstitutionPattern depend_output = SubstitutionPattern::MakeForTest(
- kDependPattern);
- solink_tool->set_depend_output(depend_output);
-
- solink_tool->set_outputs(SubstitutionList::MakeForTest(
- kLinkPattern, kDependPattern));
-
- toolchain.SetTool(Toolchain::TYPE_SOLINK, std::move(solink_tool));
-
- Target target(setup.settings(), Label(SourceDir("//a/"), "a"));
- target.set_output_type(Target::SHARED_LIBRARY);
- target.SetToolchain(&toolchain);
- ASSERT_TRUE(target.OnResolved(&err));
-
- EXPECT_EQ("./liba.so", target.link_output_file().value());
- EXPECT_EQ("./liba.so.TOC", target.dependency_output_file().value());
-
- ASSERT_EQ(1u, target.runtime_outputs().size());
- EXPECT_EQ("./liba.so", target.runtime_outputs()[0].value());
-}
-
-// Tests that runtime_outputs works without an explicit link_output for
-// solink tools.
-TEST_F(TargetTest, RuntimeOuputs) {
- TestWithScope setup;
- Err err;
-
- Toolchain toolchain(setup.settings(), Label(SourceDir("//tc/"), "tc"));
-
- std::unique_ptr<Tool> solink_tool = std::make_unique<Tool>();
- solink_tool->set_output_prefix("");
- solink_tool->set_default_output_extension(".dll");
-
- // Say the linker makes a DLL< an import library, and a symbol file we want
- // to treat as a runtime output.
- const char kLibPattern[] =
- "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.lib";
- const char kDllPattern[] =
- "{{root_out_dir}}/{{target_output_name}}{{output_extension}}";
- const char kPdbPattern[] =
- "{{root_out_dir}}/{{target_output_name}}.pdb";
- SubstitutionPattern pdb_pattern =
- SubstitutionPattern::MakeForTest(kPdbPattern);
-
- solink_tool->set_outputs(
- SubstitutionList::MakeForTest(kLibPattern, kDllPattern, kPdbPattern));
-
- // Say we only want the DLL and symbol file treaded as runtime outputs.
- solink_tool->set_runtime_outputs(SubstitutionList::MakeForTest(
- kDllPattern, kPdbPattern));
-
- toolchain.SetTool(Toolchain::TYPE_SOLINK, std::move(solink_tool));
-
- Target target(setup.settings(), Label(SourceDir("//a/"), "a"));
- target.set_output_type(Target::SHARED_LIBRARY);
- target.SetToolchain(&toolchain);
- ASSERT_TRUE(target.OnResolved(&err));
-
- EXPECT_EQ("./a.dll.lib", target.link_output_file().value());
- EXPECT_EQ("./a.dll.lib", target.dependency_output_file().value());
-
- ASSERT_EQ(2u, target.runtime_outputs().size());
- EXPECT_EQ("./a.dll", target.runtime_outputs()[0].value());
- EXPECT_EQ("./a.pdb", target.runtime_outputs()[1].value());
-}
-
-// Shared libraries should be inherited across public shared liobrary
-// boundaries.
-TEST_F(TargetTest, SharedInheritance) {
- TestWithScope setup;
- Err err;
-
- // Create two leaf shared libraries.
- TestTarget pub(setup, "//foo:pub", Target::SHARED_LIBRARY);
- ASSERT_TRUE(pub.OnResolved(&err));
-
- TestTarget priv(setup, "//foo:priv", Target::SHARED_LIBRARY);
- ASSERT_TRUE(priv.OnResolved(&err));
-
- // Intermediate shared library with the leaf shared libraries as
- // dependencies, one public, one private.
- TestTarget inter(setup, "//foo:inter", Target::SHARED_LIBRARY);
- inter.public_deps().push_back(LabelTargetPair(&pub));
- inter.private_deps().push_back(LabelTargetPair(&priv));
- ASSERT_TRUE(inter.OnResolved(&err));
-
- // The intermediate shared library should have both "pub" and "priv" in its
- // inherited libraries.
- std::vector<const Target*> inter_inherited =
- inter.inherited_libraries().GetOrdered();
- ASSERT_EQ(2u, inter_inherited.size());
- EXPECT_EQ(&pub, inter_inherited[0]);
- EXPECT_EQ(&priv, inter_inherited[1]);
-
- // Make a toplevel executable target depending on the intermediate one.
- TestTarget exe(setup, "//foo:exe", Target::SHARED_LIBRARY);
- exe.private_deps().push_back(LabelTargetPair(&inter));
- ASSERT_TRUE(exe.OnResolved(&err));
-
- // The exe's inherited libraries should be "inter" (because it depended
- // directly on it) and "pub" (because inter depended publicly on it).
- std::vector<const Target*> exe_inherited =
- exe.inherited_libraries().GetOrdered();
- ASSERT_EQ(2u, exe_inherited.size());
- EXPECT_EQ(&inter, exe_inherited[0]);
- EXPECT_EQ(&pub, exe_inherited[1]);
-}
-
-TEST_F(TargetTest, GeneratedInputs) {
- TestWithScope setup;
- Err err;
-
- SourceFile generated_file("//out/Debug/generated.cc");
-
- // This target has a generated input and no dependency makes it.
- TestTarget non_existent_generator(setup, "//foo:non_existent_generator",
- Target::EXECUTABLE);
- non_existent_generator.sources().push_back(generated_file);
- EXPECT_TRUE(non_existent_generator.OnResolved(&err)) << err.message();
- AssertSchedulerHasOneUnknownFileMatching(&non_existent_generator,
- generated_file);
- scheduler().ClearUnknownGeneratedInputsAndWrittenFiles();
-
- // Make a target that generates the file.
- TestTarget generator(setup, "//foo:generator", Target::ACTION);
- generator.action_values().outputs() =
- SubstitutionList::MakeForTest(generated_file.value().c_str());
- err = Err();
- EXPECT_TRUE(generator.OnResolved(&err)) << err.message();
-
- // A target that depends on the generator that uses the file as a source
- // should be OK. This uses a private dep (will be used later).
- TestTarget existent_generator(setup, "//foo:existent_generator",
- Target::SHARED_LIBRARY);
- existent_generator.sources().push_back(generated_file);
- existent_generator.private_deps().push_back(LabelTargetPair(&generator));
- EXPECT_TRUE(existent_generator.OnResolved(&err)) << err.message();
- EXPECT_TRUE(scheduler().GetUnknownGeneratedInputs().empty());
-
- // A target that depends on the previous one should *not* be allowed to
- // use the generated file, because existent_generator used private deps.
- // This is:
- // indirect_private --> existent_generator --[private]--> generator
- TestTarget indirect_private(setup, "//foo:indirect_private",
- Target::EXECUTABLE);
- indirect_private.sources().push_back(generated_file);
- indirect_private.public_deps().push_back(
- LabelTargetPair(&existent_generator));
- EXPECT_TRUE(indirect_private.OnResolved(&err));
- AssertSchedulerHasOneUnknownFileMatching(&indirect_private, generated_file);
- scheduler().ClearUnknownGeneratedInputsAndWrittenFiles();
-
- // Now make a chain like the above but with all public deps, it should be OK.
- TestTarget existent_public(setup, "//foo:existent_public",
- Target::SHARED_LIBRARY);
- existent_public.public_deps().push_back(LabelTargetPair(&generator));
- EXPECT_TRUE(existent_public.OnResolved(&err)) << err.message();
- TestTarget indirect_public(setup, "//foo:indirect_public",
- Target::EXECUTABLE);
- indirect_public.sources().push_back(generated_file);
- indirect_public.public_deps().push_back(LabelTargetPair(&existent_public));
- EXPECT_TRUE(indirect_public.OnResolved(&err)) << err.message();
- EXPECT_TRUE(scheduler().GetUnknownGeneratedInputs().empty());
-}
-
-// This is sort of a Scheduler test, but is related to the above test more.
-TEST_F(TargetTest, WriteFileGeneratedInputs) {
- TestWithScope setup;
- Err err;
-
- SourceFile generated_file("//out/Debug/generated.data");
-
- // This target has a generated input and no dependency makes it.
- TestTarget non_existent_generator(setup, "//foo:non_existent_generator",
- Target::EXECUTABLE);
- non_existent_generator.sources().push_back(generated_file);
- EXPECT_TRUE(non_existent_generator.OnResolved(&err));
- AssertSchedulerHasOneUnknownFileMatching(&non_existent_generator,
- generated_file);
- scheduler().ClearUnknownGeneratedInputsAndWrittenFiles();
-
- // This target has a generated file and we've decared we write it.
- TestTarget existent_generator(setup, "//foo:existent_generator",
- Target::EXECUTABLE);
- existent_generator.sources().push_back(generated_file);
- EXPECT_TRUE(existent_generator.OnResolved(&err));
- scheduler().AddWrittenFile(generated_file);
-
- // Should be OK.
- EXPECT_TRUE(scheduler().GetUnknownGeneratedInputs().empty());
-}
-
-TEST_F(TargetTest, WriteRuntimeDepsGeneratedInputs) {
- TestWithScope setup;
- Err err;
-
- SourceFile source_file("//out/Debug/generated.runtime_deps");
- OutputFile output_file(setup.build_settings(), source_file);
-
- TestTarget generator(setup, "//foo:generator", Target::EXECUTABLE);
- generator.set_write_runtime_deps_output(output_file);
- g_scheduler->AddWriteRuntimeDepsTarget(&generator);
-
- TestTarget middle_data_dep(setup, "//foo:middle", Target::EXECUTABLE);
- middle_data_dep.data_deps().push_back(LabelTargetPair(&generator));
-
- // This target has a generated input and no dependency makes it.
- TestTarget dep_missing(setup, "//foo:no_dep", Target::EXECUTABLE);
- dep_missing.sources().push_back(source_file);
- EXPECT_TRUE(dep_missing.OnResolved(&err));
- AssertSchedulerHasOneUnknownFileMatching(&dep_missing, source_file);
- scheduler().ClearUnknownGeneratedInputsAndWrittenFiles();
-
- // This target has a generated file and we've directly dependended on it.
- TestTarget dep_present(setup, "//foo:with_dep", Target::EXECUTABLE);
- dep_present.sources().push_back(source_file);
- dep_present.private_deps().push_back(LabelTargetPair(&generator));
- EXPECT_TRUE(dep_present.OnResolved(&err));
- EXPECT_TRUE(scheduler().GetUnknownGeneratedInputs().empty());
-
- // This target has a generated file and we've indirectly dependended on it
- // via data_deps.
- TestTarget dep_indirect(setup, "//foo:with_dep", Target::EXECUTABLE);
- dep_indirect.sources().push_back(source_file);
- dep_indirect.data_deps().push_back(LabelTargetPair(&middle_data_dep));
- EXPECT_TRUE(dep_indirect.OnResolved(&err));
- AssertSchedulerHasOneUnknownFileMatching(&dep_indirect, source_file);
- scheduler().ClearUnknownGeneratedInputsAndWrittenFiles();
-
- // This target has a generated file and we've directly dependended on it
- // via data_deps.
- TestTarget data_dep_present(setup, "//foo:with_dep", Target::EXECUTABLE);
- data_dep_present.sources().push_back(source_file);
- data_dep_present.data_deps().push_back(LabelTargetPair(&generator));
- EXPECT_TRUE(data_dep_present.OnResolved(&err));
- EXPECT_TRUE(scheduler().GetUnknownGeneratedInputs().empty());
-}
-
-// Tests that intermediate object files generated by binary targets are also
-// considered generated for the purposes of input checking. Above, we tested
-// the failure cases for generated inputs, so here only test .o files that are
-// present.
-TEST_F(TargetTest, ObjectGeneratedInputs) {
- TestWithScope setup;
- Err err;
-
- // This target compiles the source.
- SourceFile source_file("//source.cc");
- TestTarget source_generator(setup, "//:source_target", Target::SOURCE_SET);
- source_generator.sources().push_back(source_file);
- EXPECT_TRUE(source_generator.OnResolved(&err));
-
- // This is the object file that the test toolchain generates for the source.
- SourceFile object_file("//out/Debug/obj/source_target.source.o");
-
- TestTarget final_target(setup, "//:final", Target::ACTION);
- final_target.config_values().inputs().push_back(object_file);
- EXPECT_TRUE(final_target.OnResolved(&err));
-
- AssertSchedulerHasOneUnknownFileMatching(&final_target, object_file);
-}
-
-TEST_F(TargetTest, ResolvePrecompiledHeaders) {
- TestWithScope setup;
- Err err;
-
- Target target(setup.settings(), Label(SourceDir("//foo/"), "bar"));
-
- // Target with no settings, no configs, should be a no-op.
- EXPECT_TRUE(target.ResolvePrecompiledHeaders(&err));
-
- // Config with PCH values.
- Config config_1(setup.settings(), Label(SourceDir("//foo/"), "c1"));
- std::string pch_1("pch.h");
- SourceFile pcs_1("//pcs.cc");
- config_1.own_values().set_precompiled_header(pch_1);
- config_1.own_values().set_precompiled_source(pcs_1);
- ASSERT_TRUE(config_1.OnResolved(&err));
- target.configs().push_back(LabelConfigPair(&config_1));
-
- // No PCH info specified on TargetTest, but the config specifies one, the
- // values should get copied to the target.
- EXPECT_TRUE(target.ResolvePrecompiledHeaders(&err));
- EXPECT_EQ(pch_1, target.config_values().precompiled_header());
- EXPECT_TRUE(target.config_values().precompiled_source() == pcs_1);
-
- // Now both target and config have matching PCH values. Resolving again
- // should be a no-op since they all match.
- EXPECT_TRUE(target.ResolvePrecompiledHeaders(&err));
- EXPECT_TRUE(target.config_values().precompiled_header() == pch_1);
- EXPECT_TRUE(target.config_values().precompiled_source() == pcs_1);
-
- // Second config with different PCH values.
- Config config_2(setup.settings(), Label(SourceDir("//foo/"), "c2"));
- std::string pch_2("pch2.h");
- SourceFile pcs_2("//pcs2.cc");
- config_2.own_values().set_precompiled_header(pch_2);
- config_2.own_values().set_precompiled_source(pcs_2);
- ASSERT_TRUE(config_2.OnResolved(&err));
- target.configs().push_back(LabelConfigPair(&config_2));
-
- // This should be an error since they don't match.
- EXPECT_FALSE(target.ResolvePrecompiledHeaders(&err));
-
- // Make sure the proper labels are blamed.
- EXPECT_EQ(
- "The target //foo:bar\n"
- "has conflicting precompiled header settings.\n"
- "\n"
- "From //foo:bar\n"
- " header: pch.h\n"
- " source: //pcs.cc\n"
- "\n"
- "From //foo:c2\n"
- " header: pch2.h\n"
- " source: //pcs2.cc",
- err.help_text());
-}
-
-TEST_F(TargetTest, AssertNoDeps) {
- TestWithScope setup;
- Err err;
-
- // A target.
- TestTarget a(setup, "//a", Target::SHARED_LIBRARY);
- ASSERT_TRUE(a.OnResolved(&err));
-
- // B depends on A and has an assert_no_deps for a random dir.
- TestTarget b(setup, "//b", Target::SHARED_LIBRARY);
- b.private_deps().push_back(LabelTargetPair(&a));
- b.assert_no_deps().push_back(LabelPattern(
- LabelPattern::RECURSIVE_DIRECTORY, SourceDir("//disallowed/"),
- std::string(), Label()));
- ASSERT_TRUE(b.OnResolved(&err));
-
- LabelPattern disallow_a(LabelPattern::RECURSIVE_DIRECTORY, SourceDir("//a/"),
- std::string(), Label());
-
- // C depends on B and disallows depending on A. This should fail.
- TestTarget c(setup, "//c", Target::EXECUTABLE);
- c.private_deps().push_back(LabelTargetPair(&b));
- c.assert_no_deps().push_back(disallow_a);
- ASSERT_FALSE(c.OnResolved(&err));
-
- // Validate the error message has the proper path.
- EXPECT_EQ(
- "//c:c has an assert_no_deps entry:\n"
- " //a/*\n"
- "which fails for the dependency path:\n"
- " //c:c ->\n"
- " //b:b ->\n"
- " //a:a",
- err.help_text());
- err = Err();
-
- // Add an intermediate executable with: exe -> b -> a
- TestTarget exe(setup, "//exe", Target::EXECUTABLE);
- exe.private_deps().push_back(LabelTargetPair(&b));
- ASSERT_TRUE(exe.OnResolved(&err));
-
- // D depends on the executable and disallows depending on A. Since there is
- // an intermediate executable, this should be OK.
- TestTarget d(setup, "//d", Target::EXECUTABLE);
- d.private_deps().push_back(LabelTargetPair(&exe));
- d.assert_no_deps().push_back(disallow_a);
- ASSERT_TRUE(d.OnResolved(&err));
-
- // A2 disallows depending on anything in its own directory, but the
- // assertions should not match the target itself so this should be OK.
- TestTarget a2(setup, "//a:a2", Target::EXECUTABLE);
- a2.assert_no_deps().push_back(disallow_a);
- ASSERT_TRUE(a2.OnResolved(&err));
-}
-
-TEST_F(TargetTest, PullRecursiveBundleData) {
- TestWithScope setup;
- Err err;
-
- // We have the following dependency graph:
- // A (create_bundle) -> B (bundle_data)
- // \-> C (create_bundle) -> D (bundle_data)
- // \-> E (group) -> F (bundle_data)
- // \-> B (bundle_data)
- TestTarget a(setup, "//foo:a", Target::CREATE_BUNDLE);
- TestTarget b(setup, "//foo:b", Target::BUNDLE_DATA);
- TestTarget c(setup, "//foo:c", Target::CREATE_BUNDLE);
- TestTarget d(setup, "//foo:d", Target::BUNDLE_DATA);
- TestTarget e(setup, "//foo:e", Target::GROUP);
- TestTarget f(setup, "//foo:f", Target::BUNDLE_DATA);
- a.public_deps().push_back(LabelTargetPair(&b));
- a.public_deps().push_back(LabelTargetPair(&c));
- a.public_deps().push_back(LabelTargetPair(&e));
- c.public_deps().push_back(LabelTargetPair(&d));
- e.public_deps().push_back(LabelTargetPair(&f));
- e.public_deps().push_back(LabelTargetPair(&b));
-
- b.sources().push_back(SourceFile("//foo/b1.txt"));
- b.sources().push_back(SourceFile("//foo/b2.txt"));
- b.action_values().outputs() = SubstitutionList::MakeForTest(
- "{{bundle_resources_dir}}/{{source_file_part}}");
- ASSERT_TRUE(b.OnResolved(&err));
-
- d.sources().push_back(SourceFile("//foo/d.txt"));
- d.action_values().outputs() = SubstitutionList::MakeForTest(
- "{{bundle_resources_dir}}/{{source_file_part}}");
- ASSERT_TRUE(d.OnResolved(&err));
-
- f.sources().push_back(SourceFile("//foo/f1.txt"));
- f.sources().push_back(SourceFile("//foo/f2.txt"));
- f.sources().push_back(SourceFile("//foo/f3.txt"));
- f.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/Contents.json"));
- f.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/FooEmpty-29.png"));
- f.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/FooEmpty-29@2x.png"));
- f.sources().push_back(
- SourceFile("//foo/Foo.xcassets/foo.imageset/FooEmpty-29@3x.png"));
- f.action_values().outputs() = SubstitutionList::MakeForTest(
- "{{bundle_resources_dir}}/{{source_file_part}}");
- ASSERT_TRUE(f.OnResolved(&err));
-
- ASSERT_TRUE(e.OnResolved(&err));
- ASSERT_TRUE(c.OnResolved(&err));
- ASSERT_TRUE(a.OnResolved(&err));
-
- // A gets its data from B and F.
- ASSERT_EQ(a.bundle_data().file_rules().size(), 2u);
- ASSERT_EQ(a.bundle_data().file_rules()[0].sources().size(), 2u);
- ASSERT_EQ(a.bundle_data().file_rules()[1].sources().size(), 3u);
- ASSERT_EQ(a.bundle_data().assets_catalog_sources().size(), 1u);
- ASSERT_EQ(a.bundle_data().bundle_deps().size(), 2u);
-
- // C gets its data from D.
- ASSERT_EQ(c.bundle_data().file_rules().size(), 1u);
- ASSERT_EQ(c.bundle_data().file_rules()[0].sources().size(), 1u);
- ASSERT_EQ(c.bundle_data().bundle_deps().size(), 1u);
-
- // E does not have any bundle_data information but gets a list of
- // bundle_deps to propagate them during target resolution.
- ASSERT_TRUE(e.bundle_data().file_rules().empty());
- ASSERT_TRUE(e.bundle_data().assets_catalog_sources().empty());
- ASSERT_EQ(e.bundle_data().bundle_deps().size(), 2u);
-}
diff --git a/chromium/tools/gn/template.cc b/chromium/tools/gn/template.cc
deleted file mode 100644
index ad28680619d..00000000000
--- a/chromium/tools/gn/template.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/template.h"
-
-#include <memory>
-#include <utility>
-
-#include "tools/gn/err.h"
-#include "tools/gn/functions.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/scope_per_file_provider.h"
-#include "tools/gn/value.h"
-#include "tools/gn/variables.h"
-
-Template::Template(const Scope* scope, const FunctionCallNode* def)
- : closure_(scope->MakeClosure()),
- definition_(def) {
-}
-
-Template::Template(std::unique_ptr<Scope> scope, const FunctionCallNode* def)
- : closure_(std::move(scope)), definition_(def) {}
-
-Template::~Template() = default;
-
-Value Template::Invoke(Scope* scope,
- const FunctionCallNode* invocation,
- const std::string& template_name,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) const {
- // Don't allow templates to be executed from imported files. Imports are for
- // simple values only.
- if (!EnsureNotProcessingImport(invocation, scope, err))
- return Value();
-
- // First run the invocation's block. Need to allocate the scope on the heap
- // so we can pass ownership to the template.
- std::unique_ptr<Scope> invocation_scope = std::make_unique<Scope>(scope);
- if (!FillTargetBlockScope(scope, invocation, template_name,
- block, args, invocation_scope.get(), err))
- return Value();
-
- {
- // Don't allow the block of the template invocation to include other
- // targets configs, or template invocations. This must only be applied
- // to the invoker's block rather than the whole function because the
- // template execution itself must be able to define targets, etc.
- NonNestableBlock non_nestable(scope, invocation, "template invocation");
- if (!non_nestable.Enter(err))
- return Value();
-
- block->Execute(invocation_scope.get(), err);
- if (err->has_error())
- return Value();
- }
-
- // Set up the scope to run the template and set the current directory for the
- // template (which ScopePerFileProvider uses to base the target-related
- // variables target_gen_dir and target_out_dir on) to be that of the invoker.
- // This way, files don't have to be rebased and target_*_dir works the way
- // people expect (otherwise its to easy to be putting generated files in the
- // gen dir corresponding to an imported file).
- Scope template_scope(closure_.get());
- template_scope.set_source_dir(scope->GetSourceDir());
-
- ScopePerFileProvider per_file_provider(&template_scope, true);
-
- // Targets defined in the template go in the collector for the invoking file.
- template_scope.set_item_collector(scope->GetItemCollector());
-
- // We jump through some hoops to avoid copying the invocation scope when
- // setting it in the template scope (since the invocation scope may have
- // large lists of source files in it and could be expensive to copy).
- //
- // Scope.SetValue will copy the value which will in turn copy the scope, but
- // if we instead create a value and then set the scope on it, the copy can
- // be avoided.
- template_scope.SetValue(variables::kInvoker,
- Value(nullptr, std::unique_ptr<Scope>()), invocation);
- Value* invoker_value = template_scope.GetMutableValue(
- variables::kInvoker, Scope::SEARCH_NESTED, false);
- invoker_value->SetScopeValue(std::move(invocation_scope));
- template_scope.set_source_dir(scope->GetSourceDir());
-
- const base::StringPiece target_name(variables::kTargetName);
- template_scope.SetValue(target_name,
- Value(invocation, args[0].string_value()),
- invocation);
-
- // Actually run the template code.
- Value result =
- definition_->block()->Execute(&template_scope, err);
- if (err->has_error()) {
- // If there was an error, append the caller location so the error message
- // displays a stack trace of how it got here.
- err->AppendSubErr(Err(invocation, "whence it was called."));
- return Value();
- }
-
- // Check for unused variables in the invocation scope. This will find typos
- // of things the caller meant to pass to the template but the template didn't
- // read out.
- //
- // This is a bit tricky because it's theoretically possible for the template
- // to overwrite the value of "invoker" and free the Scope owned by the
- // value. So we need to look it up again and don't do anything if it doesn't
- // exist.
- invoker_value = template_scope.GetMutableValue(
- variables::kInvoker, Scope::SEARCH_NESTED, false);
- if (invoker_value && invoker_value->type() == Value::SCOPE) {
- if (!invoker_value->scope_value()->CheckForUnusedVars(err))
- return Value();
- }
-
- // Check for unused variables in the template itself.
- if (!template_scope.CheckForUnusedVars(err))
- return Value();
-
- return result;
-}
-
-LocationRange Template::GetDefinitionRange() const {
- return definition_->GetRange();
-}
diff --git a/chromium/tools/gn/template.h b/chromium/tools/gn/template.h
deleted file mode 100644
index 6386ba9f2ba..00000000000
--- a/chromium/tools/gn/template.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_TEMPLATE_H_
-#define TOOLS_GN_TEMPLATE_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/memory/ref_counted.h"
-
-class BlockNode;
-class Err;
-class FunctionCallNode;
-class LocationRange;
-class Scope;
-class Value;
-
-// Represents the information associated with a template() call in GN, which
-// includes a closure and the code to run when the template is invoked.
-//
-// This class is immutable so we can reference it from multiple threads without
-// locking. Normally, this will be associated with a .gni file and then a
-// reference will be taken by each .gn file that imports it. These files might
-// execute the template in parallel.
-class Template : public base::RefCountedThreadSafe<Template> {
- public:
- // Makes a new closure based on the given scope.
- Template(const Scope* scope, const FunctionCallNode* def);
-
- // Takes ownership of a previously-constructed closure.
- Template(std::unique_ptr<Scope> closure, const FunctionCallNode* def);
-
- // Invoke the template. The values correspond to the state of the code
- // invoking the template. The template name needs to be supplied since the
- // template object itself doesn't know what name the calling code is using
- // to refer to it (this is used to set defaults).
- Value Invoke(Scope* scope,
- const FunctionCallNode* invocation,
- const std::string& template_name,
- const std::vector<Value>& args,
- BlockNode* block,
- Err* err) const;
-
- // Returns the location range where this template was defined.
- LocationRange GetDefinitionRange() const;
-
- private:
- friend class base::RefCountedThreadSafe<Template>;
-
- Template();
- ~Template();
-
- // It's important that this Scope is const. A template can be referenced by
- // the root BUILDCONFIG file and then duplicated to all threads. Therefore,
- // this scope must be usable from multiple threads at the same time.
- //
- // When executing a template, a new scope will be created as a child of this
- // one, which will reference it as mutable or not according to the mutability
- // of this value.
- std::unique_ptr<const Scope> closure_;
-
- const FunctionCallNode* definition_;
-};
-
-#endif // TOOLS_GN_TEMPLATE_H_
diff --git a/chromium/tools/gn/template_unittest.cc b/chromium/tools/gn/template_unittest.cc
deleted file mode 100644
index 905dc7bb048..00000000000
--- a/chromium/tools/gn/template_unittest.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/strings/string_number_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/test_with_scope.h"
-
-TEST(Template, Basic) {
- TestWithScope setup;
- TestParseInput input(
- "template(\"foo\") {\n"
- " print(target_name)\n"
- " print(invoker.bar)\n"
- "}\n"
- "foo(\"lala\") {\n"
- " bar = 42\n"
- "}");
- ASSERT_FALSE(input.has_error());
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(err.has_error()) << err.message();
-
- EXPECT_EQ("lala\n42\n", setup.print_output());
-}
-
-TEST(Template, UnusedTargetNameShouldThrowError) {
- TestWithScope setup;
- TestParseInput input(
- "template(\"foo\") {\n"
- " print(invoker.bar)\n"
- "}\n"
- "foo(\"lala\") {\n"
- " bar = 42\n"
- "}");
- ASSERT_FALSE(input.has_error());
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
-}
-
-TEST(Template, UnusedInvokerShouldThrowError) {
- TestWithScope setup;
- TestParseInput input(
- "template(\"foo\") {\n"
- " print(target_name)\n"
- "}\n"
- "foo(\"lala\") {\n"
- " bar = 42\n"
- "}");
- ASSERT_FALSE(input.has_error());
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
-}
-
-TEST(Template, UnusedVarInInvokerShouldThrowError) {
- TestWithScope setup;
- TestParseInput input(
- "template(\"foo\") {\n"
- " print(target_name)\n"
- " print(invoker.bar)\n"
- "}\n"
- "foo(\"lala\") {\n"
- " bar = 42\n"
- " baz = [ \"foo\" ]\n"
- "}");
- ASSERT_FALSE(input.has_error());
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- EXPECT_TRUE(err.has_error());
-}
-
-// Previous versions of the template implementation would copy templates by
-// value when it makes a closure. Doing a sequence of them means that every new
-// one copies all previous ones, which gives a significant blow-up in memory.
-// If this test doesn't crash with out-of-memory, it passed.
-TEST(Template, MemoryBlowUp) {
- TestWithScope setup;
- std::string code;
- for (int i = 0; i < 100; i++)
- code += "template(\"test" + base::IntToString(i) + "\") {}\n";
-
- TestParseInput input(code);
-
- Err err;
- input.parsed()->Execute(setup.scope(), &err);
- ASSERT_FALSE(input.has_error());
-}
diff --git a/chromium/tools/gn/test_with_scheduler.cc b/chromium/tools/gn/test_with_scheduler.cc
deleted file mode 100644
index ce7a90c7110..00000000000
--- a/chromium/tools/gn/test_with_scheduler.cc
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/test_with_scheduler.h"
-
-TestWithScheduler::TestWithScheduler() = default;
-TestWithScheduler::~TestWithScheduler() = default;
diff --git a/chromium/tools/gn/test_with_scheduler.h b/chromium/tools/gn/test_with_scheduler.h
deleted file mode 100644
index 230f69e5e2e..00000000000
--- a/chromium/tools/gn/test_with_scheduler.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_TEST_WITH_SCHEDULER_H_
-#define TOOLS_GN_TEST_WITH_SCHEDULER_H_
-
-#include "base/macros.h"
-#include "base/test/scoped_task_environment.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/scheduler.h"
-
-class TestWithScheduler : public testing::Test {
- protected:
- TestWithScheduler();
- ~TestWithScheduler() override;
-
- Scheduler& scheduler() { return scheduler_; }
-
- private:
- base::test::ScopedTaskEnvironment scoped_task_environment_;
- Scheduler scheduler_;
-
- DISALLOW_COPY_AND_ASSIGN(TestWithScheduler);
-};
-
-#endif // TOOLS_GN_TEST_WITH_SCHEDULER_H_
diff --git a/chromium/tools/gn/test_with_scope.cc b/chromium/tools/gn/test_with_scope.cc
deleted file mode 100644
index c834e7c745d..00000000000
--- a/chromium/tools/gn/test_with_scope.cc
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/test_with_scope.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "tools/gn/parser.h"
-#include "tools/gn/tokenizer.h"
-
-namespace {
-
-BuildSettings CreateBuildSettingsForTest() {
- BuildSettings build_settings;
- build_settings.SetBuildDir(SourceDir("//out/Debug/"));
- return build_settings;
-}
-
-} // namespace
-
-TestWithScope::TestWithScope()
- : build_settings_(CreateBuildSettingsForTest()),
- settings_(&build_settings_, std::string()),
- toolchain_(&settings_, Label(SourceDir("//toolchain/"), "default")),
- scope_(&settings_),
- scope_progammatic_provider_(&scope_, true) {
- build_settings_.set_print_callback(
- base::Bind(&TestWithScope::AppendPrintOutput, base::Unretained(this)));
-
- settings_.set_toolchain_label(toolchain_.label());
- settings_.set_default_toolchain_label(toolchain_.label());
-
- SetupToolchain(&toolchain_);
- scope_.set_item_collector(&items_);
-}
-
-TestWithScope::~TestWithScope() = default;
-
-Label TestWithScope::ParseLabel(const std::string& str) const {
- Err err;
- Label result = Label::Resolve(SourceDir("//"), toolchain_.label(),
- Value(nullptr, str), &err);
- CHECK(!err.has_error());
- return result;
-}
-
-bool TestWithScope::ExecuteSnippet(const std::string& str, Err* err) {
- TestParseInput input(str);
- if (input.has_error()) {
- *err = input.parse_err();
- return false;
- }
-
- size_t first_item = items_.size();
- input.parsed()->Execute(&scope_, err);
- if (err->has_error())
- return false;
-
- for (size_t i = first_item; i < items_.size(); ++i) {
- CHECK(items_[i]->AsTarget() != nullptr)
- << "Only targets are supported in ExecuteSnippet()";
- items_[i]->AsTarget()->SetToolchain(&toolchain_);
- if (!items_[i]->OnResolved(err))
- return false;
- }
- return true;
-}
-
-// static
-void TestWithScope::SetupToolchain(Toolchain* toolchain) {
- Err err;
-
- // CC
- std::unique_ptr<Tool> cc_tool = std::make_unique<Tool>();
- SetCommandForTool(
- "cc {{source}} {{cflags}} {{cflags_c}} {{defines}} {{include_dirs}} "
- "-o {{output}}",
- cc_tool.get());
- cc_tool->set_outputs(SubstitutionList::MakeForTest(
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
- toolchain->SetTool(Toolchain::TYPE_CC, std::move(cc_tool));
-
- // CXX
- std::unique_ptr<Tool> cxx_tool = std::make_unique<Tool>();
- SetCommandForTool(
- "c++ {{source}} {{cflags}} {{cflags_cc}} {{defines}} {{include_dirs}} "
- "-o {{output}}",
- cxx_tool.get());
- cxx_tool->set_outputs(SubstitutionList::MakeForTest(
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
- toolchain->SetTool(Toolchain::TYPE_CXX, std::move(cxx_tool));
-
- // OBJC
- std::unique_ptr<Tool> objc_tool = std::make_unique<Tool>();
- SetCommandForTool(
- "objcc {{source}} {{cflags}} {{cflags_objc}} {{defines}} "
- "{{include_dirs}} -o {{output}}",
- objc_tool.get());
- objc_tool->set_outputs(SubstitutionList::MakeForTest(
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
- toolchain->SetTool(Toolchain::TYPE_OBJC, std::move(objc_tool));
-
- // OBJC
- std::unique_ptr<Tool> objcxx_tool = std::make_unique<Tool>();
- SetCommandForTool(
- "objcxx {{source}} {{cflags}} {{cflags_objcc}} {{defines}} "
- "{{include_dirs}} -o {{output}}",
- objcxx_tool.get());
- objcxx_tool->set_outputs(SubstitutionList::MakeForTest(
- "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o"));
- toolchain->SetTool(Toolchain::TYPE_OBJCXX, std::move(objcxx_tool));
-
- // Don't use RC and ASM tools in unit tests yet. Add here if needed.
-
- // ALINK
- std::unique_ptr<Tool> alink_tool = std::make_unique<Tool>();
- SetCommandForTool("ar {{output}} {{source}}", alink_tool.get());
- alink_tool->set_lib_switch("-l");
- alink_tool->set_lib_dir_switch("-L");
- alink_tool->set_output_prefix("lib");
- alink_tool->set_outputs(SubstitutionList::MakeForTest(
- "{{target_out_dir}}/{{target_output_name}}.a"));
- toolchain->SetTool(Toolchain::TYPE_ALINK, std::move(alink_tool));
-
- // SOLINK
- std::unique_ptr<Tool> solink_tool = std::make_unique<Tool>();
- SetCommandForTool("ld -shared -o {{target_output_name}}.so {{inputs}} "
- "{{ldflags}} {{libs}}", solink_tool.get());
- solink_tool->set_lib_switch("-l");
- solink_tool->set_lib_dir_switch("-L");
- solink_tool->set_output_prefix("lib");
- solink_tool->set_default_output_extension(".so");
- solink_tool->set_outputs(SubstitutionList::MakeForTest(
- "{{root_out_dir}}/{{target_output_name}}{{output_extension}}"));
- toolchain->SetTool(Toolchain::TYPE_SOLINK, std::move(solink_tool));
-
- // SOLINK_MODULE
- std::unique_ptr<Tool> solink_module_tool = std::make_unique<Tool>();
- SetCommandForTool("ld -bundle -o {{target_output_name}}.so {{inputs}} "
- "{{ldflags}} {{libs}}", solink_module_tool.get());
- solink_module_tool->set_lib_switch("-l");
- solink_module_tool->set_lib_dir_switch("-L");
- solink_module_tool->set_output_prefix("lib");
- solink_module_tool->set_default_output_extension(".so");
- solink_module_tool->set_outputs(SubstitutionList::MakeForTest(
- "{{root_out_dir}}/{{target_output_name}}{{output_extension}}"));
- toolchain->SetTool(Toolchain::TYPE_SOLINK_MODULE,
- std::move(solink_module_tool));
-
- // LINK
- std::unique_ptr<Tool> link_tool = std::make_unique<Tool>();
- SetCommandForTool("ld -o {{target_output_name}} {{source}} "
- "{{ldflags}} {{libs}}", link_tool.get());
- link_tool->set_lib_switch("-l");
- link_tool->set_lib_dir_switch("-L");
- link_tool->set_outputs(SubstitutionList::MakeForTest(
- "{{root_out_dir}}/{{target_output_name}}"));
- toolchain->SetTool(Toolchain::TYPE_LINK, std::move(link_tool));
-
- // STAMP
- std::unique_ptr<Tool> stamp_tool = std::make_unique<Tool>();
- SetCommandForTool("touch {{output}}", stamp_tool.get());
- toolchain->SetTool(Toolchain::TYPE_STAMP, std::move(stamp_tool));
-
- // COPY
- std::unique_ptr<Tool> copy_tool = std::make_unique<Tool>();
- SetCommandForTool("cp {{source}} {{output}}", copy_tool.get());
- toolchain->SetTool(Toolchain::TYPE_COPY, std::move(copy_tool));
-
- // COPY_BUNDLE_DATA
- std::unique_ptr<Tool> copy_bundle_data_tool = std::make_unique<Tool>();
- SetCommandForTool("cp {{source}} {{output}}", copy_bundle_data_tool.get());
- toolchain->SetTool(Toolchain::TYPE_COPY_BUNDLE_DATA,
- std::move(copy_bundle_data_tool));
-
- // COMPILE_XCASSETS
- std::unique_ptr<Tool> compile_xcassets_tool = std::make_unique<Tool>();
- SetCommandForTool("touch {{output}}", compile_xcassets_tool.get());
- toolchain->SetTool(Toolchain::TYPE_COMPILE_XCASSETS,
- std::move(compile_xcassets_tool));
-
- toolchain->ToolchainSetupComplete();
-}
-
-// static
-void TestWithScope::SetCommandForTool(const std::string& cmd, Tool* tool) {
- Err err;
- SubstitutionPattern command;
- command.Parse(cmd, nullptr, &err);
- CHECK(!err.has_error())
- << "Couldn't parse \"" << cmd << "\", " << "got " << err.message();
- tool->set_command(command);
-}
-
-void TestWithScope::AppendPrintOutput(const std::string& str) {
- print_output_.append(str);
-}
-
-TestParseInput::TestParseInput(const std::string& input)
- : input_file_(SourceFile("//test")) {
- input_file_.SetContents(input);
-
- tokens_ = Tokenizer::Tokenize(&input_file_, &parse_err_);
- if (!parse_err_.has_error())
- parsed_ = Parser::Parse(tokens_, &parse_err_);
-}
-
-TestParseInput::~TestParseInput() = default;
-
-TestTarget::TestTarget(const TestWithScope& setup,
- const std::string& label_string,
- Target::OutputType type)
- : Target(setup.settings(), setup.ParseLabel(label_string)) {
- visibility().SetPublic();
- set_output_type(type);
- SetToolchain(setup.toolchain());
-}
-
-TestTarget::~TestTarget() = default;
diff --git a/chromium/tools/gn/test_with_scope.h b/chromium/tools/gn/test_with_scope.h
deleted file mode 100644
index 88532438213..00000000000
--- a/chromium/tools/gn/test_with_scope.h
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_TEST_WITH_SCOPE_H_
-#define TOOLS_GN_TEST_WITH_SCOPE_H_
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/err.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/scope_per_file_provider.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/target.h"
-#include "tools/gn/token.h"
-#include "tools/gn/toolchain.h"
-#include "tools/gn/value.h"
-
-// A helper class for setting up a Scope that a test can use. It makes a
-// toolchain and sets up all the build state.
-class TestWithScope {
- public:
- TestWithScope();
- ~TestWithScope();
-
- BuildSettings* build_settings() { return &build_settings_; }
- Settings* settings() { return &settings_; }
- const Settings* settings() const { return &settings_; }
- Toolchain* toolchain() { return &toolchain_; }
- const Toolchain* toolchain() const { return &toolchain_; }
- Scope* scope() { return &scope_; }
- const Scope::ItemVector& items() { return items_; }
-
- // This buffer accumulates output from any print() commands executed in the
- // context of this test. Note that the implementation of this is not
- // threadsafe so don't write tests that call print from multiple threads.
- std::string& print_output() { return print_output_; }
-
- // Parse the given string into a label in the default toolchain. This will
- // assert if the label isn't valid (this is intended for hardcoded labels).
- Label ParseLabel(const std::string& str) const;
-
- // Parses, evaluates, and resolves targets from the given snippet of code.
- // All targets must be defined in dependency order (does not use a Builder,
- // just blindly resolves all targets in order).
- bool ExecuteSnippet(const std::string& str, Err* err);
-
- // Fills in the tools for the given toolchain with reasonable default values.
- // The toolchain in this object will be automatically set up with this
- // function, it is exposed to allow tests to get the same functionality for
- // other toolchains they make.
- static void SetupToolchain(Toolchain* toolchain);
-
- // Sets the given text command on the given tool, parsing it as a
- // substitution pattern. This will assert if the input is malformed. This is
- // designed to help setting up Tools for tests.
- static void SetCommandForTool(const std::string& cmd, Tool* tool);
-
- private:
- void AppendPrintOutput(const std::string& str);
-
- BuildSettings build_settings_;
- Settings settings_;
- Toolchain toolchain_;
- Scope scope_;
- Scope::ItemVector items_;
-
- // Supplies the scope with built-in variables like root_out_dir.
- ScopePerFileProvider scope_progammatic_provider_;
-
- std::string print_output_;
-
- DISALLOW_COPY_AND_ASSIGN(TestWithScope);
-};
-
-// Helper class to treat some string input as a file.
-//
-// Instantiate it with the contents you want, be sure to check for error, and
-// then you can execute the ParseNode or whatever.
-class TestParseInput {
- public:
- explicit TestParseInput(const std::string& input);
- ~TestParseInput();
-
- // Indicates whether and what error occurred during tokenizing and parsing.
- bool has_error() const { return parse_err_.has_error(); }
- const Err& parse_err() const { return parse_err_; }
-
- const InputFile& input_file() const { return input_file_; }
- const std::vector<Token>& tokens() const { return tokens_; }
- const ParseNode* parsed() const { return parsed_.get(); }
-
- private:
- InputFile input_file_;
-
- std::vector<Token> tokens_;
- std::unique_ptr<ParseNode> parsed_;
-
- Err parse_err_;
-
- DISALLOW_COPY_AND_ASSIGN(TestParseInput);
-};
-
-// Shortcut for creating targets for tests that take the test setup, a pretty-
-// style label, and a target type and sets everything up. The target will
-// default to public visibility.
-class TestTarget : public Target {
- public:
- TestTarget(const TestWithScope& setup,
- const std::string& label_string,
- Target::OutputType type);
- ~TestTarget() override;
-};
-
-#endif // TOOLS_GN_TEST_WITH_SCOPE_H_
diff --git a/chromium/tools/gn/token.cc b/chromium/tools/gn/token.cc
deleted file mode 100644
index 6721619d0d6..00000000000
--- a/chromium/tools/gn/token.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/token.h"
-
-#include "base/logging.h"
-
-Token::Token() : type_(INVALID), value_() {
-}
-
-Token::Token(const Location& location,
- Type t,
- const base::StringPiece& v)
- : type_(t),
- value_(v),
- location_(location) {
-}
-
-Token::Token(const Token& other) = default;
-
-bool Token::IsIdentifierEqualTo(const char* v) const {
- return type_ == IDENTIFIER && value_ == v;
-}
-
-bool Token::IsStringEqualTo(const char* v) const {
- return type_ == STRING && value_ == v;
-}
diff --git a/chromium/tools/gn/token.h b/chromium/tools/gn/token.h
deleted file mode 100644
index 24c4e9c2e10..00000000000
--- a/chromium/tools/gn/token.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_TOKEN_H_
-#define TOOLS_GN_TOKEN_H_
-
-#include "base/strings/string_piece.h"
-#include "tools/gn/location.h"
-
-class Token {
- public:
- enum Type {
- INVALID,
- INTEGER, // 123
- STRING, // "blah"
- TRUE_TOKEN, // Not "TRUE" to avoid collisions with #define in windows.h.
- FALSE_TOKEN,
-
- // Various operators.
- EQUAL,
- PLUS,
- MINUS,
- PLUS_EQUALS,
- MINUS_EQUALS,
- EQUAL_EQUAL,
- NOT_EQUAL,
- LESS_EQUAL,
- GREATER_EQUAL,
- LESS_THAN,
- GREATER_THAN,
- BOOLEAN_AND,
- BOOLEAN_OR,
- BANG,
- DOT,
-
- LEFT_PAREN,
- RIGHT_PAREN,
- LEFT_BRACKET,
- RIGHT_BRACKET,
- LEFT_BRACE,
- RIGHT_BRACE,
-
- IF,
- ELSE,
- IDENTIFIER, // foo
- COMMA, // ,
- UNCLASSIFIED_COMMENT, // #...\n, of unknown style (will be converted
- // to one below)
- LINE_COMMENT, // #...\n on a line alone.
- SUFFIX_COMMENT, // #...\n on a line following other code.
- BLOCK_COMMENT, // #...\n line comment, but free-standing.
-
- UNCLASSIFIED_OPERATOR,
-
- NUM_TYPES
- };
-
- Token();
- Token(const Location& location, Type t, const base::StringPiece& v);
- Token(const Token& other);
-
- Type type() const { return type_; }
- const base::StringPiece& value() const { return value_; }
- const Location& location() const { return location_; }
- void set_location(Location location) { location_ = location; }
- LocationRange range() const {
- return LocationRange(
- location_,
- Location(location_.file(),
- location_.line_number(),
- location_.column_number() + static_cast<int>(value_.size()),
- location_.byte() + static_cast<int>(value_.size())));
- }
-
- // Helper functions for comparing this token to something.
- bool IsIdentifierEqualTo(const char* v) const;
- bool IsStringEqualTo(const char* v) const;
-
- private:
- Type type_;
- base::StringPiece value_;
- Location location_;
-};
-
-#endif // TOOLS_GN_TOKEN_H_
diff --git a/chromium/tools/gn/tokenizer.cc b/chromium/tools/gn/tokenizer.cc
deleted file mode 100644
index 306f626872b..00000000000
--- a/chromium/tools/gn/tokenizer.cc
+++ /dev/null
@@ -1,409 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/tokenizer.h"
-
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "tools/gn/input_file.h"
-
-namespace {
-
-bool CouldBeTwoCharOperatorBegin(char c) {
- return c == '<' || c == '>' || c == '!' || c == '=' || c == '-' ||
- c == '+' || c == '|' || c == '&';
-}
-
-bool CouldBeTwoCharOperatorEnd(char c) {
- return c == '=' || c == '|' || c == '&';
-}
-
-bool CouldBeOneCharOperator(char c) {
- return c == '=' || c == '<' || c == '>' || c == '+' || c == '!' ||
- c == ':' || c == '|' || c == '&' || c == '-';
-}
-
-bool CouldBeOperator(char c) {
- return CouldBeOneCharOperator(c) || CouldBeTwoCharOperatorBegin(c);
-}
-
-bool IsScoperChar(char c) {
- return c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}';
-}
-
-Token::Type GetSpecificOperatorType(base::StringPiece value) {
- if (value == "=")
- return Token::EQUAL;
- if (value == "+")
- return Token::PLUS;
- if (value == "-")
- return Token::MINUS;
- if (value == "+=")
- return Token::PLUS_EQUALS;
- if (value == "-=")
- return Token::MINUS_EQUALS;
- if (value == "==")
- return Token::EQUAL_EQUAL;
- if (value == "!=")
- return Token::NOT_EQUAL;
- if (value == "<=")
- return Token::LESS_EQUAL;
- if (value == ">=")
- return Token::GREATER_EQUAL;
- if (value == "<")
- return Token::LESS_THAN;
- if (value == ">")
- return Token::GREATER_THAN;
- if (value == "&&")
- return Token::BOOLEAN_AND;
- if (value == "||")
- return Token::BOOLEAN_OR;
- if (value == "!")
- return Token::BANG;
- if (value == ".")
- return Token::DOT;
- return Token::INVALID;
-}
-
-} // namespace
-
-Tokenizer::Tokenizer(const InputFile* input_file, Err* err)
- : input_file_(input_file),
- input_(input_file->contents()),
- err_(err),
- cur_(0),
- line_number_(1),
- column_number_(1) {
-}
-
-Tokenizer::~Tokenizer() = default;
-
-// static
-std::vector<Token> Tokenizer::Tokenize(const InputFile* input_file, Err* err) {
- Tokenizer t(input_file, err);
- return t.Run();
-}
-
-std::vector<Token> Tokenizer::Run() {
- DCHECK(tokens_.empty());
- while (!done()) {
- AdvanceToNextToken();
- if (done())
- break;
- Location location = GetCurrentLocation();
-
- Token::Type type = ClassifyCurrent();
- if (type == Token::INVALID) {
- *err_ = GetErrorForInvalidToken(location);
- break;
- }
- size_t token_begin = cur_;
- AdvanceToEndOfToken(location, type);
- if (has_error())
- break;
- size_t token_end = cur_;
-
- base::StringPiece token_value(&input_.data()[token_begin],
- token_end - token_begin);
-
- if (type == Token::UNCLASSIFIED_OPERATOR) {
- type = GetSpecificOperatorType(token_value);
- } else if (type == Token::IDENTIFIER) {
- if (token_value == "if")
- type = Token::IF;
- else if (token_value == "else")
- type = Token::ELSE;
- else if (token_value == "true")
- type = Token::TRUE_TOKEN;
- else if (token_value == "false")
- type = Token::FALSE_TOKEN;
- } else if (type == Token::UNCLASSIFIED_COMMENT) {
- if (AtStartOfLine(token_begin) &&
- // If it's a standalone comment, but is a continuation of a comment on
- // a previous line, then instead make it a continued suffix comment.
- (tokens_.empty() || tokens_.back().type() != Token::SUFFIX_COMMENT ||
- tokens_.back().location().line_number() + 1 !=
- location.line_number() ||
- tokens_.back().location().column_number() !=
- location.column_number())) {
- type = Token::LINE_COMMENT;
- if (!at_end()) // Could be EOF.
- Advance(); // The current \n.
- // If this comment is separated from the next syntax element, then we
- // want to tag it as a block comment. This will become a standalone
- // statement at the parser level to keep this comment separate, rather
- // than attached to the subsequent statement.
- while (!at_end() && IsCurrentWhitespace()) {
- if (IsCurrentNewline()) {
- type = Token::BLOCK_COMMENT;
- break;
- }
- Advance();
- }
- } else {
- type = Token::SUFFIX_COMMENT;
- }
- }
-
- tokens_.push_back(Token(location, type, token_value));
- }
- if (err_->has_error())
- tokens_.clear();
- return tokens_;
-}
-
-// static
-size_t Tokenizer::ByteOffsetOfNthLine(const base::StringPiece& buf, int n) {
- DCHECK_GT(n, 0);
-
- if (n == 1)
- return 0;
-
- int cur_line = 1;
- size_t cur_byte = 0;
- while (cur_byte < buf.size()) {
- if (IsNewline(buf, cur_byte)) {
- cur_line++;
- if (cur_line == n)
- return cur_byte + 1;
- }
- cur_byte++;
- }
- return static_cast<size_t>(-1);
-}
-
-// static
-bool Tokenizer::IsNewline(const base::StringPiece& buffer, size_t offset) {
- DCHECK(offset < buffer.size());
- // We may need more logic here to handle different line ending styles.
- return buffer[offset] == '\n';
-}
-
-// static
-bool Tokenizer::IsIdentifierFirstChar(char c) {
- return base::IsAsciiAlpha(c) || c == '_';
-}
-
-// static
-bool Tokenizer::IsIdentifierContinuingChar(char c) {
- // Also allow digits after the first char.
- return IsIdentifierFirstChar(c) || base::IsAsciiDigit(c);
-}
-
-void Tokenizer::AdvanceToNextToken() {
- while (!at_end() && IsCurrentWhitespace())
- Advance();
-}
-
-Token::Type Tokenizer::ClassifyCurrent() const {
- DCHECK(!at_end());
- char next_char = cur_char();
- if (base::IsAsciiDigit(next_char))
- return Token::INTEGER;
- if (next_char == '"')
- return Token::STRING;
-
- // Note: '-' handled specially below.
- if (next_char != '-' && CouldBeOperator(next_char))
- return Token::UNCLASSIFIED_OPERATOR;
-
- if (IsIdentifierFirstChar(next_char))
- return Token::IDENTIFIER;
-
- if (next_char == '[')
- return Token::LEFT_BRACKET;
- if (next_char == ']')
- return Token::RIGHT_BRACKET;
- if (next_char == '(')
- return Token::LEFT_PAREN;
- if (next_char == ')')
- return Token::RIGHT_PAREN;
- if (next_char == '{')
- return Token::LEFT_BRACE;
- if (next_char == '}')
- return Token::RIGHT_BRACE;
-
- if (next_char == '.')
- return Token::DOT;
- if (next_char == ',')
- return Token::COMMA;
-
- if (next_char == '#')
- return Token::UNCLASSIFIED_COMMENT;
-
- // For the case of '-' differentiate between a negative number and anything
- // else.
- if (next_char == '-') {
- if (!CanIncrement())
- return Token::UNCLASSIFIED_OPERATOR; // Just the minus before end of
- // file.
- char following_char = input_[cur_ + 1];
- if (base::IsAsciiDigit(following_char))
- return Token::INTEGER;
- return Token::UNCLASSIFIED_OPERATOR;
- }
-
- return Token::INVALID;
-}
-
-void Tokenizer::AdvanceToEndOfToken(const Location& location,
- Token::Type type) {
- switch (type) {
- case Token::INTEGER:
- do {
- Advance();
- } while (!at_end() && base::IsAsciiDigit(cur_char()));
- if (!at_end()) {
- // Require the char after a number to be some kind of space, scope,
- // or operator.
- char c = cur_char();
- if (!IsCurrentWhitespace() && !CouldBeOperator(c) &&
- !IsScoperChar(c) && c != ',') {
- *err_ = Err(GetCurrentLocation(),
- "This is not a valid number.",
- "Learn to count.");
- // Highlight the number.
- err_->AppendRange(LocationRange(location, GetCurrentLocation()));
- }
- }
- break;
-
- case Token::STRING: {
- char initial = cur_char();
- Advance(); // Advance past initial "
- for (;;) {
- if (at_end()) {
- *err_ = Err(LocationRange(location, GetCurrentLocation()),
- "Unterminated string literal.",
- "Don't leave me hanging like this!");
- break;
- }
- if (IsCurrentStringTerminator(initial)) {
- Advance(); // Skip past last "
- break;
- } else if (IsCurrentNewline()) {
- *err_ = Err(LocationRange(location, GetCurrentLocation()),
- "Newline in string constant.");
- }
- Advance();
- }
- break;
- }
-
- case Token::UNCLASSIFIED_OPERATOR:
- // Some operators are two characters, some are one.
- if (CouldBeTwoCharOperatorBegin(cur_char())) {
- if (CanIncrement() && CouldBeTwoCharOperatorEnd(input_[cur_ + 1]))
- Advance();
- }
- Advance();
- break;
-
- case Token::IDENTIFIER:
- while (!at_end() && IsIdentifierContinuingChar(cur_char()))
- Advance();
- break;
-
- case Token::LEFT_BRACKET:
- case Token::RIGHT_BRACKET:
- case Token::LEFT_BRACE:
- case Token::RIGHT_BRACE:
- case Token::LEFT_PAREN:
- case Token::RIGHT_PAREN:
- case Token::DOT:
- case Token::COMMA:
- Advance(); // All are one char.
- break;
-
- case Token::UNCLASSIFIED_COMMENT:
- // Eat to EOL.
- while (!at_end() && !IsCurrentNewline())
- Advance();
- break;
-
- case Token::INVALID:
- default:
- *err_ = Err(location, "Everything is all messed up",
- "Please insert system disk in drive A: and press any key.");
- NOTREACHED();
- return;
- }
-}
-
-bool Tokenizer::AtStartOfLine(size_t location) const {
- while (location > 0) {
- --location;
- char c = input_[location];
- if (c == '\n')
- return true;
- if (c != ' ')
- return false;
- }
- return true;
-}
-
-bool Tokenizer::IsCurrentWhitespace() const {
- DCHECK(!at_end());
- char c = input_[cur_];
- // Note that tab (0x09), vertical tab (0x0B), and formfeed (0x0C) are illegal.
- return c == 0x0A || c == 0x0D || c == 0x20;
-}
-
-bool Tokenizer::IsCurrentStringTerminator(char quote_char) const {
- DCHECK(!at_end());
- if (cur_char() != quote_char)
- return false;
-
- // Check for escaping. \" is not a string terminator, but \\" is. Count
- // the number of preceding backslashes.
- int num_backslashes = 0;
- for (int i = static_cast<int>(cur_) - 1; i >= 0 && input_[i] == '\\'; i--)
- num_backslashes++;
-
- // Even backslashes mean that they were escaping each other and don't count
- // as escaping this quote.
- return (num_backslashes % 2) == 0;
-}
-
-bool Tokenizer::IsCurrentNewline() const {
- return IsNewline(input_, cur_);
-}
-
-void Tokenizer::Advance() {
- DCHECK(cur_ < input_.size());
- if (IsCurrentNewline()) {
- line_number_++;
- column_number_ = 1;
- } else {
- column_number_++;
- }
- cur_++;
-}
-
-Location Tokenizer::GetCurrentLocation() const {
- return Location(
- input_file_, line_number_, column_number_, static_cast<int>(cur_));
-}
-
-Err Tokenizer::GetErrorForInvalidToken(const Location& location) const {
- std::string help;
- if (cur_char() == ';') {
- // Semicolon.
- help = "Semicolons are not needed, delete this one.";
- } else if (cur_char() == '\t') {
- // Tab.
- help = "You got a tab character in here. Tabs are evil. "
- "Convert to spaces.";
- } else if (cur_char() == '/' && cur_ + 1 < input_.size() &&
- (input_[cur_ + 1] == '/' || input_[cur_ + 1] == '*')) {
- // Different types of comments.
- help = "Comments should start with # instead";
- } else if (cur_char() == '\'') {
- help = "Strings are delimited by \" characters, not apostrophes.";
- } else {
- help = "I have no idea what this is.";
- }
-
- return Err(location, "Invalid token.", help);
-}
diff --git a/chromium/tools/gn/tokenizer.h b/chromium/tools/gn/tokenizer.h
deleted file mode 100644
index 67590df55ef..00000000000
--- a/chromium/tools/gn/tokenizer.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_TOKENIZER_H_
-#define TOOLS_GN_TOKENIZER_H_
-
-#include <stddef.h>
-
-#include <vector>
-
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-#include "tools/gn/err.h"
-#include "tools/gn/token.h"
-
-class InputFile;
-
-class Tokenizer {
- public:
- static std::vector<Token> Tokenize(const InputFile* input_file, Err* err);
-
- // Counts lines in the given buffer (the first line is "1") and returns
- // the byte offset of the beginning of that line, or (size_t)-1 if there
- // aren't that many lines in the file. Note that this will return the byte
- // one past the end of the input if the last character is a newline.
- //
- // This is a helper function for error output so that the tokenizer's
- // notion of lines can be used elsewhere.
- static size_t ByteOffsetOfNthLine(const base::StringPiece& buf, int n);
-
- // Returns true if the given offset of the string piece counts as a newline.
- // The offset must be in the buffer.
- static bool IsNewline(const base::StringPiece& buffer, size_t offset);
-
- static bool IsIdentifierFirstChar(char c);
-
- static bool IsIdentifierContinuingChar(char c);
-
- private:
- // InputFile must outlive the tokenizer and all generated tokens.
- Tokenizer(const InputFile* input_file, Err* err);
- ~Tokenizer();
-
- std::vector<Token> Run();
-
- void AdvanceToNextToken();
- Token::Type ClassifyCurrent() const;
- void AdvanceToEndOfToken(const Location& location, Token::Type type);
-
- // Whether from this location back to the beginning of the line is only
- // whitespace. |location| should be the first character of the token to be
- // checked.
- bool AtStartOfLine(size_t location) const;
-
- bool IsCurrentWhitespace() const;
- bool IsCurrentNewline() const;
- bool IsCurrentStringTerminator(char quote_char) const;
-
- bool CanIncrement() const { return cur_ < input_.size() - 1; }
-
- // Increments the current location by one.
- void Advance();
-
- // Returns the current character in the file as a location.
- Location GetCurrentLocation() const;
-
- Err GetErrorForInvalidToken(const Location& location) const;
-
- bool done() const { return at_end() || has_error(); }
-
- bool at_end() const { return cur_ == input_.size(); }
- char cur_char() const { return input_[cur_]; }
-
- bool has_error() const { return err_->has_error(); }
-
- std::vector<Token> tokens_;
-
- const InputFile* input_file_;
- const base::StringPiece input_;
- Err* err_;
- size_t cur_; // Byte offset into input buffer.
-
- int line_number_;
- int column_number_;
-
- DISALLOW_COPY_AND_ASSIGN(Tokenizer);
-};
-
-#endif // TOOLS_GN_TOKENIZER_H_
diff --git a/chromium/tools/gn/tokenizer_unittest.cc b/chromium/tools/gn/tokenizer_unittest.cc
deleted file mode 100644
index 1f34c334662..00000000000
--- a/chromium/tools/gn/tokenizer_unittest.cc
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/input_file.h"
-#include "tools/gn/token.h"
-#include "tools/gn/tokenizer.h"
-
-namespace {
-
-struct TokenExpectation {
- Token::Type type;
- const char* value;
-};
-
-template<size_t len>
-bool CheckTokenizer(const char* input, const TokenExpectation (&expect)[len]) {
- InputFile input_file(SourceFile("/test"));
- input_file.SetContents(input);
-
- Err err;
- std::vector<Token> results = Tokenizer::Tokenize(&input_file, &err);
-
- if (results.size() != len)
- return false;
- for (size_t i = 0; i < len; i++) {
- if (expect[i].type != results[i].type())
- return false;
- if (expect[i].value != results[i].value())
- return false;
- }
- return true;
-}
-
-} // namespace
-
-TEST(Tokenizer, Empty) {
- InputFile empty_string_input(SourceFile("/test"));
- empty_string_input.SetContents("");
-
- Err err;
- std::vector<Token> results = Tokenizer::Tokenize(&empty_string_input, &err);
- EXPECT_TRUE(results.empty());
-
- InputFile whitespace_input(SourceFile("/test"));
- whitespace_input.SetContents(" \r \n \r\n");
-
- results = Tokenizer::Tokenize(&whitespace_input, &err);
- EXPECT_TRUE(results.empty());
-}
-
-TEST(Tokenizer, Identifier) {
- TokenExpectation one_ident[] = {
- { Token::IDENTIFIER, "foo" }
- };
- EXPECT_TRUE(CheckTokenizer(" foo ", one_ident));
-}
-
-TEST(Tokenizer, Integer) {
- TokenExpectation integers[] = {
- { Token::INTEGER, "123" },
- { Token::INTEGER, "-123" }
- };
- EXPECT_TRUE(CheckTokenizer(" 123 -123 ", integers));
-}
-
-TEST(Tokenizer, IntegerNoSpace) {
- TokenExpectation integers[] = {
- { Token::INTEGER, "123" },
- { Token::INTEGER, "-123" }
- };
- EXPECT_TRUE(CheckTokenizer(" 123-123 ", integers));
-}
-
-TEST(Tokenizer, String) {
- TokenExpectation strings[] = {
- { Token::STRING, "\"foo\"" },
- { Token::STRING, "\"bar\\\"baz\"" },
- { Token::STRING, "\"asdf\\\\\"" }
- };
- EXPECT_TRUE(CheckTokenizer(" \"foo\" \"bar\\\"baz\" \"asdf\\\\\" ",
- strings));
-}
-
-TEST(Tokenizer, Operator) {
- TokenExpectation operators[] = {
- { Token::MINUS, "-" },
- { Token::PLUS, "+" },
- { Token::EQUAL, "=" },
- { Token::PLUS_EQUALS, "+=" },
- { Token::MINUS_EQUALS, "-=" },
- { Token::NOT_EQUAL, "!=" },
- { Token::EQUAL_EQUAL, "==" },
- { Token::LESS_THAN, "<" },
- { Token::GREATER_THAN, ">" },
- { Token::LESS_EQUAL, "<=" },
- { Token::GREATER_EQUAL, ">=" },
- { Token::BANG, "!" },
- { Token::BOOLEAN_OR, "||" },
- { Token::BOOLEAN_AND, "&&" },
- { Token::DOT, "." },
- { Token::COMMA, "," },
- };
- EXPECT_TRUE(CheckTokenizer("- + = += -= != == < > <= >= ! || && . ,",
- operators));
-}
-
-TEST(Tokenizer, Scoper) {
- TokenExpectation scopers[] = {
- { Token::LEFT_BRACE, "{" },
- { Token::LEFT_BRACKET, "[" },
- { Token::RIGHT_BRACKET, "]" },
- { Token::RIGHT_BRACE, "}" },
- { Token::LEFT_PAREN, "(" },
- { Token::RIGHT_PAREN, ")" },
- };
- EXPECT_TRUE(CheckTokenizer("{[ ]} ()", scopers));
-}
-
-TEST(Tokenizer, FunctionCall) {
- TokenExpectation fn[] = {
- { Token::IDENTIFIER, "fun" },
- { Token::LEFT_PAREN, "(" },
- { Token::STRING, "\"foo\"" },
- { Token::RIGHT_PAREN, ")" },
- { Token::LEFT_BRACE, "{" },
- { Token::IDENTIFIER, "foo" },
- { Token::EQUAL, "=" },
- { Token::INTEGER, "12" },
- { Token::RIGHT_BRACE, "}" },
- };
- EXPECT_TRUE(CheckTokenizer("fun(\"foo\") {\nfoo = 12}", fn));
-}
-
-TEST(Tokenizer, Locations) {
- InputFile input(SourceFile("/test"));
- input.SetContents("1 2 \"three\"\n 4");
- Err err;
- std::vector<Token> results = Tokenizer::Tokenize(&input, &err);
-
- ASSERT_EQ(4u, results.size());
- ASSERT_TRUE(results[0].location() == Location(&input, 1, 1, 1));
- ASSERT_TRUE(results[1].location() == Location(&input, 1, 3, 3));
- ASSERT_TRUE(results[2].location() == Location(&input, 1, 5, 5));
- ASSERT_TRUE(results[3].location() == Location(&input, 2, 3, 8));
-}
-
-TEST(Tokenizer, ByteOffsetOfNthLine) {
- EXPECT_EQ(0u, Tokenizer::ByteOffsetOfNthLine("foo", 1));
-
- // Windows and Posix have different line endings, so check the byte at the
- // location rather than the offset.
- char input1[] = "aaa\nxaa\n\nya";
- EXPECT_EQ('x', input1[Tokenizer::ByteOffsetOfNthLine(input1, 2)]);
- EXPECT_EQ('y', input1[Tokenizer::ByteOffsetOfNthLine(input1, 4)]);
-
- char input2[3];
- input2[0] = 'a';
- input2[1] = '\n'; // Manually set to avoid Windows double-byte endings.
- input2[2] = 0;
- EXPECT_EQ(0u, Tokenizer::ByteOffsetOfNthLine(input2, 1));
- EXPECT_EQ(2u, Tokenizer::ByteOffsetOfNthLine(input2, 2));
-}
-
-TEST(Tokenizer, Comments) {
- TokenExpectation fn[] = {
- { Token::LINE_COMMENT, "# Stuff" },
- { Token::IDENTIFIER, "fun" },
- { Token::LEFT_PAREN, "(" },
- { Token::STRING, "\"foo\"" },
- { Token::RIGHT_PAREN, ")" },
- { Token::LEFT_BRACE, "{" },
- { Token::SUFFIX_COMMENT, "# Things" },
- { Token::LINE_COMMENT, "#Wee" },
- { Token::IDENTIFIER, "foo" },
- { Token::EQUAL, "=" },
- { Token::INTEGER, "12" },
- { Token::SUFFIX_COMMENT, "#Zip" },
- { Token::RIGHT_BRACE, "}" },
- };
- EXPECT_TRUE(CheckTokenizer(
- "# Stuff\n"
- "fun(\"foo\") { # Things\n"
- "#Wee\n"
- "foo = 12 #Zip\n"
- "}",
- fn));
-}
-
-TEST(Tokenizer, CommentsContinued) {
- // In the first test, the comments aren't horizontally aligned, so they're
- // considered separate. In the second test, they are, so "B" is a
- // continuation of "A" (another SUFFIX comment).
- TokenExpectation fn1[] = {
- { Token::IDENTIFIER, "fun" },
- { Token::LEFT_PAREN, "(" },
- { Token::STRING, "\"foo\"" },
- { Token::RIGHT_PAREN, ")" },
- { Token::LEFT_BRACE, "{" },
- { Token::SUFFIX_COMMENT, "# A" },
- { Token::LINE_COMMENT, "# B" },
- { Token::RIGHT_BRACE, "}" },
- };
- EXPECT_TRUE(CheckTokenizer(
- "fun(\"foo\") { # A\n"
- " # B\n"
- "}",
- fn1));
-
- TokenExpectation fn2[] = {
- { Token::IDENTIFIER, "fun" },
- { Token::LEFT_PAREN, "(" },
- { Token::STRING, "\"foo\"" },
- { Token::RIGHT_PAREN, ")" },
- { Token::LEFT_BRACE, "{" },
- { Token::SUFFIX_COMMENT, "# A" },
- { Token::SUFFIX_COMMENT, "# B" },
- { Token::RIGHT_BRACE, "}" },
- };
- EXPECT_TRUE(CheckTokenizer(
- "fun(\"foo\") { # A\n"
- " # B\n" // Note that these are aligned, the \"s move A out.
- "}",
- fn2));
-}
diff --git a/chromium/tools/gn/tool.cc b/chromium/tools/gn/tool.cc
deleted file mode 100644
index 31fb6682942..00000000000
--- a/chromium/tools/gn/tool.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/tool.h"
-
-Tool::Tool()
- : defined_from_(nullptr),
- depsformat_(DEPS_GCC),
- precompiled_header_type_(PCH_NONE),
- restat_(false),
- complete_(false) {
-}
-
-Tool::~Tool() = default;
-
-void Tool::SetComplete() {
- DCHECK(!complete_);
- complete_ = true;
-
- command_.FillRequiredTypes(&substitution_bits_);
- depfile_.FillRequiredTypes(&substitution_bits_);
- description_.FillRequiredTypes(&substitution_bits_);
- outputs_.FillRequiredTypes(&substitution_bits_);
- link_output_.FillRequiredTypes(&substitution_bits_);
- depend_output_.FillRequiredTypes(&substitution_bits_);
- rspfile_.FillRequiredTypes(&substitution_bits_);
- rspfile_content_.FillRequiredTypes(&substitution_bits_);
-}
diff --git a/chromium/tools/gn/tool.h b/chromium/tools/gn/tool.h
deleted file mode 100644
index f44af2e59f4..00000000000
--- a/chromium/tools/gn/tool.h
+++ /dev/null
@@ -1,236 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_TOOL_H_
-#define TOOLS_GN_TOOL_H_
-
-#include <string>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "tools/gn/label.h"
-#include "tools/gn/label_ptr.h"
-#include "tools/gn/substitution_list.h"
-#include "tools/gn/substitution_pattern.h"
-
-class ParseNode;
-class Pool;
-
-class Tool {
- public:
- enum DepsFormat {
- DEPS_GCC = 0,
- DEPS_MSVC = 1
- };
-
- enum PrecompiledHeaderType {
- PCH_NONE = 0,
- PCH_GCC = 1,
- PCH_MSVC = 2
- };
-
- Tool();
- ~Tool();
-
- const ParseNode* defined_from() const { return defined_from_; }
- void set_defined_from(const ParseNode* df) { defined_from_ = df; }
-
- // Getters/setters ----------------------------------------------------------
- //
- // After the tool has had its attributes set, the caller must call
- // SetComplete(), at which point no other changes can be made.
-
- // Command to run.
- const SubstitutionPattern& command() const {
- return command_;
- }
- void set_command(SubstitutionPattern cmd) {
- DCHECK(!complete_);
- command_ = std::move(cmd);
- }
-
- // Should include a leading "." if nonempty.
- const std::string& default_output_extension() const {
- return default_output_extension_;
- }
- void set_default_output_extension(std::string ext) {
- DCHECK(!complete_);
- DCHECK(ext.empty() || ext[0] == '.');
- default_output_extension_ = std::move(ext);
- }
-
- const SubstitutionPattern& default_output_dir() const {
- return default_output_dir_;
- }
- void set_default_output_dir(SubstitutionPattern dir) {
- DCHECK(!complete_);
- default_output_dir_ = std::move(dir);
- }
-
- // Dependency file (if supported).
- const SubstitutionPattern& depfile() const {
- return depfile_;
- }
- void set_depfile(SubstitutionPattern df) {
- DCHECK(!complete_);
- depfile_ = std::move(df);
- }
-
- DepsFormat depsformat() const {
- return depsformat_;
- }
- void set_depsformat(DepsFormat f) {
- DCHECK(!complete_);
- depsformat_ = f;
- }
-
- PrecompiledHeaderType precompiled_header_type() const {
- return precompiled_header_type_;
- }
- void set_precompiled_header_type(PrecompiledHeaderType pch_type) {
- precompiled_header_type_ = pch_type;
- }
-
- const SubstitutionPattern& description() const {
- return description_;
- }
- void set_description(SubstitutionPattern desc) {
- DCHECK(!complete_);
- description_ = std::move(desc);
- }
-
- const std::string& lib_switch() const {
- return lib_switch_;
- }
- void set_lib_switch(std::string s) {
- DCHECK(!complete_);
- lib_switch_ = std::move(s);
- }
-
- const std::string& lib_dir_switch() const {
- return lib_dir_switch_;
- }
- void set_lib_dir_switch(std::string s) {
- DCHECK(!complete_);
- lib_dir_switch_ = std::move(s);
- }
-
- const SubstitutionList& outputs() const {
- return outputs_;
- }
- void set_outputs(SubstitutionList out) {
- DCHECK(!complete_);
- outputs_ = std::move(out);
- }
-
- // Should match files in the outputs() if nonempty.
- const SubstitutionPattern& link_output() const {
- return link_output_;
- }
- void set_link_output(SubstitutionPattern link_out) {
- DCHECK(!complete_);
- link_output_ = std::move(link_out);
- }
-
- const SubstitutionPattern& depend_output() const {
- return depend_output_;
- }
- void set_depend_output(SubstitutionPattern dep_out) {
- DCHECK(!complete_);
- depend_output_ = std::move(dep_out);
- }
-
- const SubstitutionList& runtime_outputs() const {
- return runtime_outputs_;
- }
- void set_runtime_outputs(SubstitutionList run_out) {
- DCHECK(!complete_);
- runtime_outputs_ = std::move(run_out);
- }
-
- const std::string& output_prefix() const {
- return output_prefix_;
- }
- void set_output_prefix(std::string s) {
- DCHECK(!complete_);
- output_prefix_ = std::move(s);
- }
-
- bool restat() const {
- return restat_;
- }
- void set_restat(bool r) {
- DCHECK(!complete_);
- restat_ = r;
- }
-
- const SubstitutionPattern& rspfile() const {
- return rspfile_;
- }
- void set_rspfile(SubstitutionPattern rsp) {
- DCHECK(!complete_);
- rspfile_ = std::move(rsp);
- }
-
- const SubstitutionPattern& rspfile_content() const {
- return rspfile_content_;
- }
- void set_rspfile_content(SubstitutionPattern content) {
- DCHECK(!complete_);
- rspfile_content_ = std::move(content);
- }
-
- const LabelPtrPair<Pool>& pool() const { return pool_; }
- void set_pool(LabelPtrPair<Pool> pool) { pool_ = std::move(pool); }
-
- // Other functions ----------------------------------------------------------
-
- // Called when the toolchain is saving this tool, after everything is filled
- // in.
- void SetComplete();
-
- // Returns true if this tool has separate outputs for dependency tracking
- // and linking.
- bool has_separate_solink_files() const {
- return !link_output_.empty() || !depend_output_.empty();
- }
-
- // Substitutions required by this tool.
- const SubstitutionBits& substitution_bits() const {
- DCHECK(complete_);
- return substitution_bits_;
- }
-
- bool OnResolved(Err* err);
-
- private:
- const ParseNode* defined_from_;
-
- SubstitutionPattern command_;
- std::string default_output_extension_;
- SubstitutionPattern default_output_dir_;
- SubstitutionPattern depfile_;
- DepsFormat depsformat_;
- PrecompiledHeaderType precompiled_header_type_;
- SubstitutionPattern description_;
- std::string lib_switch_;
- std::string lib_dir_switch_;
- SubstitutionList outputs_;
- SubstitutionPattern link_output_;
- SubstitutionPattern depend_output_;
- SubstitutionList runtime_outputs_;
- std::string output_prefix_;
- bool restat_;
- SubstitutionPattern rspfile_;
- SubstitutionPattern rspfile_content_;
- LabelPtrPair<Pool> pool_;
-
- bool complete_;
-
- SubstitutionBits substitution_bits_;
-
- DISALLOW_COPY_AND_ASSIGN(Tool);
-};
-
-#endif // TOOLS_GN_TOOL_H_
diff --git a/chromium/tools/gn/toolchain.cc b/chromium/tools/gn/toolchain.cc
deleted file mode 100644
index 879acd94af6..00000000000
--- a/chromium/tools/gn/toolchain.cc
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/toolchain.h"
-
-#include <stddef.h>
-#include <string.h>
-#include <utility>
-
-#include "base/logging.h"
-#include "tools/gn/target.h"
-#include "tools/gn/value.h"
-
-const char* Toolchain::kToolCc = "cc";
-const char* Toolchain::kToolCxx = "cxx";
-const char* Toolchain::kToolObjC = "objc";
-const char* Toolchain::kToolObjCxx = "objcxx";
-const char* Toolchain::kToolRc = "rc";
-const char* Toolchain::kToolAsm = "asm";
-const char* Toolchain::kToolAlink = "alink";
-const char* Toolchain::kToolSolink = "solink";
-const char* Toolchain::kToolSolinkModule = "solink_module";
-const char* Toolchain::kToolLink = "link";
-const char* Toolchain::kToolStamp = "stamp";
-const char* Toolchain::kToolCopy = "copy";
-const char* Toolchain::kToolCopyBundleData = "copy_bundle_data";
-const char* Toolchain::kToolCompileXCAssets = "compile_xcassets";
-const char* Toolchain::kToolAction = "action";
-
-Toolchain::Toolchain(const Settings* settings,
- const Label& label,
- const std::set<SourceFile>& build_dependency_files)
- : Item(settings, label, build_dependency_files), setup_complete_(false) {}
-
-Toolchain::~Toolchain() = default;
-
-Toolchain* Toolchain::AsToolchain() {
- return this;
-}
-
-const Toolchain* Toolchain::AsToolchain() const {
- return this;
-}
-
-// static
-Toolchain::ToolType Toolchain::ToolNameToType(const base::StringPiece& str) {
- if (str == kToolCc) return TYPE_CC;
- if (str == kToolCxx) return TYPE_CXX;
- if (str == kToolObjC) return TYPE_OBJC;
- if (str == kToolObjCxx) return TYPE_OBJCXX;
- if (str == kToolRc) return TYPE_RC;
- if (str == kToolAsm) return TYPE_ASM;
- if (str == kToolAlink) return TYPE_ALINK;
- if (str == kToolSolink) return TYPE_SOLINK;
- if (str == kToolSolinkModule) return TYPE_SOLINK_MODULE;
- if (str == kToolLink) return TYPE_LINK;
- if (str == kToolStamp) return TYPE_STAMP;
- if (str == kToolCopy) return TYPE_COPY;
- if (str == kToolCopyBundleData) return TYPE_COPY_BUNDLE_DATA;
- if (str == kToolCompileXCAssets) return TYPE_COMPILE_XCASSETS;
- if (str == kToolAction) return TYPE_ACTION;
- return TYPE_NONE;
-}
-
-// static
-std::string Toolchain::ToolTypeToName(ToolType type) {
- switch (type) {
- case TYPE_CC: return kToolCc;
- case TYPE_CXX: return kToolCxx;
- case TYPE_OBJC: return kToolObjC;
- case TYPE_OBJCXX: return kToolObjCxx;
- case TYPE_RC: return kToolRc;
- case TYPE_ASM: return kToolAsm;
- case TYPE_ALINK: return kToolAlink;
- case TYPE_SOLINK: return kToolSolink;
- case TYPE_SOLINK_MODULE: return kToolSolinkModule;
- case TYPE_LINK: return kToolLink;
- case TYPE_STAMP: return kToolStamp;
- case TYPE_COPY: return kToolCopy;
- case TYPE_COPY_BUNDLE_DATA: return kToolCopyBundleData;
- case TYPE_COMPILE_XCASSETS: return kToolCompileXCAssets;
- case TYPE_ACTION: return kToolAction;
- default:
- NOTREACHED();
- return std::string();
- }
-}
-
-Tool* Toolchain::GetTool(ToolType type) {
- DCHECK(type != TYPE_NONE);
- return tools_[static_cast<size_t>(type)].get();
-}
-
-const Tool* Toolchain::GetTool(ToolType type) const {
- DCHECK(type != TYPE_NONE);
- return tools_[static_cast<size_t>(type)].get();
-}
-
-void Toolchain::SetTool(ToolType type, std::unique_ptr<Tool> t) {
- DCHECK(type != TYPE_NONE);
- DCHECK(!tools_[type].get());
- t->SetComplete();
- tools_[type] = std::move(t);
-}
-
-void Toolchain::ToolchainSetupComplete() {
- // Collect required bits from all tools.
- for (const auto& tool : tools_) {
- if (tool)
- substitution_bits_.MergeFrom(tool->substitution_bits());
- }
-
- setup_complete_ = true;
-}
-
-// static
-Toolchain::ToolType Toolchain::GetToolTypeForSourceType(SourceFileType type) {
- switch (type) {
- case SOURCE_C:
- return TYPE_CC;
- case SOURCE_CPP:
- return TYPE_CXX;
- case SOURCE_M:
- return TYPE_OBJC;
- case SOURCE_MM:
- return TYPE_OBJCXX;
- case SOURCE_ASM:
- case SOURCE_S:
- return TYPE_ASM;
- case SOURCE_RC:
- return TYPE_RC;
- case SOURCE_UNKNOWN:
- case SOURCE_H:
- case SOURCE_O:
- case SOURCE_DEF:
- return TYPE_NONE;
- default:
- NOTREACHED();
- return TYPE_NONE;
- }
-}
-
-const Tool* Toolchain::GetToolForSourceType(SourceFileType type) {
- return tools_[GetToolTypeForSourceType(type)].get();
-}
-
-// static
-Toolchain::ToolType Toolchain::GetToolTypeForTargetFinalOutput(
- const Target* target) {
- // The contents of this list might be suprising (i.e. stamp tool for copy
- // rules). See the header for why.
- switch (target->output_type()) {
- case Target::GROUP:
- return TYPE_STAMP;
- case Target::EXECUTABLE:
- return Toolchain::TYPE_LINK;
- case Target::SHARED_LIBRARY:
- return Toolchain::TYPE_SOLINK;
- case Target::LOADABLE_MODULE:
- return Toolchain::TYPE_SOLINK_MODULE;
- case Target::STATIC_LIBRARY:
- return Toolchain::TYPE_ALINK;
- case Target::SOURCE_SET:
- return TYPE_STAMP;
- case Target::ACTION:
- case Target::ACTION_FOREACH:
- case Target::BUNDLE_DATA:
- case Target::CREATE_BUNDLE:
- case Target::COPY_FILES:
- return TYPE_STAMP;
- default:
- NOTREACHED();
- return Toolchain::TYPE_NONE;
- }
-}
-
-const Tool* Toolchain::GetToolForTargetFinalOutput(const Target* target) const {
- return tools_[GetToolTypeForTargetFinalOutput(target)].get();
-}
diff --git a/chromium/tools/gn/toolchain.h b/chromium/tools/gn/toolchain.h
deleted file mode 100644
index 1e9bc2e06e9..00000000000
--- a/chromium/tools/gn/toolchain.h
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_TOOLCHAIN_H_
-#define TOOLS_GN_TOOLCHAIN_H_
-
-#include <memory>
-
-#include "base/logging.h"
-#include "base/strings/string_piece.h"
-#include "tools/gn/item.h"
-#include "tools/gn/label_ptr.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/source_file_type.h"
-#include "tools/gn/substitution_type.h"
-#include "tools/gn/tool.h"
-#include "tools/gn/value.h"
-
-// Holds information on a specific toolchain. This data is filled in when we
-// encounter a toolchain definition.
-//
-// This class is an Item so it can participate in dependency management. In
-// particular, when a target uses a toolchain, it should have a dependency on
-// that toolchain's object so that we can be sure we loaded the toolchain
-// before generating the build for that target.
-//
-// Note on threadsafety: The label of the toolchain never changes so can
-// safely be accessed from any thread at any time (we do this when asking for
-// the toolchain name). But the values in the toolchain do, so these can't
-// be accessed until this Item is resolved.
-class Toolchain : public Item {
- public:
- enum ToolType {
- TYPE_NONE = 0,
- TYPE_CC,
- TYPE_CXX,
- TYPE_OBJC,
- TYPE_OBJCXX,
- TYPE_RC,
- TYPE_ASM,
- TYPE_ALINK,
- TYPE_SOLINK,
- TYPE_SOLINK_MODULE,
- TYPE_LINK,
- TYPE_STAMP,
- TYPE_COPY,
- TYPE_COPY_BUNDLE_DATA,
- TYPE_COMPILE_XCASSETS,
- TYPE_ACTION,
-
- TYPE_NUMTYPES // Must be last.
- };
-
- static const char* kToolCc;
- static const char* kToolCxx;
- static const char* kToolObjC;
- static const char* kToolObjCxx;
- static const char* kToolRc;
- static const char* kToolAsm;
- static const char* kToolAlink;
- static const char* kToolSolink;
- static const char* kToolSolinkModule;
- static const char* kToolLink;
- static const char* kToolStamp;
- static const char* kToolCopy;
- static const char* kToolCopyBundleData;
- static const char* kToolCompileXCAssets;
- static const char* kToolAction;
-
- // The Settings of an Item is always the context in which the Item was
- // defined. For a toolchain this is confusing because this is NOT the
- // settings object that applies to the things in the toolchain.
- //
- // To get the Settings object corresponding to objects loaded in the context
- // of this toolchain (probably what you want instead), see
- // Loader::GetToolchainSettings(). Many toolchain objects may be created in a
- // given build, but only a few might be used, and the Loader is in charge of
- // this process.
- //
- // We also track the set of build files that may affect this target, please
- // refer to Scope for how this is determined.
- Toolchain(const Settings* settings,
- const Label& label,
- const std::set<SourceFile>& build_dependency_files = {});
- ~Toolchain() override;
-
- // Item overrides.
- Toolchain* AsToolchain() override;
- const Toolchain* AsToolchain() const override;
-
- // Returns TYPE_NONE on failure.
- static ToolType ToolNameToType(const base::StringPiece& str);
- static std::string ToolTypeToName(ToolType type);
-
- // Returns null if the tool hasn't been defined.
- Tool* GetTool(ToolType type);
- const Tool* GetTool(ToolType type) const;
-
- // Set a tool. When all tools are configured, you should call
- // ToolchainSetupComplete().
- void SetTool(ToolType type, std::unique_ptr<Tool> t);
-
- // Does final setup on the toolchain once all tools are known.
- void ToolchainSetupComplete();
-
- // Targets that must be resolved before compiling any targets.
- const LabelTargetVector& deps() const { return deps_; }
- LabelTargetVector& deps() { return deps_; }
-
- // Specifies build argument overrides that will be set on the base scope. It
- // will be as if these arguments were passed in on the command line. This
- // allows a toolchain to override the OS type of the default toolchain or
- // pass in other settings.
- Scope::KeyValueMap& args() { return args_; }
- const Scope::KeyValueMap& args() const { return args_; }
-
- // Returns the tool for compiling the given source file type.
- static ToolType GetToolTypeForSourceType(SourceFileType type);
- const Tool* GetToolForSourceType(SourceFileType type);
-
- // Returns the tool that produces the final output for the given target type.
- // This isn't necessarily the tool you would expect. For copy target, this
- // will return the stamp tool instead since the final output of a copy
- // target is to stamp the set of copies done so there is one output.
- static ToolType GetToolTypeForTargetFinalOutput(const Target* target);
- const Tool* GetToolForTargetFinalOutput(const Target* target) const;
-
- const SubstitutionBits& substitution_bits() const {
- DCHECK(setup_complete_);
- return substitution_bits_;
- }
-
- private:
- std::unique_ptr<Tool> tools_[TYPE_NUMTYPES];
-
- bool setup_complete_;
-
- // Substitutions used by the tools in this toolchain.
- SubstitutionBits substitution_bits_;
-
- LabelTargetVector deps_;
- Scope::KeyValueMap args_;
-};
-
-#endif // TOOLS_GN_TOOLCHAIN_H_
diff --git a/chromium/tools/gn/trace.cc b/chromium/tools/gn/trace.cc
deleted file mode 100644
index f290613f061..00000000000
--- a/chromium/tools/gn/trace.cc
+++ /dev/null
@@ -1,339 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/trace.h"
-
-#include <stddef.h>
-
-#include <algorithm>
-#include <map>
-#include <sstream>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/json/string_escape.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/lock.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/label.h"
-
-namespace {
-
-class TraceLog {
- public:
- TraceLog() {
- events_.reserve(16384);
- }
- // Trace items leaked intentionally.
-
- void Add(TraceItem* item) {
- base::AutoLock lock(lock_);
- events_.push_back(item);
- }
-
- // Returns a copy for threadsafety.
- std::vector<TraceItem*> events() const { return events_; }
-
- private:
- base::Lock lock_;
-
- std::vector<TraceItem*> events_;
-
- DISALLOW_COPY_AND_ASSIGN(TraceLog);
-};
-
-TraceLog* trace_log = nullptr;
-
-struct Coalesced {
- Coalesced() : name_ptr(nullptr), total_duration(0.0), count(0) {}
-
- const std::string* name_ptr; // Pointer to a string with the name in it.
- double total_duration;
- int count;
-};
-
-bool DurationGreater(const TraceItem* a, const TraceItem* b) {
- return a->delta() > b->delta();
-}
-
-bool CoalescedDurationGreater(const Coalesced& a, const Coalesced& b) {
- return a.total_duration > b.total_duration;
-}
-
-void SummarizeParses(std::vector<const TraceItem*>& loads,
- std::ostream& out) {
- out << "File parse times: (time in ms, name)\n";
-
- std::sort(loads.begin(), loads.end(), &DurationGreater);
- for (auto* load : loads) {
- out << base::StringPrintf(" %8.2f ", load->delta().InMillisecondsF());
- out << load->name() << std::endl;
- }
-}
-
-void SummarizeCoalesced(std::vector<const TraceItem*>& items,
- std::ostream& out) {
- // Group by file name.
- std::map<std::string, Coalesced> coalesced;
- for (auto* item : items) {
- Coalesced& c = coalesced[item->name()];
- c.name_ptr = &item->name();
- c.total_duration += item->delta().InMillisecondsF();
- c.count++;
- }
-
- // Sort by duration.
- std::vector<Coalesced> sorted;
- for (const auto& pair : coalesced)
- sorted.push_back(pair.second);
- std::sort(sorted.begin(), sorted.end(), &CoalescedDurationGreater);
-
- for (const auto& cur : sorted) {
- out << base::StringPrintf(" %8.2f %d ", cur.total_duration, cur.count);
- out << *cur.name_ptr << std::endl;
- }
-}
-
-void SummarizeFileExecs(std::vector<const TraceItem*>& execs,
- std::ostream& out) {
- out << "File execute times: (total time in ms, # executions, name)\n";
- SummarizeCoalesced(execs, out);
-}
-
-void SummarizeScriptExecs(std::vector<const TraceItem*>& execs,
- std::ostream& out) {
- out << "Script execute times: (total time in ms, # executions, name)\n";
- SummarizeCoalesced(execs, out);
-}
-
-} // namespace
-
-TraceItem::TraceItem(Type type,
- const std::string& name,
- base::PlatformThreadId thread_id)
- : type_(type),
- name_(name),
- thread_id_(thread_id) {
-}
-
-TraceItem::~TraceItem() = default;
-
-ScopedTrace::ScopedTrace(TraceItem::Type t, const std::string& name)
- : item_(nullptr), done_(false) {
- if (trace_log) {
- item_ = new TraceItem(t, name, base::PlatformThread::CurrentId());
- item_->set_begin(base::TimeTicks::Now());
- }
-}
-
-ScopedTrace::ScopedTrace(TraceItem::Type t, const Label& label)
- : item_(nullptr), done_(false) {
- if (trace_log) {
- item_ = new TraceItem(t, label.GetUserVisibleName(false),
- base::PlatformThread::CurrentId());
- item_->set_begin(base::TimeTicks::Now());
- }
-}
-
-ScopedTrace::~ScopedTrace() {
- Done();
-}
-
-void ScopedTrace::SetToolchain(const Label& label) {
- if (item_)
- item_->set_toolchain(label.GetUserVisibleName(false));
-}
-
-void ScopedTrace::SetCommandLine(const base::CommandLine& cmdline) {
- if (item_)
- item_->set_cmdline(FilePathToUTF8(cmdline.GetArgumentsString()));
-}
-
-void ScopedTrace::Done() {
- if (!done_) {
- done_ = true;
- if (trace_log) {
- item_->set_end(base::TimeTicks::Now());
- AddTrace(item_);
- }
- }
-}
-
-void EnableTracing() {
- if (!trace_log)
- trace_log = new TraceLog;
-}
-
-bool TracingEnabled() {
- return !!trace_log;
-}
-
-void AddTrace(TraceItem* item) {
- trace_log->Add(item);
-}
-
-std::string SummarizeTraces() {
- if (!trace_log)
- return std::string();
-
- std::vector<TraceItem*> events = trace_log->events();
-
- // Classify all events.
- std::vector<const TraceItem*> parses;
- std::vector<const TraceItem*> file_execs;
- std::vector<const TraceItem*> script_execs;
- std::vector<const TraceItem*> check_headers;
- int headers_checked = 0;
- for (auto* event : events) {
- switch (event->type()) {
- case TraceItem::TRACE_FILE_PARSE:
- parses.push_back(event);
- break;
- case TraceItem::TRACE_FILE_EXECUTE:
- file_execs.push_back(event);
- break;
- case TraceItem::TRACE_SCRIPT_EXECUTE:
- script_execs.push_back(event);
- break;
- case TraceItem::TRACE_CHECK_HEADERS:
- check_headers.push_back(event);
- break;
- case TraceItem::TRACE_CHECK_HEADER:
- headers_checked++;
- break;
- case TraceItem::TRACE_IMPORT_LOAD:
- case TraceItem::TRACE_IMPORT_BLOCK:
- case TraceItem::TRACE_SETUP:
- case TraceItem::TRACE_FILE_LOAD:
- case TraceItem::TRACE_FILE_WRITE:
- case TraceItem::TRACE_DEFINE_TARGET:
- case TraceItem::TRACE_ON_RESOLVED:
- break; // Ignore these for the summary.
- }
- }
-
- std::ostringstream out;
- SummarizeParses(parses, out);
- out << std::endl;
- SummarizeFileExecs(file_execs, out);
- out << std::endl;
- SummarizeScriptExecs(script_execs, out);
- out << std::endl;
-
- // Generally there will only be one header check, but it's theoretically
- // possible for more than one to run if more than one build is going in
- // parallel. Just report the total of all of them.
- if (!check_headers.empty()) {
- double check_headers_time = 0;
- for (auto* cur : check_headers)
- check_headers_time += cur->delta().InMillisecondsF();
-
- out << "Header check time: (total time in ms, files checked)\n";
- out << base::StringPrintf(" %8.2f %d\n",
- check_headers_time, headers_checked);
- }
-
- return out.str();
-}
-
-void SaveTraces(const base::FilePath& file_name) {
- std::ostringstream out;
-
- out << "{\"traceEvents\":[";
-
- std::string quote_buffer; // Allocate outside loop to prevent reallocationg.
-
- // Write main thread metadata (assume this is being written on the main
- // thread).
- out << "{\"pid\":0,\"tid\":" << base::PlatformThread::CurrentId();
- out << ",\"ts\":0,\"ph\":\"M\",";
- out << "\"name\":\"thread_name\",\"args\":{\"name\":\"Main thread\"}},";
-
- std::vector<TraceItem*> events = trace_log->events();
- for (size_t i = 0; i < events.size(); i++) {
- const TraceItem& item = *events[i];
-
- if (i != 0)
- out << ",";
- out << "{\"pid\":0,\"tid\":" << item.thread_id();
- out << ",\"ts\":" << item.begin().ToInternalValue();
- out << ",\"ph\":\"X\""; // "X" = complete event with begin & duration.
- out << ",\"dur\":" << item.delta().InMicroseconds();
-
- quote_buffer.resize(0);
- base::EscapeJSONString(item.name(), true, &quote_buffer);
- out << ",\"name\":" << quote_buffer;
-
- out << ",\"cat\":";
- switch (item.type()) {
- case TraceItem::TRACE_SETUP:
- out << "\"setup\"";
- break;
- case TraceItem::TRACE_FILE_LOAD:
- out << "\"load\"";
- break;
- case TraceItem::TRACE_FILE_PARSE:
- out << "\"parse\"";
- break;
- case TraceItem::TRACE_FILE_EXECUTE:
- out << "\"file_exec\"";
- break;
- case TraceItem::TRACE_FILE_WRITE:
- out << "\"file_write\"";
- break;
- case TraceItem::TRACE_IMPORT_LOAD:
- out << "\"import_load\"";
- break;
- case TraceItem::TRACE_IMPORT_BLOCK:
- out << "\"import_block\"";
- break;
- case TraceItem::TRACE_SCRIPT_EXECUTE:
- out << "\"script_exec\"";
- break;
- case TraceItem::TRACE_DEFINE_TARGET:
- out << "\"define\"";
- break;
- case TraceItem::TRACE_ON_RESOLVED:
- out << "\"onresolved\"";
- break;
- case TraceItem::TRACE_CHECK_HEADER:
- out << "\"hdr\"";
- break;
- case TraceItem::TRACE_CHECK_HEADERS:
- out << "\"header_check\"";
- break;
- }
-
- if (!item.toolchain().empty() || !item.cmdline().empty()) {
- out << ",\"args\":{";
- bool needs_comma = false;
- if (!item.toolchain().empty()) {
- quote_buffer.resize(0);
- base::EscapeJSONString(item.toolchain(), true, &quote_buffer);
- out << "\"toolchain\":" << quote_buffer;
- needs_comma = true;
- }
- if (!item.cmdline().empty()) {
- quote_buffer.resize(0);
- base::EscapeJSONString(item.cmdline(), true, &quote_buffer);
- if (needs_comma)
- out << ",";
- out << "\"cmdline\":" << quote_buffer;
- needs_comma = true;
- }
- out << "}";
- }
- out << "}";
- }
-
- out << "]}";
-
- std::string out_str = out.str();
- base::WriteFile(file_name, out_str.data(),
- static_cast<int>(out_str.size()));
-}
diff --git a/chromium/tools/gn/trace.h b/chromium/tools/gn/trace.h
deleted file mode 100644
index d2116410bd5..00000000000
--- a/chromium/tools/gn/trace.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_TRACE_H_
-#define TOOLS_GN_TRACE_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-
-class Label;
-
-namespace base {
-class CommandLine;
-class FilePath;
-}
-
-class TraceItem {
- public:
- enum Type {
- TRACE_SETUP,
- TRACE_FILE_LOAD,
- TRACE_FILE_PARSE,
- TRACE_FILE_EXECUTE,
- TRACE_FILE_WRITE,
- TRACE_IMPORT_LOAD,
- TRACE_IMPORT_BLOCK,
- TRACE_SCRIPT_EXECUTE,
- TRACE_DEFINE_TARGET,
- TRACE_ON_RESOLVED,
- TRACE_CHECK_HEADER, // One file.
- TRACE_CHECK_HEADERS, // All files.
- };
-
- TraceItem(Type type,
- const std::string& name,
- base::PlatformThreadId thread_id);
- ~TraceItem();
-
- Type type() const { return type_; }
- const std::string& name() const { return name_; }
- base::PlatformThreadId thread_id() const { return thread_id_; }
-
- base::TimeTicks begin() const { return begin_; }
- void set_begin(base::TimeTicks b) { begin_ = b; }
- base::TimeTicks end() const { return end_; }
- void set_end(base::TimeTicks e) { end_ = e; }
-
- base::TimeDelta delta() const { return end_ - begin_; }
-
- // Optional toolchain label.
- const std::string& toolchain() const { return toolchain_; }
- void set_toolchain(const std::string& t) { toolchain_ = t; }
-
- // Optional command line.
- const std::string& cmdline() const { return cmdline_; }
- void set_cmdline(const std::string& c) { cmdline_ = c; }
-
- private:
- Type type_;
- std::string name_;
- base::PlatformThreadId thread_id_;
-
- base::TimeTicks begin_;
- base::TimeTicks end_;
-
- std::string toolchain_;
- std::string cmdline_;
-};
-
-class ScopedTrace {
- public:
- ScopedTrace(TraceItem::Type t, const std::string& name);
- ScopedTrace(TraceItem::Type t, const Label& label);
- ~ScopedTrace();
-
- void SetToolchain(const Label& label);
- void SetCommandLine(const base::CommandLine& cmdline);
-
- void Done();
-
- private:
- TraceItem* item_;
- bool done_;
-};
-
-// Call to turn tracing on. It's off by default.
-void EnableTracing();
-
-// Returns whether tracing is enabled.
-bool TracingEnabled();
-
-// Adds a trace event to the log. Takes ownership of the pointer.
-void AddTrace(TraceItem* item);
-
-// Returns a summary of the current traces, or the empty string if tracing is
-// not enabled.
-std::string SummarizeTraces();
-
-// Saves the current traces to the given filename in JSON format.
-void SaveTraces(const base::FilePath& file_name);
-
-#endif // TOOLS_GN_TRACE_H_
diff --git a/chromium/tools/gn/tutorial/hello.cc b/chromium/tools/gn/tutorial/hello.cc
deleted file mode 100644
index 8b25cd9db82..00000000000
--- a/chromium/tools/gn/tutorial/hello.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/tutorial/hello.h"
-
-#include <stdio.h>
-
-void Hello(const char* who) {
- printf("Hello, %s.\n", who);
-}
-
-#if defined(TWO_PEOPLE)
-void Hello(const char* one, const char* two) {
- printf("Hello, %s and %s.\n", one, two);
-}
-#endif
diff --git a/chromium/tools/gn/tutorial/hello.h b/chromium/tools/gn/tutorial/hello.h
deleted file mode 100644
index 253fe241048..00000000000
--- a/chromium/tools/gn/tutorial/hello.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_TUTORIAL_HELLO_H_
-#define TOOLS_GN_TUTORIAL_HELLO_H_
-
-void Hello(const char* who);
-
-#if defined(TWO_PEOPLE)
-void Hello(const char* one, const char* two);
-#endif
-
-#endif // TOOLS_GN_TUTORIAL_HELLO_H_
diff --git a/chromium/tools/gn/tutorial/hello_world.cc b/chromium/tools/gn/tutorial/hello_world.cc
deleted file mode 100644
index 84ffc3fc387..00000000000
--- a/chromium/tools/gn/tutorial/hello_world.cc
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdio.h>
-
-int main() {
- printf("Hello, world.\n");
- return 0;
-}
diff --git a/chromium/tools/gn/tutorial/say_hello.cc b/chromium/tools/gn/tutorial/say_hello.cc
deleted file mode 100644
index d8092bd4dae..00000000000
--- a/chromium/tools/gn/tutorial/say_hello.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/tutorial/hello.h"
-
-int main() {
-#if defined(TWO_PEOPLE)
- Hello("Bill", "Joy");
-#else
- Hello("everyone");
-#endif
- return 0;
-}
diff --git a/chromium/tools/gn/unique_vector.h b/chromium/tools/gn/unique_vector.h
deleted file mode 100644
index e629ce2da7c..00000000000
--- a/chromium/tools/gn/unique_vector.h
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_UNIQUE_VECTOR_H_
-#define TOOLS_GN_UNIQUE_VECTOR_H_
-
-#include <stddef.h>
-
-#include <algorithm>
-
-#include "base/containers/hash_tables.h"
-
-namespace internal {
-
-// This lass allows us to insert things by reference into a hash table which
-// avoids copies. The hash function of a UniquifyRef is that of the object it
-// points to.
-//
-// There are two ways it can store data: (1) by (vector*, index) which is used
-// to refer to the array in UniqueVector and make it work even when the
-// underlying vector is reallocated; (2) by T* which is used to do lookups
-// into the hash table of things that aren't in a vector yet.
-//
-// It also caches the hash value which allows us to query and then insert
-// without recomputing the hash.
-template<typename T>
-class UniquifyRef {
- public:
- UniquifyRef()
- : value_(nullptr),
- vect_(nullptr),
- index_(static_cast<size_t>(-1)),
- hash_val_(0) {
- }
-
- // Initialize with a pointer to a value.
- explicit UniquifyRef(const T* v)
- : value_(v),
- vect_(nullptr),
- index_(static_cast<size_t>(-1)) {
- FillHashValue();
- }
-
- // Initialize with an array + index.
- UniquifyRef(const std::vector<T>* v, size_t i)
- : value_(nullptr),
- vect_(v),
- index_(i) {
- FillHashValue();
- }
-
- // Initialize with an array + index and a known hash value to prevent
- // re-hashing.
- UniquifyRef(const std::vector<T>* v, size_t i, size_t hash_value)
- : value_(nullptr),
- vect_(v),
- index_(i),
- hash_val_(hash_value) {
- }
-
- const T& value() const { return value_ ? *value_ : (*vect_)[index_]; }
- size_t hash_val() const { return hash_val_; }
- size_t index() const { return index_; }
-
- private:
- void FillHashValue() {
- BASE_HASH_NAMESPACE::hash<T> h;
- hash_val_ = h(value());
- }
-
- // When non-null, points to the object.
- const T* value_;
-
- // When value is null these are used.
- const std::vector<T>* vect_;
- size_t index_;
-
- size_t hash_val_;
-};
-
-template<typename T> inline bool operator==(const UniquifyRef<T>& a,
- const UniquifyRef<T>& b) {
- return a.value() == b.value();
-}
-
-template<typename T> inline bool operator<(const UniquifyRef<T>& a,
- const UniquifyRef<T>& b) {
- return a.value() < b.value();
-}
-
-} // namespace internal
-
-namespace BASE_HASH_NAMESPACE {
-
-template<typename T> struct hash< internal::UniquifyRef<T> > {
- std::size_t operator()(const internal::UniquifyRef<T>& v) const {
- return v.hash_val();
- }
-};
-
-} // namespace BASE_HASH_NAMESPACE
-
-// An ordered set optimized for GN's usage. Such sets are used to store lists
-// of configs and libraries, and are appended to but not randomly inserted
-// into.
-template<typename T>
-class UniqueVector {
- public:
- typedef std::vector<T> Vector;
- typedef typename Vector::iterator iterator;
- typedef typename Vector::const_iterator const_iterator;
-
- const Vector& vector() const { return vector_; }
- size_t size() const { return vector_.size(); }
- bool empty() const { return vector_.empty(); }
- void clear() { vector_.clear(); set_.clear(); }
- void reserve(size_t s) { vector_.reserve(s); }
-
- const T& operator[](size_t index) const { return vector_[index]; }
-
- const_iterator begin() const { return vector_.begin(); }
- iterator begin() { return vector_.begin(); }
- const_iterator end() const { return vector_.end(); }
- iterator end() { return vector_.end(); }
-
- // Returns true if the item was appended, false if it already existed (and
- // thus the vector was not modified).
- bool push_back(const T& t) {
- Ref ref(&t);
- if (set_.find(ref) != set_.end())
- return false; // Already have this one.
-
- vector_.push_back(t);
- set_.insert(Ref(&vector_, vector_.size() - 1, ref.hash_val()));
- return true;
- }
-
- // Like push_back but swaps in the type to avoid a copy.
- bool PushBackViaSwap(T* t) {
- using std::swap;
-
- Ref ref(t);
- if (set_.find(ref) != set_.end())
- return false; // Already have this one.
-
- size_t new_index = vector_.size();
- vector_.resize(new_index + 1);
- swap(vector_[new_index], *t);
- set_.insert(Ref(&vector_, vector_.size() - 1, ref.hash_val()));
- return true;
- }
-
- // Appends a range of items from an iterator.
- template<typename iter> void Append(const iter& begin, const iter& end) {
- for (iter i = begin; i != end; ++i)
- push_back(*i);
- }
-
- // Returns the index of the item matching the given value in the list, or
- // (size_t)(-1) if it's not found.
- size_t IndexOf(const T& t) const {
- Ref ref(&t);
- typename HashSet::const_iterator found = set_.find(ref);
- if (found == set_.end())
- return static_cast<size_t>(-1);
- return found->index();
- }
-
- private:
- typedef internal::UniquifyRef<T> Ref;
- typedef base::hash_set<Ref> HashSet;
-
- HashSet set_;
- Vector vector_;
-};
-
-#endif // TOOLS_GN_UNIQUE_VECTOR_H_
diff --git a/chromium/tools/gn/unique_vector_unittest.cc b/chromium/tools/gn/unique_vector_unittest.cc
deleted file mode 100644
index d735423ff4d..00000000000
--- a/chromium/tools/gn/unique_vector_unittest.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include <algorithm>
-
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/unique_vector.h"
-
-TEST(UniqueVector, PushBack) {
- UniqueVector<int> foo;
- EXPECT_TRUE(foo.push_back(1));
- EXPECT_FALSE(foo.push_back(1));
- EXPECT_TRUE(foo.push_back(2));
- EXPECT_TRUE(foo.push_back(0));
- EXPECT_FALSE(foo.push_back(2));
- EXPECT_FALSE(foo.push_back(1));
-
- EXPECT_EQ(3u, foo.size());
- EXPECT_EQ(1, foo[0]);
- EXPECT_EQ(2, foo[1]);
- EXPECT_EQ(0, foo[2]);
-
- // Verify those results with IndexOf as well.
- EXPECT_EQ(0u, foo.IndexOf(1));
- EXPECT_EQ(1u, foo.IndexOf(2));
- EXPECT_EQ(2u, foo.IndexOf(0));
- EXPECT_EQ(static_cast<size_t>(-1), foo.IndexOf(99));
-}
-
-TEST(UniqueVector, PushBackViaSwap) {
- UniqueVector<std::string> vect;
- std::string a("a");
- EXPECT_TRUE(vect.PushBackViaSwap(&a));
- EXPECT_EQ("", a);
-
- a = "a";
- EXPECT_FALSE(vect.PushBackViaSwap(&a));
- EXPECT_EQ("a", a);
-
- EXPECT_EQ(0u, vect.IndexOf("a"));
-}
diff --git a/chromium/tools/gn/value.cc b/chromium/tools/gn/value.cc
deleted file mode 100644
index f92c885564b..00000000000
--- a/chromium/tools/gn/value.cc
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/value.h"
-
-#include <stddef.h>
-#include <utility>
-
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "tools/gn/scope.h"
-
-Value::Value()
- : type_(NONE),
- boolean_value_(false),
- int_value_(0),
- origin_(nullptr) {
-}
-
-Value::Value(const ParseNode* origin, Type t)
- : type_(t),
- boolean_value_(false),
- int_value_(0),
- origin_(origin) {
-}
-
-Value::Value(const ParseNode* origin, bool bool_val)
- : type_(BOOLEAN),
- boolean_value_(bool_val),
- int_value_(0),
- origin_(origin) {
-}
-
-Value::Value(const ParseNode* origin, int64_t int_val)
- : type_(INTEGER),
- boolean_value_(false),
- int_value_(int_val),
- origin_(origin) {
-}
-
-Value::Value(const ParseNode* origin, std::string str_val)
- : type_(STRING),
- string_value_(std::move(str_val)),
- boolean_value_(false),
- int_value_(0),
- origin_(origin) {}
-
-Value::Value(const ParseNode* origin, const char* str_val)
- : type_(STRING),
- string_value_(str_val),
- boolean_value_(false),
- int_value_(0),
- origin_(origin) {
-}
-
-Value::Value(const ParseNode* origin, std::unique_ptr<Scope> scope)
- : type_(SCOPE),
- string_value_(),
- boolean_value_(false),
- int_value_(0),
- scope_value_(std::move(scope)),
- origin_(origin) {}
-
-Value::Value(const Value& other)
- : type_(other.type_),
- string_value_(other.string_value_),
- boolean_value_(other.boolean_value_),
- int_value_(other.int_value_),
- list_value_(other.list_value_),
- origin_(other.origin_) {
- if (type() == SCOPE && other.scope_value_.get())
- scope_value_ = other.scope_value_->MakeClosure();
-}
-
-Value::Value(Value&& other) noexcept = default;
-
-Value::~Value() = default;
-
-Value& Value::operator=(const Value& other) {
- type_ = other.type_;
- string_value_ = other.string_value_;
- boolean_value_ = other.boolean_value_;
- int_value_ = other.int_value_;
- list_value_ = other.list_value_;
- if (type() == SCOPE && other.scope_value_.get())
- scope_value_ = other.scope_value_->MakeClosure();
- origin_ = other.origin_;
- return *this;
-}
-
-// static
-const char* Value::DescribeType(Type t) {
- switch (t) {
- case NONE:
- return "none";
- case BOOLEAN:
- return "boolean";
- case INTEGER:
- return "integer";
- case STRING:
- return "string";
- case LIST:
- return "list";
- case SCOPE:
- return "scope";
- default:
- NOTREACHED();
- return "UNKNOWN";
- }
-}
-
-void Value::SetScopeValue(std::unique_ptr<Scope> scope) {
- DCHECK(type_ == SCOPE);
- scope_value_ = std::move(scope);
-}
-
-std::string Value::ToString(bool quote_string) const {
- switch (type_) {
- case NONE:
- return "<void>";
- case BOOLEAN:
- return boolean_value_ ? "true" : "false";
- case INTEGER:
- return base::Int64ToString(int_value_);
- case STRING:
- if (quote_string) {
- std::string result = "\"";
- bool hanging_backslash = false;
- for (char ch : string_value_) {
- // If the last character was a literal backslash and the next
- // character could form a valid escape sequence, we need to insert
- // an extra backslash to prevent that.
- if (hanging_backslash && (ch == '$' || ch == '"' || ch == '\\'))
- result += '\\';
- // If the next character is a dollar sign or double quote, it needs
- // to be escaped; otherwise it can be printed as is.
- if (ch == '$' || ch == '"')
- result += '\\';
- result += ch;
- hanging_backslash = (ch == '\\');
- }
- // Again, we need to prevent the closing double quotes from becoming
- // an escape sequence.
- if (hanging_backslash)
- result += '\\';
- result += '"';
- return result;
- }
- return string_value_;
- case LIST: {
- std::string result = "[";
- for (size_t i = 0; i < list_value_.size(); i++) {
- if (i > 0)
- result += ", ";
- result += list_value_[i].ToString(true);
- }
- result.push_back(']');
- return result;
- }
- case SCOPE: {
- Scope::KeyValueMap scope_values;
- scope_value_->GetCurrentScopeValues(&scope_values);
- if (scope_values.empty())
- return std::string("{ }");
-
- std::string result = "{\n";
- for (const auto& pair : scope_values) {
- result += " " + pair.first.as_string() + " = " +
- pair.second.ToString(true) + "\n";
- }
- result += "}";
-
- return result;
- }
- }
- return std::string();
-}
-
-bool Value::VerifyTypeIs(Type t, Err* err) const {
- if (type_ == t)
- return true;
-
- *err = Err(origin(),
- std::string("This is not a ") + DescribeType(t) + ".",
- std::string("Instead I see a ") + DescribeType(type_) + " = " +
- ToString(true));
- return false;
-}
-
-bool Value::operator==(const Value& other) const {
- if (type_ != other.type_)
- return false;
-
- switch (type_) {
- case Value::BOOLEAN:
- return boolean_value() == other.boolean_value();
- case Value::INTEGER:
- return int_value() == other.int_value();
- case Value::STRING:
- return string_value() == other.string_value();
- case Value::LIST:
- if (list_value().size() != other.list_value().size())
- return false;
- for (size_t i = 0; i < list_value().size(); i++) {
- if (list_value()[i] != other.list_value()[i])
- return false;
- }
- return true;
- case Value::SCOPE:
- // Scopes are always considered not equal because there's currently
- // no use case for comparing them, and it requires a bunch of complex
- // iteration code.
- return false;
- default:
- return false;
- }
-}
-
-bool Value::operator!=(const Value& other) const {
- return !operator==(other);
-}
diff --git a/chromium/tools/gn/value.h b/chromium/tools/gn/value.h
deleted file mode 100644
index 13beb6fdcf2..00000000000
--- a/chromium/tools/gn/value.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_VALUE_H_
-#define TOOLS_GN_VALUE_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "tools/gn/err.h"
-
-class ParseNode;
-class Scope;
-
-// Represents a variable value in the interpreter.
-class Value {
- public:
- enum Type {
- NONE = 0,
- BOOLEAN,
- INTEGER,
- STRING,
- LIST,
- SCOPE,
- };
-
- Value();
- Value(const ParseNode* origin, Type t);
- Value(const ParseNode* origin, bool bool_val);
- Value(const ParseNode* origin, int64_t int_val);
- Value(const ParseNode* origin, std::string str_val);
- Value(const ParseNode* origin, const char* str_val);
- // Values "shouldn't" have null scopes when type == Scope, so be sure to
- // always set one. However, this is not asserted since there are some
- // use-cases for creating values and immediately setting the scope on it. So
- // you can pass a null scope here if you promise to set it before any other
- // code gets it (code will generally assume the scope is not null).
- Value(const ParseNode* origin, std::unique_ptr<Scope> scope);
-
- Value(const Value& other);
- Value(Value&& other) noexcept;
- ~Value();
-
- Value& operator=(const Value& other);
- Value& operator=(Value&& other) = default;
-
- Type type() const { return type_; }
-
- // Returns a string describing the given type.
- static const char* DescribeType(Type t);
-
- // Returns the node that made this. May be NULL.
- const ParseNode* origin() const { return origin_; }
- void set_origin(const ParseNode* o) { origin_ = o; }
-
- bool& boolean_value() {
- DCHECK(type_ == BOOLEAN);
- return boolean_value_;
- }
- const bool& boolean_value() const {
- DCHECK(type_ == BOOLEAN);
- return boolean_value_;
- }
-
- int64_t& int_value() {
- DCHECK(type_ == INTEGER);
- return int_value_;
- }
- const int64_t& int_value() const {
- DCHECK(type_ == INTEGER);
- return int_value_;
- }
-
- std::string& string_value() {
- DCHECK(type_ == STRING);
- return string_value_;
- }
- const std::string& string_value() const {
- DCHECK(type_ == STRING);
- return string_value_;
- }
-
- std::vector<Value>& list_value() {
- DCHECK(type_ == LIST);
- return list_value_;
- }
- const std::vector<Value>& list_value() const {
- DCHECK(type_ == LIST);
- return list_value_;
- }
-
- Scope* scope_value() {
- DCHECK(type_ == SCOPE);
- return scope_value_.get();
- }
- const Scope* scope_value() const {
- DCHECK(type_ == SCOPE);
- return scope_value_.get();
- }
- void SetScopeValue(std::unique_ptr<Scope> scope);
-
- // Converts the given value to a string. Returns true if strings should be
- // quoted or the ToString of a string should be the string itself. If the
- // string is quoted, it will also enable escaping.
- std::string ToString(bool quote_strings) const;
-
- // Verifies that the value is of the given type. If it isn't, returns
- // false and sets the error.
- bool VerifyTypeIs(Type t, Err* err) const;
-
- // Compares values. Only the "value" is compared, not the origin.
- bool operator==(const Value& other) const;
- bool operator!=(const Value& other) const;
-
- private:
- // This are a lot of objects associated with every Value that need
- // initialization and tear down every time. It might be more efficient to
- // create a union of objects (see small_map) and only use the one we care
- // about.
- Type type_;
- std::string string_value_;
- bool boolean_value_;
- int64_t int_value_;
- std::vector<Value> list_value_;
- std::unique_ptr<Scope> scope_value_;
-
- const ParseNode* origin_;
-};
-
-#endif // TOOLS_GN_VALUE_H_
diff --git a/chromium/tools/gn/value_extractors.cc b/chromium/tools/gn/value_extractors.cc
deleted file mode 100644
index ff009ce1b59..00000000000
--- a/chromium/tools/gn/value_extractors.cc
+++ /dev/null
@@ -1,257 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/value_extractors.h"
-
-#include <stddef.h>
-
-#include "tools/gn/build_settings.h"
-#include "tools/gn/err.h"
-#include "tools/gn/label.h"
-#include "tools/gn/source_dir.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/target.h"
-#include "tools/gn/value.h"
-
-namespace {
-
-// Sets the error and returns false on failure.
-template<typename T, class Converter>
-bool ListValueExtractor(const Value& value,
- std::vector<T>* dest,
- Err* err,
- const Converter& converter) {
- if (!value.VerifyTypeIs(Value::LIST, err))
- return false;
- const std::vector<Value>& input_list = value.list_value();
- dest->resize(input_list.size());
- for (size_t i = 0; i < input_list.size(); i++) {
- if (!converter(input_list[i], &(*dest)[i], err))
- return false;
- }
- return true;
-}
-
-// Like the above version but extracts to a UniqueVector and sets the error if
-// there are duplicates.
-template<typename T, class Converter>
-bool ListValueUniqueExtractor(const Value& value,
- UniqueVector<T>* dest,
- Err* err,
- const Converter& converter) {
- if (!value.VerifyTypeIs(Value::LIST, err))
- return false;
- const std::vector<Value>& input_list = value.list_value();
-
- for (const auto& item : input_list) {
- T new_one;
- if (!converter(item, &new_one, err))
- return false;
- if (!dest->push_back(new_one)) {
- // Already in the list, throw error.
- *err = Err(item, "Duplicate item in list");
- size_t previous_index = dest->IndexOf(new_one);
- err->AppendSubErr(Err(input_list[previous_index],
- "This was the previous definition."));
- return false;
- }
- }
- return true;
-}
-
-struct RelativeFileConverter {
- RelativeFileConverter(const BuildSettings* build_settings_in,
- const SourceDir& current_dir_in)
- : build_settings(build_settings_in),
- current_dir(current_dir_in) {
- }
- bool operator()(const Value& v, SourceFile* out, Err* err) const {
- *out = current_dir.ResolveRelativeFile(v, err,
- build_settings->root_path_utf8());
- return !err->has_error();
- }
- const BuildSettings* build_settings;
- const SourceDir& current_dir;
-};
-
-struct LibFileConverter {
- LibFileConverter(const BuildSettings* build_settings_in,
- const SourceDir& current_dir_in)
- : build_settings(build_settings_in),
- current_dir(current_dir_in) {
- }
- bool operator()(const Value& v, LibFile* out, Err* err) const {
- if (!v.VerifyTypeIs(Value::STRING, err))
- return false;
- if (v.string_value().find('/') == std::string::npos) {
- *out = LibFile(v.string_value());
- } else {
- *out = LibFile(current_dir.ResolveRelativeFile(
- v, err, build_settings->root_path_utf8()));
- }
- return !err->has_error();
- }
- const BuildSettings* build_settings;
- const SourceDir& current_dir;
-};
-
-struct RelativeDirConverter {
- RelativeDirConverter(const BuildSettings* build_settings_in,
- const SourceDir& current_dir_in)
- : build_settings(build_settings_in),
- current_dir(current_dir_in) {
- }
- bool operator()(const Value& v, SourceDir* out, Err* err) const {
- *out = current_dir.ResolveRelativeDir(v, err,
- build_settings->root_path_utf8());
- return true;
- }
- const BuildSettings* build_settings;
- const SourceDir& current_dir;
-};
-
-// Fills in a label.
-template<typename T> struct LabelResolver {
- LabelResolver(const SourceDir& current_dir_in,
- const Label& current_toolchain_in)
- : current_dir(current_dir_in),
- current_toolchain(current_toolchain_in) {}
- bool operator()(const Value& v, Label* out, Err* err) const {
- if (!v.VerifyTypeIs(Value::STRING, err))
- return false;
- *out = Label::Resolve(current_dir, current_toolchain, v, err);
- return !err->has_error();
- }
- const SourceDir& current_dir;
- const Label& current_toolchain;
-};
-
-// Fills the label part of a LabelPtrPair, leaving the pointer null.
-template<typename T> struct LabelPtrResolver {
- LabelPtrResolver(const SourceDir& current_dir_in,
- const Label& current_toolchain_in)
- : current_dir(current_dir_in),
- current_toolchain(current_toolchain_in) {}
- bool operator()(const Value& v, LabelPtrPair<T>* out, Err* err) const {
- if (!v.VerifyTypeIs(Value::STRING, err))
- return false;
- out->label = Label::Resolve(current_dir, current_toolchain, v, err);
- out->origin = v.origin();
- return !err->has_error();
- }
- const SourceDir& current_dir;
- const Label& current_toolchain;
-};
-
-struct LabelPatternResolver {
- LabelPatternResolver(const SourceDir& current_dir_in)
- : current_dir(current_dir_in) {
- }
- bool operator()(const Value& v, LabelPattern* out, Err* err) const {
- *out = LabelPattern::GetPattern(current_dir, v, err);
- return !err->has_error();
- }
- const SourceDir& current_dir;
-};
-
-} // namespace
-
-bool ExtractListOfStringValues(const Value& value,
- std::vector<std::string>* dest,
- Err* err) {
- if (!value.VerifyTypeIs(Value::LIST, err))
- return false;
- const std::vector<Value>& input_list = value.list_value();
- dest->reserve(input_list.size());
- for (const auto& item : input_list) {
- if (!item.VerifyTypeIs(Value::STRING, err))
- return false;
- dest->push_back(item.string_value());
- }
- return true;
-}
-
-bool ExtractListOfRelativeFiles(const BuildSettings* build_settings,
- const Value& value,
- const SourceDir& current_dir,
- std::vector<SourceFile>* files,
- Err* err) {
- return ListValueExtractor(value, files, err,
- RelativeFileConverter(build_settings, current_dir));
-}
-
-bool ExtractListOfLibs(const BuildSettings* build_settings,
- const Value& value,
- const SourceDir& current_dir,
- std::vector<LibFile>* libs,
- Err* err) {
- return ListValueExtractor(value, libs, err,
- LibFileConverter(build_settings, current_dir));
-}
-
-bool ExtractListOfRelativeDirs(const BuildSettings* build_settings,
- const Value& value,
- const SourceDir& current_dir,
- std::vector<SourceDir>* dest,
- Err* err) {
- return ListValueExtractor(value, dest, err,
- RelativeDirConverter(build_settings, current_dir));
-}
-
-bool ExtractListOfLabels(const Value& value,
- const SourceDir& current_dir,
- const Label& current_toolchain,
- LabelTargetVector* dest,
- Err* err) {
- return ListValueExtractor(value, dest, err,
- LabelPtrResolver<Target>(current_dir,
- current_toolchain));
-}
-
-bool ExtractListOfUniqueLabels(const Value& value,
- const SourceDir& current_dir,
- const Label& current_toolchain,
- UniqueVector<Label>* dest,
- Err* err) {
- return ListValueUniqueExtractor(value, dest, err,
- LabelResolver<Config>(current_dir,
- current_toolchain));
-}
-
-bool ExtractListOfUniqueLabels(const Value& value,
- const SourceDir& current_dir,
- const Label& current_toolchain,
- UniqueVector<LabelConfigPair>* dest,
- Err* err) {
- return ListValueUniqueExtractor(value, dest, err,
- LabelPtrResolver<Config>(current_dir,
- current_toolchain));
-}
-
-bool ExtractListOfUniqueLabels(const Value& value,
- const SourceDir& current_dir,
- const Label& current_toolchain,
- UniqueVector<LabelTargetPair>* dest,
- Err* err) {
- return ListValueUniqueExtractor(value, dest, err,
- LabelPtrResolver<Target>(current_dir,
- current_toolchain));
-}
-
-bool ExtractRelativeFile(const BuildSettings* build_settings,
- const Value& value,
- const SourceDir& current_dir,
- SourceFile* file,
- Err* err) {
- RelativeFileConverter converter(build_settings, current_dir);
- return converter(value, file, err);
-}
-
-bool ExtractListOfLabelPatterns(const Value& value,
- const SourceDir& current_dir,
- std::vector<LabelPattern>* patterns,
- Err* err) {
- return ListValueExtractor(value, patterns, err,
- LabelPatternResolver(current_dir));
-}
diff --git a/chromium/tools/gn/value_extractors.h b/chromium/tools/gn/value_extractors.h
deleted file mode 100644
index 1e426502036..00000000000
--- a/chromium/tools/gn/value_extractors.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_VALUE_EXTRACTORS_H_
-#define TOOLS_GN_VALUE_EXTRACTORS_H_
-
-#include <string>
-#include <vector>
-
-#include "tools/gn/label_ptr.h"
-#include "tools/gn/lib_file.h"
-#include "tools/gn/unique_vector.h"
-
-class BuildSettings;
-class Err;
-class Label;
-class LabelPattern;
-class SourceDir;
-class SourceFile;
-class Value;
-
-// On failure, returns false and sets the error.
-bool ExtractListOfStringValues(const Value& value,
- std::vector<std::string>* dest,
- Err* err);
-
-// Looks for a list of source files relative to a given current dir.
-bool ExtractListOfRelativeFiles(const BuildSettings* build_settings,
- const Value& value,
- const SourceDir& current_dir,
- std::vector<SourceFile>* files,
- Err* err);
-
-// Extracts a list of libraries. When they contain a "/" they are treated as
-// source paths and are otherwise treated as plain strings.
-bool ExtractListOfLibs(const BuildSettings* build_settings,
- const Value& value,
- const SourceDir& current_dir,
- std::vector<LibFile>* libs,
- Err* err);
-
-// Looks for a list of source directories relative to a given current dir.
-bool ExtractListOfRelativeDirs(const BuildSettings* build_settings,
- const Value& value,
- const SourceDir& current_dir,
- std::vector<SourceDir>* dest,
- Err* err);
-
-// Extracts the list of labels and their origins to the given vector. Only the
-// labels are filled in, the ptr for each pair in the vector will be null.
-bool ExtractListOfLabels(const Value& value,
- const SourceDir& current_dir,
- const Label& current_toolchain,
- LabelTargetVector* dest,
- Err* err);
-
-// Extracts the list of labels and their origins to the given vector. For the
-// version taking Label*Pair, only the labels are filled in, the ptr for each
-// pair in the vector will be null. Sets an error and returns false if a label
-// is maformed or there are duplicates.
-bool ExtractListOfUniqueLabels(const Value& value,
- const SourceDir& current_dir,
- const Label& current_toolchain,
- UniqueVector<Label>* dest,
- Err* err);
-bool ExtractListOfUniqueLabels(const Value& value,
- const SourceDir& current_dir,
- const Label& current_toolchain,
- UniqueVector<LabelConfigPair>* dest,
- Err* err);
-bool ExtractListOfUniqueLabels(const Value& value,
- const SourceDir& current_dir,
- const Label& current_toolchain,
- UniqueVector<LabelTargetPair>* dest,
- Err* err);
-
-bool ExtractRelativeFile(const BuildSettings* build_settings,
- const Value& value,
- const SourceDir& current_dir,
- SourceFile* file,
- Err* err);
-
-bool ExtractListOfLabelPatterns(const Value& value,
- const SourceDir& current_dir,
- std::vector<LabelPattern>* patterns,
- Err* err);
-
-#endif // TOOLS_GN_VALUE_EXTRACTORS_H_
diff --git a/chromium/tools/gn/value_unittest.cc b/chromium/tools/gn/value_unittest.cc
deleted file mode 100644
index 9fefaf7948b..00000000000
--- a/chromium/tools/gn/value_unittest.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/test_with_scope.h"
-#include "tools/gn/value.h"
-
-TEST(Value, ToString) {
- Value strval(nullptr, "hi\" $me\\you\\$\\\"");
- EXPECT_EQ("hi\" $me\\you\\$\\\"", strval.ToString(false));
- EXPECT_EQ("\"hi\\\" \\$me\\you\\\\\\$\\\\\\\"\"", strval.ToString(true));
-
- // crbug.com/470217
- Value strval2(nullptr, "\\foo\\\\bar\\");
- EXPECT_EQ("\"\\foo\\\\\\bar\\\\\"", strval2.ToString(true));
-
- // Void type.
- EXPECT_EQ("<void>", Value().ToString(false));
-
- // Test lists, bools, and ints.
- Value listval(nullptr, Value::LIST);
- listval.list_value().push_back(Value(nullptr, "hi\"me"));
- listval.list_value().push_back(Value(nullptr, true));
- listval.list_value().push_back(Value(nullptr, false));
- listval.list_value().push_back(Value(nullptr, static_cast<int64_t>(42)));
- // Printing lists always causes embedded strings to be quoted (ignoring the
- // quote flag), or else they wouldn't make much sense.
- EXPECT_EQ("[\"hi\\\"me\", true, false, 42]", listval.ToString(false));
- EXPECT_EQ("[\"hi\\\"me\", true, false, 42]", listval.ToString(true));
-
- // Scopes.
- TestWithScope setup;
- Scope* scope = new Scope(setup.scope());
- Value scopeval(nullptr, std::unique_ptr<Scope>(scope));
- EXPECT_EQ("{ }", scopeval.ToString(false));
-
- scope->SetValue("a", Value(nullptr, static_cast<int64_t>(42)), nullptr);
- scope->SetValue("b", Value(nullptr, "hello, world"), nullptr);
- EXPECT_EQ("{\n a = 42\n b = \"hello, world\"\n}", scopeval.ToString(false));
-}
diff --git a/chromium/tools/gn/variables.cc b/chromium/tools/gn/variables.cc
deleted file mode 100644
index 42191e36edb..00000000000
--- a/chromium/tools/gn/variables.cc
+++ /dev/null
@@ -1,2089 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/variables.h"
-
-namespace variables {
-
-// Built-in variables ----------------------------------------------------------
-
-const char kHostCpu[] = "host_cpu";
-const char kHostCpu_HelpShort[] =
- "host_cpu: [string] The processor architecture that GN is running on.";
-const char kHostCpu_Help[] =
- R"(host_cpu: The processor architecture that GN is running on.
-
- This is value is exposed so that cross-compile toolchains can access the host
- architecture when needed.
-
- The value should generally be considered read-only, but it can be overriden
- in order to handle unusual cases where there might be multiple plausible
- values for the host architecture (e.g., if you can do either 32-bit or 64-bit
- builds). The value is not used internally by GN for any purpose.
-
-Some possible values
-
- - "x64"
- - "x86"
-)";
-
-const char kHostOs[] = "host_os";
-const char kHostOs_HelpShort[] =
- "host_os: [string] The operating system that GN is running on.";
-const char kHostOs_Help[] =
- R"(host_os: [string] The operating system that GN is running on.
-
- This value is exposed so that cross-compiles can access the host build
- system's settings.
-
- This value should generally be treated as read-only. It, however, is not used
- internally by GN for any purpose.
-
-Some possible values
-
- - "linux"
- - "mac"
- - "win"
-)";
-
-const char kInvoker[] = "invoker";
-const char kInvoker_HelpShort[] =
- "invoker: [string] The invoking scope inside a template.";
-const char kInvoker_Help[] =
- R"(invoker: [string] The invoking scope inside a template.
-
- Inside a template invocation, this variable refers to the scope of the
- invoker of the template. Outside of template invocations, this variable is
- undefined.
-
- All of the variables defined inside the template invocation are accessible as
- members of the "invoker" scope. This is the way that templates read values
- set by the callers.
-
- This is often used with "defined" to see if a value is set on the invoking
- scope.
-
- See "gn help template" for more examples.
-
-Example
-
- template("my_template") {
- print(invoker.sources) # Prints [ "a.cc", "b.cc" ]
- print(defined(invoker.foo)) # Prints false.
- print(defined(invoker.bar)) # Prints true.
- }
-
- my_template("doom_melon") {
- sources = [ "a.cc", "b.cc" ]
- bar = 123
- }
-)";
-
-const char kTargetCpu[] = "target_cpu";
-const char kTargetCpu_HelpShort[] =
- "target_cpu: [string] The desired cpu architecture for the build.";
-const char kTargetCpu_Help[] =
- R"(target_cpu: The desired cpu architecture for the build.
-
- This value should be used to indicate the desired architecture for the
- primary objects of the build. It will match the cpu architecture of the
- default toolchain, but not necessarily the current toolchain.
-
- In many cases, this is the same as "host_cpu", but in the case of
- cross-compiles, this can be set to something different. This value is
- different from "current_cpu" in that it does not change based on the current
- toolchain. When writing rules, "current_cpu" should be used rather than
- "target_cpu" most of the time.
-
- This value is not used internally by GN for any purpose, so it may be set to
- whatever value is needed for the build. GN defaults this value to the empty
- string ("") and the configuration files should set it to an appropriate value
- (e.g., setting it to the value of "host_cpu") if it is not overridden on the
- command line or in the args.gn file.
-
-Possible values
-
- - "x86"
- - "x64"
- - "arm"
- - "arm64"
- - "mipsel"
-)";
-
-const char kTargetName[] = "target_name";
-const char kTargetName_HelpShort[] =
- "target_name: [string] The name of the current target.";
-const char kTargetName_Help[] =
- R"(target_name: [string] The name of the current target.
-
- Inside a target or template invocation, this variable refers to the name
- given to the target or template invocation. Outside of these, this variable
- is undefined.
-
- This is most often used in template definitions to name targets defined in
- the template based on the name of the invocation. This is necessary both to
- ensure generated targets have unique names and to generate a target with the
- exact name of the invocation that other targets can depend on.
-
- Be aware that this value will always reflect the innermost scope. So when
- defining a target inside a template, target_name will refer to the target
- rather than the template invocation. To get the name of the template
- invocation in this case, you should save target_name to a temporary variable
- outside of any target definitions.
-
- See "gn help template" for more examples.
-
-Example
-
- executable("doom_melon") {
- print(target_name) # Prints "doom_melon".
- }
-
- template("my_template") {
- print(target_name) # Prints "space_ray" when invoked below.
-
- executable(target_name + "_impl") {
- print(target_name) # Prints "space_ray_impl".
- }
- }
-
- my_template("space_ray") {
- }
-)";
-
-const char kTargetOs[] = "target_os";
-const char kTargetOs_HelpShort[] =
- "target_os: [string] The desired operating system for the build.";
-const char kTargetOs_Help[] =
- R"(target_os: The desired operating system for the build.
-
- This value should be used to indicate the desired operating system for the
- primary object(s) of the build. It will match the OS of the default
- toolchain.
-
- In many cases, this is the same as "host_os", but in the case of
- cross-compiles, it may be different. This variable differs from "current_os"
- in that it can be referenced from inside any toolchain and will always return
- the initial value.
-
- This should be set to the most specific value possible. So, "android" or
- "chromeos" should be used instead of "linux" where applicable, even though
- Android and ChromeOS are both Linux variants. This can mean that one needs to
- write
-
- if (target_os == "android" || target_os == "linux") {
- # ...
- }
-
- and so forth.
-
- This value is not used internally by GN for any purpose, so it may be set to
- whatever value is needed for the build. GN defaults this value to the empty
- string ("") and the configuration files should set it to an appropriate value
- (e.g., setting it to the value of "host_os") if it is not set via the command
- line or in the args.gn file.
-
-Possible values
-
- - "android"
- - "chromeos"
- - "ios"
- - "linux"
- - "nacl"
- - "mac"
- - "win"
-)";
-
-const char kCurrentCpu[] = "current_cpu";
-const char kCurrentCpu_HelpShort[] =
- "current_cpu: [string] The processor architecture of the current "
- "toolchain.";
-const char kCurrentCpu_Help[] =
- R"(current_cpu: The processor architecture of the current toolchain.
-
- The build configuration usually sets this value based on the value of
- "host_cpu" (see "gn help host_cpu") and then threads this through the
- toolchain definitions to ensure that it always reflects the appropriate
- value.
-
- This value is not used internally by GN for any purpose. It is set it to the
- empty string ("") by default but is declared so that it can be overridden on
- the command line if so desired.
-
- See "gn help target_cpu" for a list of common values returned.)";
-
-const char kCurrentOs[] = "current_os";
-const char kCurrentOs_HelpShort[] =
- "current_os: [string] The operating system of the current toolchain.";
-const char kCurrentOs_Help[] =
- R"(current_os: The operating system of the current toolchain.
-
- The build configuration usually sets this value based on the value of
- "target_os" (see "gn help target_os"), and then threads this through the
- toolchain definitions to ensure that it always reflects the appropriate
- value.
-
- This value is not used internally by GN for any purpose. It is set it to the
- empty string ("") by default but is declared so that it can be overridden on
- the command line if so desired.
-
- See "gn help target_os" for a list of common values returned.
-)";
-
-const char kCurrentToolchain[] = "current_toolchain";
-const char kCurrentToolchain_HelpShort[] =
- "current_toolchain: [string] Label of the current toolchain.";
-const char kCurrentToolchain_Help[] =
- R"(current_toolchain: Label of the current toolchain.
-
- A fully-qualified label representing the current toolchain. You can use this
- to make toolchain-related decisions in the build. See also
- "default_toolchain".
-
-Example
-
- if (current_toolchain == "//build:64_bit_toolchain") {
- executable("output_thats_64_bit_only") {
- ...
-)";
-
-const char kDefaultToolchain[] = "default_toolchain";
-const char kDefaultToolchain_HelpShort[] =
- "default_toolchain: [string] Label of the default toolchain.";
-const char kDefaultToolchain_Help[] =
- R"(default_toolchain: [string] Label of the default toolchain.
-
- A fully-qualified label representing the default toolchain, which may not
- necessarily be the current one (see "current_toolchain").
-)";
-
-const char kPythonPath[] = "python_path";
-const char kPythonPath_HelpShort[] =
- "python_path: [string] Absolute path of Python.";
-const char kPythonPath_Help[] =
- R"(python_path: Absolute path of Python.
-
- Normally used in toolchain definitions if running some command requires
- Python. You will normally not need this when invoking scripts since GN
- automatically finds it for you.
-)";
-
-const char kRootBuildDir[] = "root_build_dir";
-const char kRootBuildDir_HelpShort[] =
- "root_build_dir: [string] Directory where build commands are run.";
-const char kRootBuildDir_Help[] =
- R"(root_build_dir: [string] Directory where build commands are run.
-
- This is the root build output directory which will be the current directory
- when executing all compilers and scripts.
-
- Most often this is used with rebase_path (see "gn help rebase_path") to
- convert arguments to be relative to a script's current directory.
-)";
-
-const char kRootGenDir[] = "root_gen_dir";
-const char kRootGenDir_HelpShort[] =
- "root_gen_dir: [string] Directory for the toolchain's generated files.";
-const char kRootGenDir_Help[] =
- R"(root_gen_dir: Directory for the toolchain's generated files.
-
- Absolute path to the root of the generated output directory tree for the
- current toolchain. An example would be "//out/Debug/gen" for the default
- toolchain, or "//out/Debug/arm/gen" for the "arm" toolchain.
-
- This is primarily useful for setting up include paths for generated files. If
- you are passing this to a script, you will want to pass it through
- rebase_path() (see "gn help rebase_path") to convert it to be relative to the
- build directory.
-
- See also "target_gen_dir" which is usually a better location for generated
- files. It will be inside the root generated dir.
-)";
-
-const char kRootOutDir[] = "root_out_dir";
-const char kRootOutDir_HelpShort[] =
- "root_out_dir: [string] Root directory for toolchain output files.";
-const char kRootOutDir_Help[] =
- R"(root_out_dir: [string] Root directory for toolchain output files.
-
- Absolute path to the root of the output directory tree for the current
- toolchain. It will not have a trailing slash.
-
- For the default toolchain this will be the same as the root_build_dir. An
- example would be "//out/Debug" for the default toolchain, or
- "//out/Debug/arm" for the "arm" toolchain.
-
- This is primarily useful for setting up script calls. If you are passing this
- to a script, you will want to pass it through rebase_path() (see "gn help
- rebase_path") to convert it to be relative to the build directory.
-
- See also "target_out_dir" which is usually a better location for output
- files. It will be inside the root output dir.
-
-Example
-
- action("myscript") {
- # Pass the output dir to the script.
- args = [ "-o", rebase_path(root_out_dir, root_build_dir) ]
- }
-)";
-
-const char kTargetGenDir[] = "target_gen_dir";
-const char kTargetGenDir_HelpShort[] =
- "target_gen_dir: [string] Directory for a target's generated files.";
-const char kTargetGenDir_Help[] =
- R"(target_gen_dir: Directory for a target's generated files.
-
- Absolute path to the target's generated file directory. This will be the
- "root_gen_dir" followed by the relative path to the current build file. If
- your file is in "//tools/doom_melon" then target_gen_dir would be
- "//out/Debug/gen/tools/doom_melon". It will not have a trailing slash.
-
- This is primarily useful for setting up include paths for generated files. If
- you are passing this to a script, you will want to pass it through
- rebase_path() (see "gn help rebase_path") to convert it to be relative to the
- build directory.
-
- See also "gn help root_gen_dir".
-
-Example
-
- action("myscript") {
- # Pass the generated output dir to the script.
- args = [ "-o", rebase_path(target_gen_dir, root_build_dir) ]"
- }
-)";
-
-const char kTargetOutDir[] = "target_out_dir";
-const char kTargetOutDir_HelpShort[] =
- "target_out_dir: [string] Directory for target output files.";
-const char kTargetOutDir_Help[] =
- R"(target_out_dir: [string] Directory for target output files.
-
- Absolute path to the target's generated file directory. If your current
- target is in "//tools/doom_melon" then this value might be
- "//out/Debug/obj/tools/doom_melon". It will not have a trailing slash.
-
- This is primarily useful for setting up arguments for calling scripts. If you
- are passing this to a script, you will want to pass it through rebase_path()
- (see "gn help rebase_path") to convert it to be relative to the build
- directory.
-
- See also "gn help root_out_dir".
-
-Example
-
- action("myscript") {
- # Pass the output dir to the script.
- args = [ "-o", rebase_path(target_out_dir, root_build_dir) ]"
-
- }
-)";
-
-// Target variables ------------------------------------------------------------
-
-#define COMMON_ORDERING_HELP \
- "\n" \
- "Ordering of flags and values\n" \
- "\n" \
- " 1. Those set on the current target (not in a config).\n" \
- " 2. Those set on the \"configs\" on the target in order that the\n" \
- " configs appear in the list.\n" \
- " 3. Those set on the \"all_dependent_configs\" on the target in order\n" \
- " that the configs appear in the list.\n" \
- " 4. Those set on the \"public_configs\" on the target in order that\n" \
- " those configs appear in the list.\n" \
- " 5. all_dependent_configs pulled from dependencies, in the order of\n" \
- " the \"deps\" list. This is done recursively. If a config appears\n" \
- " more than once, only the first occurence will be used.\n" \
- " 6. public_configs pulled from dependencies, in the order of the\n" \
- " \"deps\" list. If a dependency is public, they will be applied\n" \
- " recursively.\n"
-
-const char kAllDependentConfigs[] = "all_dependent_configs";
-const char kAllDependentConfigs_HelpShort[] =
- "all_dependent_configs: [label list] Configs to be forced on dependents.";
-const char kAllDependentConfigs_Help[] =
- R"(all_dependent_configs: Configs to be forced on dependents.
-
- A list of config labels.
-
- All targets depending on this one, and recursively, all targets depending on
- those, will have the configs listed in this variable added to them. These
- configs will also apply to the current target.
-
- This addition happens in a second phase once a target and all of its
- dependencies have been resolved. Therefore, a target will not see these
- force-added configs in their "configs" variable while the script is running,
- and they can not be removed. As a result, this capability should generally
- only be used to add defines and include directories necessary to compile a
- target's headers.
-
- See also "public_configs".
-)"
- COMMON_ORDERING_HELP;
-
-const char kAllowCircularIncludesFrom[] = "allow_circular_includes_from";
-const char kAllowCircularIncludesFrom_HelpShort[] =
- "allow_circular_includes_from: [label list] Permit includes from deps.";
-const char kAllowCircularIncludesFrom_Help[] =
- R"(allow_circular_includes_from: Permit includes from deps.
-
- A list of target labels. Must be a subset of the target's "deps". These
- targets will be permitted to include headers from the current target despite
- the dependency going in the opposite direction.
-
- When you use this, both targets must be included in a final binary for it to
- link. To keep linker errors from happening, it is good practice to have all
- external dependencies depend only on one of the two targets, and to set the
- visibility on the other to enforce this. Thus the targets will always be
- linked together in any output.
-
-Details
-
- Normally, for a file in target A to include a file from target B, A must list
- B as a dependency. This invariant is enforced by the "gn check" command (and
- the --check flag to "gn gen" -- see "gn help check").
-
- Sometimes, two targets might be the same unit for linking purposes (two
- source sets or static libraries that would always be linked together in a
- final executable or shared library) and they each include headers from the
- other: you want A to be able to include B's headers, and B to include A's
- headers. This is not an ideal situation but is sometimes unavoidable.
-
- This list, if specified, lists which of the dependencies of the current
- target can include header files from the current target. That is, if A
- depends on B, B can only include headers from A if it is in A's
- allow_circular_includes_from list. Normally includes must follow the
- direction of dependencies, this flag allows them to go in the opposite
- direction.
-
-Danger
-
- In the above example, A's headers are likely to include headers from A's
- dependencies. Those dependencies may have public_configs that apply flags,
- defines, and include paths that make those headers work properly.
-
- With allow_circular_includes_from, B can include A's headers, and
- transitively from A's dependencies, without having the dependencies that
- would bring in the public_configs those headers need. The result may be
- errors or inconsistent builds.
-
- So when you use allow_circular_includes_from, make sure that any compiler
- settings, flags, and include directories are the same between both targets
- (consider putting such things in a shared config they can both reference).
- Make sure the dependencies are also the same (you might consider a group to
- collect such dependencies they both depend on).
-
-Example
-
- source_set("a") {
- deps = [ ":b", ":a_b_shared_deps" ]
- allow_circular_includes_from = [ ":b" ]
- ...
- }
-
- source_set("b") {
- deps = [ ":a_b_shared_deps" ]
- # Sources here can include headers from a despite lack of deps.
- ...
- }
-
- group("a_b_shared_deps") {
- public_deps = [ ":c" ]
- }
-)";
-
-const char kArflags[] = "arflags";
-const char kArflags_HelpShort[] =
- "arflags: [string list] Arguments passed to static_library archiver.";
-const char kArflags_Help[] =
- R"(arflags: Arguments passed to static_library archiver.
-
- A list of flags passed to the archive/lib command that creates static
- libraries.
-
- arflags are NOT pushed to dependents, so applying arflags to source sets or
- any other target type will be a no-op. As with ldflags, you could put the
- arflags in a config and set that as a public or "all dependent" config, but
- that will likely not be what you want. If you have a chain of static
- libraries dependent on each other, this can cause the flags to propagate up
- to other static libraries. Due to the nature of how arflags are typically
- used, you will normally want to apply them directly on static_library targets
- themselves.
-)"
- COMMON_ORDERING_HELP;
-
-const char kArgs[] = "args";
-const char kArgs_HelpShort[] =
- "args: [string list] Arguments passed to an action.";
-const char kArgs_Help[] =
- R"(args: Arguments passed to an action.
-
- For action and action_foreach targets, args is the list of arguments to pass
- to the script. Typically you would use source expansion (see "gn help
- source_expansion") to insert the source file names.
-
- See also "gn help action" and "gn help action_foreach".
-)";
-
-const char kAssertNoDeps[] = "assert_no_deps";
-const char kAssertNoDeps_HelpShort[] =
- "assert_no_deps: [label pattern list] Ensure no deps on these targets.";
-const char kAssertNoDeps_Help[] =
- R"(assert_no_deps: Ensure no deps on these targets.
-
- A list of label patterns.
-
- This list is a list of patterns that must not match any of the transitive
- dependencies of the target. These include all public, private, and data
- dependencies, and cross shared library boundaries. This allows you to express
- that undesirable code isn't accidentally added to downstream dependencies in
- a way that might otherwise be difficult to notice.
-
- Checking does not cross executable boundaries. If a target depends on an
- executable, it's assumed that the executable is a tool that is producing part
- of the build rather than something that is linked and distributed. This
- allows assert_no_deps to express what is distributed in the final target
- rather than depend on the internal build steps (which may include
- non-distributable code).
-
- See "gn help label_pattern" for the format of the entries in the list. These
- patterns allow blacklisting individual targets or whole directory
- hierarchies.
-
- Sometimes it is desirable to enforce that many targets have no dependencies
- on a target or set of targets. One efficient way to express this is to create
- a group with the assert_no_deps rule on it, and make that group depend on all
- targets you want to apply that assertion to.
-
-Example
-
- executable("doom_melon") {
- deps = [ "//foo:bar" ]
- ...
- assert_no_deps = [
- "//evil/*", # Don't link any code from the evil directory.
- "//foo:test_support", # This target is also disallowed.
- ]
- }
-)";
-
-const char kBundleRootDir[] = "bundle_root_dir";
-const char kBundleRootDir_HelpShort[] =
- "bundle_root_dir: Expansion of {{bundle_root_dir}} in create_bundle.";
-const char kBundleRootDir_Help[] =
- R"(bundle_root_dir: Expansion of {{bundle_root_dir}} in create_bundle.
-
- A string corresponding to a path in root_build_dir.
-
- This string is used by the "create_bundle" target to expand the
- {{bundle_root_dir}} of the "bundle_data" target it depends on. This must
- correspond to a path under root_build_dir.
-
-Example
-
- bundle_data("info_plist") {
- sources = [ "Info.plist" ]
- outputs = [ "{{bundle_contents_dir}}/Info.plist" ]
- }
-
- create_bundle("doom_melon.app") {
- deps = [ ":info_plist" ]
- bundle_root_dir = "${root_build_dir}/doom_melon.app"
- bundle_contents_dir = "${bundle_root_dir}/Contents"
- bundle_resources_dir = "${bundle_contents_dir}/Resources"
- bundle_executable_dir = "${bundle_contents_dir}/MacOS"
- bundle_plugins_dir = "${bundle_contents_dir}/PlugIns"
- }
-)";
-
-const char kBundleContentsDir[] = "bundle_contents_dir";
-const char kBundleContentsDir_HelpShort[] =
- "bundle_contents_dir: "
- "Expansion of {{bundle_contents_dir}} in create_bundle.";
-const char kBundleContentsDir_Help[] =
- R"(bundle_contents_dir: Expansion of {{bundle_contents_dir}} in
- create_bundle.
-
- A string corresponding to a path in $root_build_dir.
-
- This string is used by the "create_bundle" target to expand the
- {{bundle_contents_dir}} of the "bundle_data" target it depends on. This must
- correspond to a path under "bundle_root_dir".
-
- See "gn help bundle_root_dir" for examples.
-)";
-
-const char kBundleResourcesDir[] = "bundle_resources_dir";
-const char kBundleResourcesDir_HelpShort[] =
- "bundle_resources_dir: "
- "Expansion of {{bundle_resources_dir}} in create_bundle.";
-const char kBundleResourcesDir_Help[] =
- R"(bundle_resources_dir: Expansion of {{bundle_resources_dir}} in
- create_bundle.
-
- A string corresponding to a path in $root_build_dir.
-
- This string is used by the "create_bundle" target to expand the
- {{bundle_resources_dir}} of the "bundle_data" target it depends on. This must
- correspond to a path under "bundle_root_dir".
-
- See "gn help bundle_root_dir" for examples.
-)";
-
-const char kBundleDepsFilter[] = "bundle_deps_filter";
-const char kBundleDepsFilter_HelpShort[] =
- "bundle_deps_filter: [label list] A list of labels that are filtered out.";
-const char kBundleDepsFilter_Help[] =
- R"(bundle_deps_filter: [label list] A list of labels that are filtered out.
-
- A list of target labels.
-
- This list contains target label patterns that should be filtered out when
- creating the bundle. Any target matching one of those label will be removed
- from the dependencies of the create_bundle target.
-
- This is mostly useful when creating application extension bundle as the
- application extension has access to runtime resources from the application
- bundle and thus do not require a second copy.
-
- See "gn help create_bundle" for more information.
-
-Example
-
- create_bundle("today_extension") {
- deps = [
- "//base"
- ]
- bundle_root_dir = "$root_out_dir/today_extension.appex"
- bundle_deps_filter = [
- # The extension uses //base but does not use any function calling into
- # third_party/icu and thus does not need the icudtl.dat file.
- "//third_party/icu:icudata",
- ]
- }
-)";
-
-const char kBundleExecutableDir[] = "bundle_executable_dir";
-const char kBundleExecutableDir_HelpShort[] =
- "bundle_executable_dir: "
- "Expansion of {{bundle_executable_dir}} in create_bundle";
-const char kBundleExecutableDir_Help[] =
- R"(bundle_executable_dir: Expansion of {{bundle_executable_dir}} in
- create_bundle.
-
- A string corresponding to a path in $root_build_dir.
-
- This string is used by the "create_bundle" target to expand the
- {{bundle_executable_dir}} of the "bundle_data" target it depends on. This
- must correspond to a path under "bundle_root_dir".
-
- See "gn help bundle_root_dir" for examples.
-)";
-
-const char kBundlePlugInsDir[] = "bundle_plugins_dir";
-const char kBundlePlugInsDir_HelpShort[] =
- "bundle_plugins_dir: "
- "Expansion of {{bundle_plugins_dir}} in create_bundle.";
-const char kBundlePlugInsDir_Help[] =
- R"(bundle_plugins_dir: Expansion of {{bundle_plugins_dir}} in create_bundle.
-
- A string corresponding to a path in $root_build_dir.
-
- This string is used by the "create_bundle" target to expand the
- {{bundle_plugins_dir}} of the "bundle_data" target it depends on. This must
- correspond to a path under "bundle_root_dir".
-
- See "gn help bundle_root_dir" for examples.
-)";
-
-const char kCflags[] = "cflags";
-const char kCflags_HelpShort[] =
- "cflags: [string list] Flags passed to all C compiler variants.";
-const char kCommonCflagsHelp[] =
- R"(cflags*: Flags passed to the C compiler.
-
- A list of strings.
-
- "cflags" are passed to all invocations of the C, C++, Objective C, and
- Objective C++ compilers.
-
- To target one of these variants individually, use "cflags_c", "cflags_cc",
- "cflags_objc", and "cflags_objcc", respectively. These variant-specific
- versions of cflags* will be appended on the compiler command line after
- "cflags".
-
- See also "asmflags" for flags for assembly-language files.
-)"
- COMMON_ORDERING_HELP;
-const char* kCflags_Help = kCommonCflagsHelp;
-
-const char kAsmflags[] = "asmflags";
-const char kAsmflags_HelpShort[] =
- "asmflags: [string list] Flags passed to the assembler.";
-const char* kAsmflags_Help =
- R"(asmflags: Flags passed to the assembler.
-
- A list of strings.
-
- "asmflags" are passed to any invocation of a tool that takes an .asm or .S
- file as input.
-)"
- COMMON_ORDERING_HELP;
-
-const char kCflagsC[] = "cflags_c";
-const char kCflagsC_HelpShort[] =
- "cflags_c: [string list] Flags passed to the C compiler.";
-const char* kCflagsC_Help = kCommonCflagsHelp;
-
-const char kCflagsCC[] = "cflags_cc";
-const char kCflagsCC_HelpShort[] =
- "cflags_cc: [string list] Flags passed to the C++ compiler.";
-const char* kCflagsCC_Help = kCommonCflagsHelp;
-
-const char kCflagsObjC[] = "cflags_objc";
-const char kCflagsObjC_HelpShort[] =
- "cflags_objc: [string list] Flags passed to the Objective C compiler.";
-const char* kCflagsObjC_Help = kCommonCflagsHelp;
-
-const char kCflagsObjCC[] = "cflags_objcc";
-const char kCflagsObjCC_HelpShort[] =
- "cflags_objcc: [string list] Flags passed to the Objective C++ compiler.";
-const char* kCflagsObjCC_Help = kCommonCflagsHelp;
-
-const char kCheckIncludes[] = "check_includes";
-const char kCheckIncludes_HelpShort[] =
- "check_includes: [boolean] Controls whether a target's files are checked.";
-const char kCheckIncludes_Help[] =
- R"(check_includes: [boolean] Controls whether a target's files are checked.
-
- When true (the default), the "gn check" command (as well as "gn gen" with the
- --check flag) will check this target's sources and headers for proper
- dependencies.
-
- When false, the files in this target will be skipped by default. This does
- not affect other targets that depend on the current target, it just skips
- checking the includes of the current target's files.
-
- If there are a few conditionally included headers that trip up checking, you
- can exclude headers individually by annotating them with "nogncheck" (see "gn
- help nogncheck").
-
- The topic "gn help check" has general information on how checking works and
- advice on how to pass a check in problematic cases.
-
-Example
-
- source_set("busted_includes") {
- # This target's includes are messed up, exclude it from checking.
- check_includes = false
- ...
- }
-)";
-
-const char kCodeSigningArgs[] = "code_signing_args";
-const char kCodeSigningArgs_HelpShort[] =
- "code_signing_args: [string list] Arguments passed to code signing script.";
-const char kCodeSigningArgs_Help[] =
- R"(code_signing_args: [string list] Arguments passed to code signing script.
-
- For create_bundle targets, code_signing_args is the list of arguments to pass
- to the code signing script. Typically you would use source expansion (see "gn
- help source_expansion") to insert the source file names.
-
- See also "gn help create_bundle".
-)";
-
-const char kCodeSigningScript[] = "code_signing_script";
-const char kCodeSigningScript_HelpShort[] =
- "code_signing_script: [file name] Script for code signing.";
-const char kCodeSigningScript_Help[] =
- R"(code_signing_script: [file name] Script for code signing."
-
- An absolute or buildfile-relative file name of a Python script to run for a
- create_bundle target to perform code signing step.
-
- See also "gn help create_bundle".
-)";
-
-const char kCodeSigningSources[] = "code_signing_sources";
-const char kCodeSigningSources_HelpShort[] =
- "code_signing_sources: [file list] Sources for code signing step.";
-const char kCodeSigningSources_Help[] =
- R"(code_signing_sources: [file list] Sources for code signing step.
-
- A list of files used as input for code signing script step of a create_bundle
- target. Non-absolute paths will be resolved relative to the current build
- file.
-
- See also "gn help create_bundle".
-)";
-
-const char kCodeSigningOutputs[] = "code_signing_outputs";
-const char kCodeSigningOutputs_HelpShort[] =
- "code_signing_outputs: [file list] Output files for code signing step.";
-const char kCodeSigningOutputs_Help[] =
- R"(code_signing_outputs: [file list] Output files for code signing step.
-
- Outputs from the code signing step of a create_bundle target. Must refer to
- files in the build directory.
-
- See also "gn help create_bundle".
-)";
-
-const char kCompleteStaticLib[] = "complete_static_lib";
-const char kCompleteStaticLib_HelpShort[] =
- "complete_static_lib: [boolean] Links all deps into a static library.";
-const char kCompleteStaticLib_Help[] =
- R"(complete_static_lib: [boolean] Links all deps into a static library.
-
- A static library normally doesn't include code from dependencies, but instead
- forwards the static libraries and source sets in its deps up the dependency
- chain until a linkable target (an executable or shared library) is reached.
- The final linkable target only links each static library once, even if it
- appears more than once in its dependency graph.
-
- In some cases the static library might be the final desired output. For
- example, you may be producing a static library for distribution to third
- parties. In this case, the static library should include code for all
- dependencies in one complete package. However, complete static libraries
- themselves are never linked into other complete static libraries. All
- complete static libraries are for distribution and linking them in would
- cause code duplication in this case. If the static library is not for
- distribution, it should not be complete.
-
- GN treats non-complete static libraries as source sets when they are linked
- into complete static libraries. This is done because some tools like AR do
- not handle dependent static libraries properly. This makes it easier to write
- "alink" rules.
-
- In rare cases it makes sense to list a header in more than one target if it
- could be considered conceptually a member of both. libraries.
-
-Example
-
- static_library("foo") {
- complete_static_lib = true
- deps = [ "bar" ]
- }
-)";
-
-const char kConfigs[] = "configs";
-const char kConfigs_HelpShort[] =
- "configs: [label list] Configs applying to this target or config.";
-const char kConfigs_Help[] =
- R"(configs: Configs applying to this target or config.
-
- A list of config labels.
-
-Configs on a target
-
- When used on a target, the include_dirs, defines, etc. in each config are
- appended in the order they appear to the compile command for each file in the
- target. They will appear after the include_dirs, defines, etc. that the
- target sets directly.
-
- Since configs apply after the values set on a target, directly setting a
- compiler flag will prepend it to the command line. If you want to append a
- flag instead, you can put that flag in a one-off config and append that
- config to the target's configs list.
-
- The build configuration script will generally set up the default configs
- applying to a given target type (see "set_defaults"). When a target is being
- defined, it can add to or remove from this list.
-
-Configs on a config
-
- It is possible to create composite configs by specifying configs on a config.
- One might do this to forward values, or to factor out blocks of settings from
- very large configs into more manageable named chunks.
-
- In this case, the composite config is expanded to be the concatenation of its
- own values, and in order, the values from its sub-configs *before* anything
- else happens. This has some ramifications:
-
- - A target has no visibility into a config's sub-configs. Target code only
- sees the name of the composite config. It can't remove sub-configs or opt
- in to only parts of it. The composite config may not even be defined
- before the target is.
-
- - You can get duplication of values if a config is listed twice, say, on a
- target and in a sub-config that also applies. In other cases, the configs
- applying to a target are de-duped. It's expected that if a config is
- listed as a sub-config that it is only used in that context. (Note that
- it's possible to fix this and de-dupe, but it's not normally relevant and
- complicates the implementation.)
-)"
- COMMON_ORDERING_HELP
-R"(
-Example
-
- # Configs on a target.
- source_set("foo") {
- # Don't use the default RTTI config that BUILDCONFIG applied to us.
- configs -= [ "//build:no_rtti" ]
-
- # Add some of our own settings.
- configs += [ ":mysettings" ]
- }
-
- # Create a default_optimization config that forwards to one of a set of more
- # specialized configs depending on build flags. This pattern is useful
- # because it allows a target to opt in to either a default set, or a more
- # specific set, while avoid duplicating the settings in two places.
- config("super_optimization") {
- cflags = [ ... ]
- }
- config("default_optimization") {
- if (optimize_everything) {
- configs = [ ":super_optimization" ]
- } else {
- configs = [ ":no_optimization" ]
- }
- }
-)";
-
-const char kData[] = "data";
-const char kData_HelpShort[] =
- "data: [file list] Runtime data file dependencies.";
-const char kData_Help[] =
- R"(data: Runtime data file dependencies.
-
- Lists files or directories required to run the given target. These are
- typically data files or directories of data files. The paths are interpreted
- as being relative to the current build file. Since these are runtime
- dependencies, they do not affect which targets are built or when. To declare
- input files to a script, use "inputs".
-
- Appearing in the "data" section does not imply any special handling such as
- copying them to the output directory. This is just used for declaring runtime
- dependencies. Runtime dependencies can be queried using the "runtime_deps"
- category of "gn desc" or written during build generation via
- "--runtime-deps-list-file".
-
- GN doesn't require data files to exist at build-time. So actions that produce
- files that are in turn runtime dependencies can list those generated files
- both in the "outputs" list as well as the "data" list.
-
- By convention, directories are listed with a trailing slash:
- data = [ "test/data/" ]
- However, no verification is done on these so GN doesn't enforce this. The
- paths are just rebased and passed along when requested.
-
- Note: On iOS and macOS, create_bundle targets will not be recursed into when
- gathering data. See "gn help create_bundle" for details.
-
- See "gn help runtime_deps" for how these are used.
-)";
-
-const char kDataDeps[] = "data_deps";
-const char kDataDeps_HelpShort[] =
- "data_deps: [label list] Non-linked dependencies.";
-const char kDataDeps_Help[] =
- R"(data_deps: Non-linked dependencies.
-
- A list of target labels.
-
- Specifies dependencies of a target that are not actually linked into the
- current target. Such dependencies will be built and will be available at
- runtime.
-
- This is normally used for things like plugins or helper programs that a
- target needs at runtime.
-
- Note: On iOS and macOS, create_bundle targets will not be recursed into when
- gathering data_deps. See "gn help create_bundle" for details.
-
- See also "gn help deps" and "gn help data".
-
-Example
-
- executable("foo") {
- deps = [ "//base" ]
- data_deps = [ "//plugins:my_runtime_plugin" ]
- }
-)";
-
-const char kDefines[] = "defines";
-const char kDefines_HelpShort[] =
- "defines: [string list] C preprocessor defines.";
-const char kDefines_Help[] =
- R"(defines: C preprocessor defines.
-
- A list of strings
-
- These strings will be passed to the C/C++ compiler as #defines. The strings
- may or may not include an "=" to assign a value.
-)"
- COMMON_ORDERING_HELP
-R"(
-Example
-
- defines = [ "AWESOME_FEATURE", "LOG_LEVEL=3" ]
-)";
-
-const char kDepfile[] = "depfile";
-const char kDepfile_HelpShort[] =
- "depfile: [string] File name for input dependencies for actions.";
-const char kDepfile_Help[] =
- R"(depfile: [string] File name for input dependencies for actions.
-
- If nonempty, this string specifies that the current action or action_foreach
- target will generate the given ".d" file containing the dependencies of the
- input. Empty or unset means that the script doesn't generate the files.
-
- A depfile should be used only when a target depends on files that are not
- already specified by a target's inputs and sources. Likewise, depfiles should
- specify only those dependencies not already included in sources or inputs.
-
- The .d file should go in the target output directory. If you have more than
- one source file that the script is being run over, you can use the output
- file expansions described in "gn help action_foreach" to name the .d file
- according to the input."
-
- The format is that of a Makefile and all paths must be relative to the root
- build directory. Only one output may be listed and it must match the first
- output of the action.
-
- Although depfiles are created by an action, they should not be listed in the
- action's "outputs" unless another target will use the file as an input.
-
-Example
-
- action_foreach("myscript_target") {
- script = "myscript.py"
- sources = [ ... ]
-
- # Locate the depfile in the output directory named like the
- # inputs but with a ".d" appended.
- depfile = "$relative_target_output_dir/{{source_name}}.d"
-
- # Say our script uses "-o <d file>" to indicate the depfile.
- args = [ "{{source}}", "-o", depfile ]
- }
-)";
-
-const char kDeps[] = "deps";
-const char kDeps_HelpShort[] =
- "deps: [label list] Private linked dependencies.";
-const char kDeps_Help[] =
- R"(deps: Private linked dependencies.
-
- A list of target labels.
-
- Specifies private dependencies of a target. Private dependencies are
- propagated up the dependency tree and linked to dependent targets, but do not
- grant the ability to include headers from the dependency. Public configs are
- not forwarded.
-
-Details of dependency propagation
-
- Source sets, shared libraries, and non-complete static libraries will be
- propagated up the dependency tree across groups, non-complete static
- libraries and source sets.
-
- Executables, shared libraries, and complete static libraries will link all
- propagated targets and stop propagation. Actions and copy steps also stop
- propagation, allowing them to take a library as an input but not force
- dependents to link to it.
-
- Propagation of all_dependent_configs and public_configs happens independently
- of target type. all_dependent_configs are always propagated across all types
- of targets, and public_configs are always propagated across public deps of
- all types of targets.
-
- Data dependencies are propagated differently. See "gn help data_deps" and
- "gn help runtime_deps".
-
- See also "public_deps".
-)";
-
-const char kFriend[] = "friend";
-const char kFriend_HelpShort[] =
- "friend: [label pattern list] Allow targets to include private headers.";
-const char kFriend_Help[] =
- R"(friend: Allow targets to include private headers.
-
- A list of label patterns (see "gn help label_pattern") that allow dependent
- targets to include private headers. Applies to all binary targets.
-
- Normally if a target lists headers in the "public" list (see "gn help
- public"), other headers are implicitly marked as private. Private headers
- can not be included by other targets, even with a public dependency path.
- The "gn check" function performs this validation.
-
- A friend declaration allows one or more targets to include private headers.
- This is useful for things like unit tests that are closely associated with a
- target and require internal knowledge without opening up all headers to be
- included by all dependents.
-
- A friend target does not allow that target to include headers when no
- dependency exists. A public dependency path must still exist between two
- targets to include any headers from a destination target. The friend
- annotation merely allows the use of headers that would otherwise be
- prohibited because they are private.
-
- The friend annotation is matched only against the target containing the file
- with the include directive. Friend annotations are not propagated across
- public or private dependencies. Friend annotations do not affect visibility.
-
-Example
-
- static_library("lib") {
- # This target can include our private headers.
- friend = [ ":unit_tests" ]
-
- public = [
- "public_api.h", # Normal public API for dependent targets.
- ]
-
- # Private API and sources.
- sources = [
- "a_source_file.cc",
-
- # Normal targets that depend on this one won't be able to include this
- # because this target defines a list of "public" headers. Without the
- # "public" list, all headers are implicitly public.
- "private_api.h",
- ]
- }
-
- executable("unit_tests") {
- sources = [
- # This can include "private_api.h" from the :lib target because it
- # depends on that target and because of the friend annotation.
- "my_test.cc",
- ]
-
- deps = [
- ":lib", # Required for the include to be allowed.
- ]
- }
-)";
-
-const char kIncludeDirs[] = "include_dirs";
-const char kIncludeDirs_HelpShort[] =
- "include_dirs: [directory list] Additional include directories.";
-const char kIncludeDirs_Help[] =
- R"(include_dirs: Additional include directories.
-
- A list of source directories.
-
- The directories in this list will be added to the include path for the files
- in the affected target.
-)"
- COMMON_ORDERING_HELP
-R"(
-Example
-
- include_dirs = [ "src/include", "//third_party/foo" ]
-)";
-
-const char kInputs[] = "inputs";
-const char kInputs_HelpShort[] =
- "inputs: [file list] Additional compile-time dependencies.";
-const char kInputs_Help[] =
- R"(inputs: Additional compile-time dependencies.
-
- Inputs are compile-time dependencies of the current target. This means that
- all inputs must be available before compiling any of the sources or executing
- any actions.
-
- Inputs are typically only used for action and action_foreach targets.
-
-Inputs for actions
-
- For action and action_foreach targets, inputs should be the inputs to script
- that don't vary. These should be all .py files that the script uses via
- imports (the main script itself will be an implicit dependency of the action
- so need not be listed).
-
- For action targets, inputs and sources are treated the same, but from a style
- perspective, it's recommended to follow the same rule as action_foreach and
- put helper files in the inputs, and the data used by the script (if any) in
- sources.
-
- Note that another way to declare input dependencies from an action is to have
- the action write a depfile (see "gn help depfile"). This allows the script to
- dynamically write input dependencies, that might not be known until actually
- executing the script. This is more efficient than doing processing while
- running GN to determine the inputs, and is easier to keep in-sync than
- hardcoding the list.
-
-Script input gotchas
-
- It may be tempting to write a script that enumerates all files in a directory
- as inputs. Don't do this! Even if you specify all the files in the inputs or
- sources in the GN target (or worse, enumerate the files in an exec_script
- call when running GN, which will be slow), the dependencies will be broken.
-
- The problem happens if a file is ever removed because the inputs are not
- listed on the command line to the script. Because the script hasn't changed
- and all inputs are up to date, the script will not re-run and you will get a
- stale build. Instead, either list all inputs on the command line to the
- script, or if there are many, create a separate list file that the script
- reads. As long as this file is listed in the inputs, the build will detect
- when it has changed in any way and the action will re-run.
-
-Inputs for binary targets
-
- Any input dependencies will be resolved before compiling any sources or
- linking the target. Normally, all actions that a target depends on will be run
- before any files in a target are compiled. So if you depend on generated
- headers, you do not typically need to list them in the inputs section.
-
- Inputs for binary targets will be treated as implicit dependencies, meaning
- that changes in any of the inputs will force all sources in the target to be
- recompiled. If an input only applies to a subset of source files, you may
- want to split those into a separate target to avoid unnecessary recompiles.
-
-Example
-
- action("myscript") {
- script = "domything.py"
- inputs = [ "input.data" ]
- }
-)";
-
-const char kLdflags[] = "ldflags";
-const char kLdflags_HelpShort[] =
- "ldflags: [string list] Flags passed to the linker.";
-const char kLdflags_Help[] =
- R"(ldflags: Flags passed to the linker.
-
- A list of strings.
-
- These flags are passed on the command-line to the linker and generally
- specify various linking options. Most targets will not need these and will
- use "libs" and "lib_dirs" instead.
-
- ldflags are NOT pushed to dependents, so applying ldflags to source sets or
- static libraries will be a no-op. If you want to apply ldflags to dependent
- targets, put them in a config and set it in the all_dependent_configs or
- public_configs.
-)"
- COMMON_ORDERING_HELP;
-
-#define COMMON_LIB_INHERITANCE_HELP \
- "\n" \
- " libs and lib_dirs work differently than other flags in two respects.\n" \
- " First, then are inherited across static library boundaries until a\n" \
- " shared library or executable target is reached. Second, they are\n" \
- " uniquified so each one is only passed once (the first instance of it\n" \
- " will be the one used).\n"
-
-#define LIBS_AND_LIB_DIRS_ORDERING_HELP \
- "\n" \
- " For \"libs\" and \"lib_dirs\" only, the values propagated from\n" \
- " dependencies (as described above) are applied last assuming they\n" \
- " are not already in the list.\n"
-
-const char kLibDirs[] = "lib_dirs";
-const char kLibDirs_HelpShort[] =
- "lib_dirs: [directory list] Additional library directories.";
-const char kLibDirs_Help[] =
- R"(lib_dirs: Additional library directories.
-
- A list of directories.
-
- Specifies additional directories passed to the linker for searching for the
- required libraries. If an item is not an absolute path, it will be treated as
- being relative to the current build file.
-)"
- COMMON_LIB_INHERITANCE_HELP
- COMMON_ORDERING_HELP
- LIBS_AND_LIB_DIRS_ORDERING_HELP
-R"(
-Example
-
- lib_dirs = [ "/usr/lib/foo", "lib/doom_melon" ]
-)";
-
-const char kLibs[] = "libs";
-const char kLibs_HelpShort[] =
- "libs: [string list] Additional libraries to link.";
-const char kLibs_Help[] =
- R"(libs: Additional libraries to link.
-
- A list of library names or library paths.
-
- These libraries will be linked into the final binary (executable or shared
- library) containing the current target.
-)"
- COMMON_LIB_INHERITANCE_HELP
-R"(
-Types of libs
-
- There are several different things that can be expressed in libs:
-
- File paths
- Values containing '/' will be treated as references to files in the
- checkout. They will be rebased to be relative to the build directory and
- specified in the "libs" for linker tools. This facility should be used
- for libraries that are checked in to the version control. For libraries
- that are generated by the build, use normal GN deps to link them.
-
- System libraries
- Values not containing '/' will be treated as system library names. These
- will be passed unmodified to the linker and prefixed with the
- "lib_switch" attribute of the linker tool. Generally you would set the
- "lib_dirs" so the given library is found. Your BUILD.gn file should not
- specify the switch (like "-l"): this will be encoded in the "lib_switch"
- of the tool.
-
- Apple frameworks
- System libraries ending in ".framework" will be special-cased: the switch
- "-framework" will be prepended instead of the lib_switch, and the
- ".framework" suffix will be trimmed. This is to support the way Mac links
- framework dependencies.
-)"
- COMMON_ORDERING_HELP
- LIBS_AND_LIB_DIRS_ORDERING_HELP
-R"(
-Examples
-
- On Windows:
- libs = [ "ctl3d.lib" ]
-
- On Linux:
- libs = [ "ld" ]
-)";
-
-const char kOutputExtension[] = "output_extension";
-const char kOutputExtension_HelpShort[] =
- "output_extension: [string] Value to use for the output's file extension.";
-const char kOutputExtension_Help[] =
- R"(output_extension: Value to use for the output's file extension.
-
- Normally the file extension for a target is based on the target type and the
- operating system, but in rare cases you will need to override the name (for
- example to use "libfreetype.so.6" instead of libfreetype.so on Linux).
-
- This value should not include a leading dot. If undefined, the default
- specified on the tool will be used. If set to the empty string, no output
- extension will be used.
-
- The output_extension will be used to set the "{{output_extension}}" expansion
- which the linker tool will generally use to specify the output file name. See
- "gn help tool".
-
-Example
-
- shared_library("freetype") {
- if (is_linux) {
- # Call the output "libfreetype.so.6"
- output_extension = "so.6"
- }
- ...
- }
-
- # On Windows, generate a "mysettings.cpl" control panel applet. Control panel
- # applets are actually special shared libraries.
- if (is_win) {
- shared_library("mysettings") {
- output_extension = "cpl"
- ...
- }
- }
-)";
-
-const char kOutputDir[] = "output_dir";
-const char kOutputDir_HelpShort[] =
- "output_dir: [directory] Directory to put output file in.";
-const char kOutputDir_Help[] =
- R"(output_dir: [directory] Directory to put output file in.
-
- For library and executable targets, overrides the directory for the final
- output. This must be in the root_build_dir or a child thereof.
-
- This should generally be in the root_out_dir or a subdirectory thereof (the
- root_out_dir will be the same as the root_build_dir for the default
- toolchain, and will be a subdirectory for other toolchains). Not putting the
- output in a subdirectory of root_out_dir can result in collisions between
- different toolchains, so you will need to take steps to ensure that your
- target is only present in one toolchain.
-
- Normally the toolchain specifies the output directory for libraries and
- executables (see "gn help tool"). You will have to consult that for the
- default location. The default location will be used if output_dir is
- undefined or empty.
-
-Example
-
- shared_library("doom_melon") {
- output_dir = "$root_out_dir/plugin_libs"
- ...
- }
-)";
-
-const char kOutputName[] = "output_name";
-const char kOutputName_HelpShort[] =
- "output_name: [string] Name for the output file other than the default.";
-const char kOutputName_Help[] =
- R"(output_name: Define a name for the output file other than the default.
-
- Normally the output name of a target will be based on the target name, so the
- target "//foo/bar:bar_unittests" will generate an output file such as
- "bar_unittests.exe" (using Windows as an example).
-
- Sometimes you will want an alternate name to avoid collisions or if the
- internal name isn't appropriate for public distribution.
-
- The output name should have no extension or prefixes, these will be added
- using the default system rules. For example, on Linux an output name of "foo"
- will produce a shared library "libfoo.so". There is no way to override the
- output prefix of a linker tool on a per- target basis. If you need more
- flexibility, create a copy target to produce the file you want.
-
- This variable is valid for all binary output target types.
-
-Example
-
- static_library("doom_melon") {
- output_name = "fluffy_bunny"
- }
-)";
-
-const char kOutputPrefixOverride[] = "output_prefix_override";
-const char kOutputPrefixOverride_HelpShort[] =
- "output_prefix_override: [boolean] Don't use prefix for output name.";
-const char kOutputPrefixOverride_Help[] =
- R"(output_prefix_override: Don't use prefix for output name.
-
- A boolean that overrides the output prefix for a target. Defaults to false.
-
- Some systems use prefixes for the names of the final target output file. The
- normal example is "libfoo.so" on Linux for a target named "foo".
-
- The output prefix for a given target type is specified on the linker tool
- (see "gn help tool"). Sometimes this prefix is undesired.
-
- See also "gn help output_extension".
-
-Example
-
- shared_library("doom_melon") {
- # Normally this will produce "libdoom_melon.so" on Linux. Setting this flag
- # will produce "doom_melon.so".
- output_prefix_override = true
- ...
- }
-)";
-
-const char kPartialInfoPlist[] = "partial_info_plist";
-const char kPartialInfoPlist_HelpShort[] =
- "partial_info_plist: [filename] Path plist from asset catalog compiler.";
-const char kPartialInfoPlist_Help[] =
- R"(partial_info_plist: [filename] Path plist from asset catalog compiler.
-
- Valid for create_bundle target, corresponds to the path for the partial
- Info.plist created by the asset catalog compiler that needs to be merged
- with the application Info.plist (usually done by the code signing script).
-
- The file will be generated regardless of whether the asset compiler has
- been invoked or not. See "gn help create_bundle".
-)";
-
-const char kOutputs[] = "outputs";
-const char kOutputs_HelpShort[] =
- "outputs: [file list] Output files for actions and copy targets.";
-const char kOutputs_Help[] =
- R"(outputs: Output files for actions and copy targets.
-
- Outputs is valid for "copy", "action", and "action_foreach" target types and
- indicates the resulting files. Outputs must always refer to files in the
- build directory.
-
- copy
- Copy targets should have exactly one entry in the outputs list. If there is
- exactly one source, this can be a literal file name or a source expansion.
- If there is more than one source, this must contain a source expansion to
- map a single input name to a single output name. See "gn help copy".
-
- action_foreach
- Action_foreach targets must always use source expansions to map input files
- to output files. There can be more than one output, which means that each
- invocation of the script will produce a set of files (presumably based on
- the name of the input file). See "gn help action_foreach".
-
- action
- Action targets (excluding action_foreach) must list literal output file(s)
- with no source expansions. See "gn help action".
-)";
-
-const char kPool[] = "pool";
-const char kPool_HelpShort[] =
- "pool: [string] Label of the pool used by the action.";
-const char kPool_Help[] =
- R"(pool: Label of the pool used by the action.
-
- A fully-qualified label representing the pool that will be used for the
- action. Pools are defined using the pool() {...} declaration.
-
-Example
-
- action("action") {
- pool = "//build:custom_pool"
- ...
- }
-)";
-
-const char kPrecompiledHeader[] = "precompiled_header";
-const char kPrecompiledHeader_HelpShort[] =
- "precompiled_header: [string] Header file to precompile.";
-const char kPrecompiledHeader_Help[] =
- R"(precompiled_header: [string] Header file to precompile.
-
- Precompiled headers will be used when a target specifies this value, or a
- config applying to this target specifies this value. In addition, the tool
- corresponding to the source files must also specify precompiled headers (see
- "gn help tool"). The tool will also specify what type of precompiled headers
- to use, by setting precompiled_header_type to either "gcc" or "msvc".
-
- The precompiled header/source variables can be specified on a target or a
- config, but must be the same for all configs applying to a given target since
- a target can only have one precompiled header.
-
- If you use both C and C++ sources, the precompiled header and source file
- will be compiled once per language. You will want to make sure to wrap C++
- includes in __cplusplus #ifdefs so the file will compile in C mode.
-
-GCC precompiled headers
-
- When using GCC-style precompiled headers, "precompiled_source" contains the
- path of a .h file that is precompiled and then included by all source files
- in targets that set "precompiled_source".
-
- The value of "precompiled_header" is not used with GCC-style precompiled
- headers.
-
-MSVC precompiled headers
-
- When using MSVC-style precompiled headers, the "precompiled_header" value is
- a string corresponding to the header. This is NOT a path to a file that GN
- recognises, but rather the exact string that appears in quotes after
- an #include line in source code. The compiler will match this string against
- includes or forced includes (/FI).
-
- MSVC also requires a source file to compile the header with. This must be
- specified by the "precompiled_source" value. In contrast to the header value,
- this IS a GN-style file name, and tells GN which source file to compile to
- make the .pch file used for subsequent compiles.
-
- For example, if the toolchain specifies MSVC headers:
-
- toolchain("vc_x64") {
- ...
- tool("cxx") {
- precompiled_header_type = "msvc"
- ...
-
- You might make a config like this:
-
- config("use_precompiled_headers") {
- precompiled_header = "build/precompile.h"
- precompiled_source = "//build/precompile.cc"
-
- # Either your source files should #include "build/precompile.h"
- # first, or you can do this to force-include the header.
- cflags = [ "/FI$precompiled_header" ]
- }
-
- And then define a target that uses the config:
-
- executable("doom_melon") {
- configs += [ ":use_precompiled_headers" ]
- ...
-)";
-
-const char kPrecompiledHeaderType[] = "precompiled_header_type";
-const char kPrecompiledHeaderType_HelpShort[] =
- "precompiled_header_type: [string] \"gcc\" or \"msvc\".";
-const char kPrecompiledHeaderType_Help[] =
- R"(precompiled_header_type: [string] "gcc" or "msvc".
-
- See "gn help precompiled_header".
-)";
-
-const char kPrecompiledSource[] = "precompiled_source";
-const char kPrecompiledSource_HelpShort[] =
- "precompiled_source: [file name] Source file to precompile.";
-const char kPrecompiledSource_Help[] =
- R"(precompiled_source: [file name] Source file to precompile.
-
- The source file that goes along with the precompiled_header when using
- "msvc"-style precompiled headers. It will be implicitly added to the sources
- of the target. See "gn help precompiled_header".
-)";
-
-const char kProductType[] = "product_type";
-const char kProductType_HelpShort[] =
- "product_type: [string] Product type for Xcode projects.";
-const char kProductType_Help[] =
- R"(product_type: Product type for Xcode projects.
-
- Correspond to the type of the product of a create_bundle target. Only
- meaningful to Xcode (used as part of the Xcode project generation).
-
- When generating Xcode project files, only create_bundle target with a
- non-empty product_type will have a corresponding target in Xcode project.
-)";
-
-const char kPublic[] = "public";
-const char kPublic_HelpShort[] =
- "public: [file list] Declare public header files for a target.";
-const char kPublic_Help[] =
- R"(public: Declare public header files for a target.
-
- A list of files that other targets can include. These permissions are checked
- via the "check" command (see "gn help check").
-
- If no public files are declared, other targets (assuming they have visibility
- to depend on this target) can include any file in the sources list. If this
- variable is defined on a target, dependent targets may only include files on
- this whitelist unless that target is marked as a friend (see "gn help
- friend").
-
- Header file permissions are also subject to visibility. A target must be
- visible to another target to include any files from it at all and the public
- headers indicate which subset of those files are permitted. See "gn help
- visibility" for more.
-
- Public files are inherited through the dependency tree. So if there is a
- dependency A -> B -> C, then A can include C's public headers. However, the
- same is NOT true of visibility, so unless A is in C's visibility list, the
- include will be rejected.
-
- GN only knows about files declared in the "sources" and "public" sections of
- targets. If a file is included that is not known to the build, it will be
- allowed.
-
- It is common for test targets to need to include private headers for their
- associated code. In this case, list the test target in the "friend" list of
- the target that owns the private header to allow the inclusion. See
- "gn help friend" for more.
-
- When a binary target has no explicit or implicit public headers (a "public"
- list is defined but is empty), GN assumes that the target can not propagate
- any compile-time dependencies up the dependency tree. In this case, the build
- can be parallelized more efficiently.
- Say there are dependencies:
- A (shared library) -> B (shared library) -> C (action).
- Normally C must complete before any source files in A can compile (because
- there might be generated includes). But when B explicitly declares no public
- headers, C can execute in parallel with A's compile steps. C must still be
- complete before any dependents link.
-
-Examples
-
- These exact files are public:
- public = [ "foo.h", "bar.h" ]
-
- No files are public (no targets may include headers from this one):
- # This allows starting compile in dependent targets earlier.
- public = []
-)";
-
-const char kPublicConfigs[] = "public_configs";
-const char kPublicConfigs_HelpShort[] =
- "public_configs: [label list] Configs applied to dependents.";
-const char kPublicConfigs_Help[] =
- R"(public_configs: Configs to be applied on dependents.
-
- A list of config labels.
-
- Targets directly depending on this one will have the configs listed in this
- variable added to them. These configs will also apply to the current target.
-
- This addition happens in a second phase once a target and all of its
- dependencies have been resolved. Therefore, a target will not see these
- force-added configs in their "configs" variable while the script is running,
- and they can not be removed. As a result, this capability should generally
- only be used to add defines and include directories necessary to compile a
- target's headers.
-
- See also "all_dependent_configs".
-)"
- COMMON_ORDERING_HELP;
-
-const char kPublicDeps[] = "public_deps";
-const char kPublicDeps_HelpShort[] =
- "public_deps: [label list] Declare public dependencies.";
-const char kPublicDeps_Help[] =
- R"(public_deps: Declare public dependencies.
-
- Public dependencies are like private dependencies (see "gn help deps") but
- additionally express that the current target exposes the listed deps as part
- of its public API.
-
- This has several ramifications:
-
- - public_configs that are part of the dependency are forwarded to direct
- dependents.
-
- - Public headers in the dependency are usable by dependents (includes do
- not require a direct dependency or visibility).
-
- - If the current target is a shared library, other shared libraries that it
- publicly depends on (directly or indirectly) are propagated up the
- dependency tree to dependents for linking.
-
-Discussion
-
- Say you have three targets: A -> B -> C. C's visibility may allow B to depend
- on it but not A. Normally, this would prevent A from including any headers
- from C, and C's public_configs would apply only to B.
-
- If B lists C in its public_deps instead of regular deps, A will now inherit
- C's public_configs and the ability to include C's public headers.
-
- Generally if you are writing a target B and you include C's headers as part
- of B's public headers, or targets depending on B should consider B and C to
- be part of a unit, you should use public_deps instead of deps.
-
-Example
-
- # This target can include files from "c" but not from
- # "super_secret_implementation_details".
- executable("a") {
- deps = [ ":b" ]
- }
-
- shared_library("b") {
- deps = [ ":super_secret_implementation_details" ]
- public_deps = [ ":c" ]
- }
-)";
-
-const char kResponseFileContents[] = "response_file_contents";
-const char kResponseFileContents_HelpShort[] =
- "response_file_contents: [string list] Contents of .rsp file for actions.";
-const char kResponseFileContents_Help[] =
- R"*(response_file_contents: Contents of a response file for actions.
-
- Sometimes the arguments passed to a script can be too long for the system's
- command-line capabilities. This is especially the case on Windows where the
- maximum command-line length is less than 8K. A response file allows you to
- pass an unlimited amount of data to a script in a temporary file for an
- action or action_foreach target.
-
- If the response_file_contents variable is defined and non-empty, the list
- will be treated as script args (including possibly substitution patterns)
- that will be written to a temporary file at build time. The name of the
- temporary file will be substituted for "{{response_file_name}}" in the script
- args.
-
- The response file contents will always be quoted and escaped according to
- Unix shell rules. To parse the response file, the Python script should use
- "shlex.split(file_contents)".
-
-Example
-
- action("process_lots_of_files") {
- script = "process.py",
- inputs = [ ... huge list of files ... ]
-
- # Write all the inputs to a response file for the script. Also,
- # make the paths relative to the script working directory.
- response_file_contents = rebase_path(inputs, root_build_dir)
-
- # The script expects the name of the response file in --file-list.
- args = [
- "--enable-foo",
- "--file-list={{response_file_name}}",
- ]
- }
-)*";
-
-const char kScript[] = "script";
-const char kScript_HelpShort[] =
- "script: [file name] Script file for actions.";
-const char kScript_Help[] =
- R"(script: Script file for actions.
-
- An absolute or buildfile-relative file name of a Python script to run for a
- action and action_foreach targets (see "gn help action" and "gn help
- action_foreach").
-)";
-
-const char kSources[] = "sources";
-const char kSources_HelpShort[] =
- "sources: [file list] Source files for a target.";
-const char kSources_Help[] =
- R"(sources: Source files for a target
-
- A list of files. Non-absolute paths will be resolved relative to the current
- build file.
-
-Sources for binary targets
-
- For binary targets (source sets, executables, and libraries), the known file
- types will be compiled with the associated tools. Unknown file types and
- headers will be skipped. However, you should still list all C/C+ header files
- so GN knows about the existence of those files for the purposes of include
- checking.
-
- As a special case, a file ending in ".def" will be treated as a Windows
- module definition file. It will be appended to the link line with a
- preceding "/DEF:" string. There must be at most one .def file in a target
- and they do not cross dependency boundaries (so specifying a .def file in a
- static library or source set will have no effect on the executable or shared
- library they're linked into).
-
-Sources for non-binary targets
-
- action_foreach
- The sources are the set of files that the script will be executed over. The
- script will run once per file.
-
- action
- The sources will be treated the same as inputs. See "gn help inputs" for
- more information and usage advice.
-
- copy
- The source are the source files to copy.
-)";
-
-const char kXcodeTestApplicationName[] = "xcode_test_application_name";
-const char kXcodeTestApplicationName_HelpShort[] =
- "test_application_name: [string] Test application name for unit or ui test "
- "target.";
-const char kXcodeTestApplicationName_Help[] =
- R"(test_application_name: Test application name for unit or ui test target.
-
- Each unit and ui test target must have a test application target, and this
- value is used to specify the relationship. Only meaningful to Xcode (used as
- part of the Xcode project generation).
-
- See "gn help create_bundle" for more information.
-
-Exmaple
-
- create_bundle("chrome_xctest") {
- test_application_name = "chrome"
- ...
- }
-)";
-
-const char kTestonly[] = "testonly";
-const char kTestonly_HelpShort[] =
- "testonly: [boolean] Declares a target must only be used for testing.";
-const char kTestonly_Help[] =
- R"(testonly: Declares a target must only be used for testing.
-
- Boolean. Defaults to false.
-
- When a target is marked "testonly = true", it must only be depended on by
- other test-only targets. Otherwise, GN will issue an error that the
- depenedency is not allowed.
-
- This feature is intended to prevent accidentally shipping test code in a
- final product.
-
-Example
-
- source_set("test_support") {
- testonly = true
- ...
- }
-)";
-
-const char kVisibility[] = "visibility";
-const char kVisibility_HelpShort[] =
- "visibility: [label list] A list of labels that can depend on a target.";
-const char kVisibility_Help[] =
- R"(visibility: A list of labels that can depend on a target.
-
- A list of labels and label patterns that define which targets can depend on
- the current one. These permissions are checked via the "check" command (see
- "gn help check").
-
- If visibility is not defined, it defaults to public ("*").
-
- If visibility is defined, only the targets with labels that match it can
- depend on the current target. The empty list means no targets can depend on
- the current target.
-
- Tip: Often you will want the same visibility for all targets in a BUILD file.
- In this case you can just put the definition at the top, outside of any
- target, and the targets will inherit that scope and see the definition.
-
-Patterns
-
- See "gn help label_pattern" for more details on what types of patterns are
- supported. If a toolchain is specified, only targets in that toolchain will
- be matched. If a toolchain is not specified on a pattern, targets in all
- toolchains will be matched.
-
-Examples
-
- Only targets in the current buildfile ("private"):
- visibility = [ ":*" ]
-
- No targets (used for targets that should be leaf nodes):
- visibility = []
-
- Any target ("public", the default):
- visibility = [ "*" ]
-
- All targets in the current directory and any subdirectory:
- visibility = [ "./*" ]
-
- Any target in "//bar/BUILD.gn":
- visibility = [ "//bar:*" ]
-
- Any target in "//bar/" or any subdirectory thereof:
- visibility = [ "//bar/*" ]
-
- Just these specific targets:
- visibility = [ ":mything", "//foo:something_else" ]
-
- Any target in the current directory and any subdirectory thereof, plus
- any targets in "//bar/" and any subdirectory thereof.
- visibility = [ "./*", "//bar/*" ]
-)";
-
-const char kWriteRuntimeDeps[] = "write_runtime_deps";
-const char kWriteRuntimeDeps_HelpShort[] =
- "write_runtime_deps: Writes the target's runtime_deps to the given path.";
-const char kWriteRuntimeDeps_Help[] =
- R"(write_runtime_deps: Writes the target's runtime_deps to the given path.
-
- Does not synchronously write the file, but rather schedules it to be written
- at the end of generation.
-
- If the file exists and the contents are identical to that being written, the
- file will not be updated. This will prevent unnecessary rebuilds of targets
- that depend on this file.
-
- Path must be within the output directory.
-
- See "gn help runtime_deps" for how the runtime dependencies are computed.
-
- The format of this file will list one file per line with no escaping. The
- files will be relative to the root_build_dir. The first line of the file will
- be the main output file of the target itself. The file contents will be the
- same as requesting the runtime deps be written on the command line (see "gn
- help --runtime-deps-list-file").
-)";
-
-const char kXcodeExtraAttributes[] = "xcode_extra_attributes";
-const char kXcodeExtraAttributes_HelpShort[] =
- "xcode_extra_attributes: [scope] Extra attributes for Xcode projects.";
-const char kXcodeExtraAttributes_Help[] =
- R"(xcode_extra_attributes: [scope] Extra attributes for Xcode projects.
-
- The value defined in this scope will be copied to the EXTRA_ATTRIBUTES
- property of the generated Xcode project. They are only meaningful when
- generating with --ide=xcode.
-
- See "gn help create_bundle" for more information.
-)";
-
-// -----------------------------------------------------------------------------
-
-VariableInfo::VariableInfo()
- : help_short(""),
- help("") {
-}
-
-VariableInfo::VariableInfo(const char* in_help_short, const char* in_help)
- : help_short(in_help_short),
- help(in_help) {
-}
-
-#define INSERT_VARIABLE(var) \
- info_map[k##var] = VariableInfo(k##var##_HelpShort, k##var##_Help);
-
-const VariableInfoMap& GetBuiltinVariables() {
- static VariableInfoMap info_map;
- if (info_map.empty()) {
- INSERT_VARIABLE(CurrentCpu)
- INSERT_VARIABLE(CurrentOs)
- INSERT_VARIABLE(CurrentToolchain)
- INSERT_VARIABLE(DefaultToolchain)
- INSERT_VARIABLE(HostCpu)
- INSERT_VARIABLE(HostOs)
- INSERT_VARIABLE(Invoker)
- INSERT_VARIABLE(PythonPath)
- INSERT_VARIABLE(RootBuildDir)
- INSERT_VARIABLE(RootGenDir)
- INSERT_VARIABLE(RootOutDir)
- INSERT_VARIABLE(TargetCpu)
- INSERT_VARIABLE(TargetOs)
- INSERT_VARIABLE(TargetGenDir)
- INSERT_VARIABLE(TargetName)
- INSERT_VARIABLE(TargetOutDir)
- }
- return info_map;
-}
-
-const VariableInfoMap& GetTargetVariables() {
- static VariableInfoMap info_map;
- if (info_map.empty()) {
- INSERT_VARIABLE(AllDependentConfigs)
- INSERT_VARIABLE(AllowCircularIncludesFrom)
- INSERT_VARIABLE(Arflags)
- INSERT_VARIABLE(Args)
- INSERT_VARIABLE(Asmflags)
- INSERT_VARIABLE(AssertNoDeps)
- INSERT_VARIABLE(BundleRootDir)
- INSERT_VARIABLE(BundleContentsDir)
- INSERT_VARIABLE(BundleResourcesDir)
- INSERT_VARIABLE(BundleDepsFilter)
- INSERT_VARIABLE(BundleExecutableDir)
- INSERT_VARIABLE(BundlePlugInsDir)
- INSERT_VARIABLE(Cflags)
- INSERT_VARIABLE(CflagsC)
- INSERT_VARIABLE(CflagsCC)
- INSERT_VARIABLE(CflagsObjC)
- INSERT_VARIABLE(CflagsObjCC)
- INSERT_VARIABLE(CheckIncludes)
- INSERT_VARIABLE(CodeSigningArgs)
- INSERT_VARIABLE(CodeSigningScript)
- INSERT_VARIABLE(CodeSigningSources)
- INSERT_VARIABLE(CodeSigningOutputs)
- INSERT_VARIABLE(CompleteStaticLib)
- INSERT_VARIABLE(Configs)
- INSERT_VARIABLE(Data)
- INSERT_VARIABLE(DataDeps)
- INSERT_VARIABLE(Defines)
- INSERT_VARIABLE(Depfile)
- INSERT_VARIABLE(Deps)
- INSERT_VARIABLE(Friend)
- INSERT_VARIABLE(IncludeDirs)
- INSERT_VARIABLE(Inputs)
- INSERT_VARIABLE(Ldflags)
- INSERT_VARIABLE(Libs)
- INSERT_VARIABLE(LibDirs)
- INSERT_VARIABLE(OutputDir)
- INSERT_VARIABLE(OutputExtension)
- INSERT_VARIABLE(OutputName)
- INSERT_VARIABLE(OutputPrefixOverride)
- INSERT_VARIABLE(Outputs)
- INSERT_VARIABLE(PartialInfoPlist)
- INSERT_VARIABLE(Pool)
- INSERT_VARIABLE(PrecompiledHeader)
- INSERT_VARIABLE(PrecompiledHeaderType)
- INSERT_VARIABLE(PrecompiledSource)
- INSERT_VARIABLE(ProductType)
- INSERT_VARIABLE(Public)
- INSERT_VARIABLE(PublicConfigs)
- INSERT_VARIABLE(PublicDeps)
- INSERT_VARIABLE(ResponseFileContents)
- INSERT_VARIABLE(Script)
- INSERT_VARIABLE(Sources)
- INSERT_VARIABLE(XcodeTestApplicationName)
- INSERT_VARIABLE(Testonly)
- INSERT_VARIABLE(Visibility)
- INSERT_VARIABLE(WriteRuntimeDeps)
- INSERT_VARIABLE(XcodeExtraAttributes)
- }
- return info_map;
-}
-
-#undef INSERT_VARIABLE
-
-} // namespace variables
diff --git a/chromium/tools/gn/variables.h b/chromium/tools/gn/variables.h
deleted file mode 100644
index 80615f92cf3..00000000000
--- a/chromium/tools/gn/variables.h
+++ /dev/null
@@ -1,333 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_VARIABLES_H_
-#define TOOLS_GN_VARIABLES_H_
-
-#include <map>
-
-#include "base/strings/string_piece.h"
-
-namespace variables {
-
-// Builtin vars ----------------------------------------------------------------
-
-extern const char kHostCpu[];
-extern const char kHostCpu_HelpShort[];
-extern const char kHostCpu_Help[];
-
-extern const char kHostOs[];
-extern const char kHostOs_HelpShort[];
-extern const char kHostOs_Help[];
-
-extern const char kCurrentCpu[];
-extern const char kCurrentCpu_HelpShort[];
-extern const char kCurrentCpu_Help[];
-
-extern const char kCurrentOs[];
-extern const char kCurrentOs_HelpShort[];
-extern const char kCurrentOs_Help[];
-
-extern const char kCurrentToolchain[];
-extern const char kCurrentToolchain_HelpShort[];
-extern const char kCurrentToolchain_Help[];
-
-extern const char kDefaultToolchain[];
-extern const char kDefaultToolchain_HelpShort[];
-extern const char kDefaultToolchain_Help[];
-
-extern const char kInvoker[];
-extern const char kInvoker_HelpShort[];
-extern const char kInvoker_Help[];
-
-extern const char kPythonPath[];
-extern const char kPythonPath_HelpShort[];
-extern const char kPythonPath_Help[];
-
-extern const char kRootBuildDir[];
-extern const char kRootBuildDir_HelpShort[];
-extern const char kRootBuildDir_Help[];
-
-extern const char kRootGenDir[];
-extern const char kRootGenDir_HelpShort[];
-extern const char kRootGenDir_Help[];
-
-extern const char kRootOutDir[];
-extern const char kRootOutDir_HelpShort[];
-extern const char kRootOutDir_Help[];
-
-extern const char kTargetCpu[];
-extern const char kTargetCpu_HelpShort[];
-extern const char kTargetCpu_Help[];
-
-extern const char kTargetName[];
-extern const char kTargetName_HelpShort[];
-extern const char kTargetName_Help[];
-
-extern const char kTargetOs[];
-extern const char kTargetOs_HelpShort[];
-extern const char kTargetOs_Help[];
-
-extern const char kTargetGenDir[];
-extern const char kTargetGenDir_HelpShort[];
-extern const char kTargetGenDir_Help[];
-
-extern const char kTargetOutDir[];
-extern const char kTargetOutDir_HelpShort[];
-extern const char kTargetOutDir_Help[];
-
-// Target vars -----------------------------------------------------------------
-
-extern const char kAllDependentConfigs[];
-extern const char kAllDependentConfigs_HelpShort[];
-extern const char kAllDependentConfigs_Help[];
-
-extern const char kAllowCircularIncludesFrom[];
-extern const char kAllowCircularIncludesFrom_HelpShort[];
-extern const char kAllowCircularIncludesFrom_Help[];
-
-extern const char kArflags[];
-extern const char kArflags_HelpShort[];
-extern const char kArflags_Help[];
-
-extern const char kArgs[];
-extern const char kArgs_HelpShort[];
-extern const char kArgs_Help[];
-
-extern const char kAsmflags[];
-extern const char kAsmflags_HelpShort[];
-extern const char* kAsmflags_Help;
-
-extern const char kAssertNoDeps[];
-extern const char kAssertNoDeps_HelpShort[];
-extern const char kAssertNoDeps_Help[];
-
-extern const char kBundleRootDir[];
-extern const char kBundleRootDir_HelpShort[];
-extern const char kBundleRootDir_Help[];
-
-extern const char kBundleContentsDir[];
-extern const char kBundleContentsDir_HelpShort[];
-extern const char kBundleContentsDir_Help[];
-
-extern const char kBundleResourcesDir[];
-extern const char kBundleResourcesDir_HelpShort[];
-extern const char kBundleResourcesDir_Help[];
-
-extern const char kBundleDepsFilter[];
-extern const char kBundleDepsFilter_HelpShort[];
-extern const char kBundleDepsFilter_Help[];
-
-extern const char kBundleExecutableDir[];
-extern const char kBundleExecutableDir_HelpShort[];
-extern const char kBundleExecutableDir_Help[];
-
-extern const char kBundlePlugInsDir[];
-extern const char kBundlePlugInsDir_HelpShort[];
-extern const char kBundlePlugInsDir_Help[];
-
-extern const char kCflags[];
-extern const char kCflags_HelpShort[];
-extern const char* kCflags_Help;
-
-extern const char kCflagsC[];
-extern const char kCflagsC_HelpShort[];
-extern const char* kCflagsC_Help;
-
-extern const char kCflagsCC[];
-extern const char kCflagsCC_HelpShort[];
-extern const char* kCflagsCC_Help;
-
-extern const char kCflagsObjC[];
-extern const char kCflagsObjC_HelpShort[];
-extern const char* kCflagsObjC_Help;
-
-extern const char kCflagsObjCC[];
-extern const char kCflagsObjCC_HelpShort[];
-extern const char* kCflagsObjCC_Help;
-
-extern const char kCheckIncludes[];
-extern const char kCheckIncludes_HelpShort[];
-extern const char kCheckIncludes_Help[];
-
-extern const char kCodeSigningArgs[];
-extern const char kCodeSigningArgs_HelpShort[];
-extern const char kCodeSigningArgs_Help[];
-
-extern const char kCodeSigningScript[];
-extern const char kCodeSigningScript_HelpShort[];
-extern const char kCodeSigningScript_Help[];
-
-extern const char kCodeSigningSources[];
-extern const char kCodeSigningSources_HelpShort[];
-extern const char kCodeSigningSources_Help[];
-
-extern const char kCodeSigningOutputs[];
-extern const char kCodeSigningOutputs_HelpShort[];
-extern const char kCodeSigningOutputs_Help[];
-
-extern const char kCompleteStaticLib[];
-extern const char kCompleteStaticLib_HelpShort[];
-extern const char kCompleteStaticLib_Help[];
-
-extern const char kConfigs[];
-extern const char kConfigs_HelpShort[];
-extern const char kConfigs_Help[];
-
-extern const char kData[];
-extern const char kData_HelpShort[];
-extern const char kData_Help[];
-
-extern const char kDataDeps[];
-extern const char kDataDeps_HelpShort[];
-extern const char kDataDeps_Help[];
-
-extern const char kDefines[];
-extern const char kDefines_HelpShort[];
-extern const char kDefines_Help[];
-
-extern const char kDepfile[];
-extern const char kDepfile_HelpShort[];
-extern const char kDepfile_Help[];
-
-extern const char kDeps[];
-extern const char kDeps_HelpShort[];
-extern const char kDeps_Help[];
-
-extern const char kFriend[];
-extern const char kFriend_HelpShort[];
-extern const char kFriend_Help[];
-
-extern const char kIncludeDirs[];
-extern const char kIncludeDirs_HelpShort[];
-extern const char kIncludeDirs_Help[];
-
-extern const char kInputs[];
-extern const char kInputs_HelpShort[];
-extern const char kInputs_Help[];
-
-extern const char kLdflags[];
-extern const char kLdflags_HelpShort[];
-extern const char kLdflags_Help[];
-
-extern const char kLibDirs[];
-extern const char kLibDirs_HelpShort[];
-extern const char kLibDirs_Help[];
-
-extern const char kLibs[];
-extern const char kLibs_HelpShort[];
-extern const char kLibs_Help[];
-
-extern const char kOutputDir[];
-extern const char kOutputDir_HelpShort[];
-extern const char kOutputDir_Help[];
-
-extern const char kOutputExtension[];
-extern const char kOutputExtension_HelpShort[];
-extern const char kOutputExtension_Help[];
-
-extern const char kOutputName[];
-extern const char kOutputName_HelpShort[];
-extern const char kOutputName_Help[];
-
-extern const char kOutputPrefixOverride[];
-extern const char kOutputPrefixOverride_HelpShort[];
-extern const char kOutputPrefixOverride_Help[];
-
-extern const char kOutputs[];
-extern const char kOutputs_HelpShort[];
-extern const char kOutputs_Help[];
-
-extern const char kPartialInfoPlist[];
-extern const char kPartialInfoPlist_HelpShort[];
-extern const char kPartialInfoPlist_Help[];
-
-extern const char kPool[];
-extern const char kPool_HelpShort[];
-extern const char kPool_Help[];
-
-extern const char kPrecompiledHeader[];
-extern const char kPrecompiledHeader_HelpShort[];
-extern const char kPrecompiledHeader_Help[];
-
-extern const char kPrecompiledHeaderType[];
-extern const char kPrecompiledHeaderType_HelpShort[];
-extern const char kPrecompiledHeaderType_Help[];
-
-extern const char kPrecompiledSource[];
-extern const char kPrecompiledSource_HelpShort[];
-extern const char kPrecompiledSource_Help[];
-
-extern const char kProductType[];
-extern const char kProductType_HelpShort[];
-extern const char kProductType_Help[];
-
-extern const char kPublic[];
-extern const char kPublic_HelpShort[];
-extern const char kPublic_Help[];
-
-extern const char kPublicConfigs[];
-extern const char kPublicConfigs_HelpShort[];
-extern const char kPublicConfigs_Help[];
-
-extern const char kPublicDeps[];
-extern const char kPublicDeps_HelpShort[];
-extern const char kPublicDeps_Help[];
-
-extern const char kResponseFileContents[];
-extern const char kResponseFileContents_HelpShort[];
-extern const char kResponseFileContents_Help[];
-
-extern const char kScript[];
-extern const char kScript_HelpShort[];
-extern const char kScript_Help[];
-
-extern const char kSources[];
-extern const char kSources_HelpShort[];
-extern const char kSources_Help[];
-
-extern const char kXcodeTestApplicationName[];
-extern const char kXcodeTestApplicationName_HelpShort[];
-extern const char kXcodeTestApplicationName_Help[];
-
-extern const char kTestonly[];
-extern const char kTestonly_HelpShort[];
-extern const char kTestonly_Help[];
-
-extern const char kVisibility[];
-extern const char kVisibility_HelpShort[];
-extern const char kVisibility_Help[];
-
-extern const char kWriteRuntimeDeps[];
-extern const char kWriteRuntimeDeps_HelpShort[];
-extern const char kWriteRuntimeDeps_Help[];
-
-extern const char kXcodeExtraAttributes[];
-extern const char kXcodeExtraAttributes_HelpShort[];
-extern const char kXcodeExtraAttributes_Help[];
-
-// -----------------------------------------------------------------------------
-
-struct VariableInfo {
- VariableInfo();
- VariableInfo(const char* in_help_short,
- const char* in_help);
-
- const char* help_short;
- const char* help;
-};
-
-typedef std::map<base::StringPiece, VariableInfo> VariableInfoMap;
-
-// Returns the built-in readonly variables.
-// Note: this is used only for help so this getter is not threadsafe.
-const VariableInfoMap& GetBuiltinVariables();
-
-// Returns the variables used by target generators.
-// Note: this is used only for help so this getter is not threadsafe.
-const VariableInfoMap& GetTargetVariables();
-
-} // namespace variables
-
-#endif // TOOLS_GN_VARIABLES_H_
diff --git a/chromium/tools/gn/visibility.cc b/chromium/tools/gn/visibility.cc
deleted file mode 100644
index ec96824ffa1..00000000000
--- a/chromium/tools/gn/visibility.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/visibility.h"
-
-#include <memory>
-
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/values.h"
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/item.h"
-#include "tools/gn/label.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/value.h"
-#include "tools/gn/variables.h"
-
-Visibility::Visibility() = default;
-
-Visibility::~Visibility() = default;
-
-bool Visibility::Set(const SourceDir& current_dir,
- const Value& value,
- Err* err) {
- patterns_.clear();
-
- if (!value.VerifyTypeIs(Value::LIST, err)) {
- CHECK(err->has_error());
- return false;
- }
-
- for (const auto& item : value.list_value()) {
- patterns_.push_back(LabelPattern::GetPattern(current_dir, item, err));
- if (err->has_error())
- return false;
- }
- return true;
-}
-
-void Visibility::SetPublic() {
- patterns_.clear();
- patterns_.push_back(
- LabelPattern(LabelPattern::RECURSIVE_DIRECTORY, SourceDir(),
- std::string(), Label()));
-}
-
-void Visibility::SetPrivate(const SourceDir& current_dir) {
- patterns_.clear();
- patterns_.push_back(
- LabelPattern(LabelPattern::DIRECTORY, current_dir, std::string(),
- Label()));
-}
-
-bool Visibility::CanSeeMe(const Label& label) const {
- return LabelPattern::VectorMatches(patterns_, label);
-}
-
-std::string Visibility::Describe(int indent, bool include_brackets) const {
- std::string outer_indent_string(indent, ' ');
-
- if (patterns_.empty())
- return outer_indent_string + "[] (no visibility)\n";
-
- std::string result;
-
- std::string inner_indent_string = outer_indent_string;
- if (include_brackets) {
- result += outer_indent_string + "[\n";
- // Indent the insides more if brackets are requested.
- inner_indent_string += " ";
- }
-
- for (const auto& pattern : patterns_)
- result += inner_indent_string + pattern.Describe() + "\n";
-
- if (include_brackets)
- result += outer_indent_string + "]\n";
- return result;
-}
-
-std::unique_ptr<base::Value> Visibility::AsValue() const {
- auto res = std::make_unique<base::ListValue>();
- for (const auto& pattern : patterns_)
- res->AppendString(pattern.Describe());
- return std::move(res);
-}
-
-// static
-bool Visibility::CheckItemVisibility(const Item* from,
- const Item* to,
- Err* err) {
- if (!to->visibility().CanSeeMe(from->label())) {
- std::string to_label = to->label().GetUserVisibleName(false);
- *err = Err(from->defined_from(), "Dependency not allowed.",
- "The item " + from->label().GetUserVisibleName(false) + "\n"
- "can not depend on " + to_label + "\n"
- "because it is not in " + to_label + "'s visibility list: " +
- to->visibility().Describe(0, true));
- return false;
- }
- return true;
-}
-
-// static
-bool Visibility::FillItemVisibility(Item* item, Scope* scope, Err* err) {
- const Value* vis_value = scope->GetValue(variables::kVisibility, true);
- if (vis_value)
- item->visibility().Set(scope->GetSourceDir(), *vis_value, err);
- else // Default to public.
- item->visibility().SetPublic();
- return !err->has_error();
-}
diff --git a/chromium/tools/gn/visibility.h b/chromium/tools/gn/visibility.h
deleted file mode 100644
index 4228f9dae77..00000000000
--- a/chromium/tools/gn/visibility.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_VISIBILITY_H_
-#define TOOLS_GN_VISIBILITY_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "tools/gn/label_pattern.h"
-#include "tools/gn/source_dir.h"
-
-namespace base {
-class Value;
-}
-
-class Err;
-class Item;
-class Label;
-class Scope;
-class Value;
-
-class Visibility {
- public:
- // Defaults to private visibility (only the current file).
- Visibility();
- ~Visibility();
-
- // Set the visibility to the thing specified by the given value. On failure,
- // returns false and sets the error.
- bool Set(const SourceDir& current_dir, const Value& value, Err* err);
-
- // Sets the visibility to be public.
- void SetPublic();
-
- // Sets the visibility to be private to the given directory.
- void SetPrivate(const SourceDir& current_dir);
-
- // Returns true if the target with the given label can depend on one with the
- // current visibility.
- bool CanSeeMe(const Label& label) const;
-
- // Returns a string listing the visibility. |indent| number of spaces will
- // be added on the left side of the output. If |include_brackets| is set, the
- // result will be wrapped in "[ ]" and the contents further indented. The
- // result will end in a newline.
- std::string Describe(int indent, bool include_brackets) const;
-
- // Returns value representation of this visibility
- std::unique_ptr<base::Value> AsValue() const;
-
- // Helper function to check visibility between the given two items. If
- // to is invisible to from, returns false and sets the error.
- static bool CheckItemVisibility(const Item* from, const Item* to, Err* err);
-
- // Helper function to fill an item's visibility from the "visibility" value
- // in the current scope.
- static bool FillItemVisibility(Item* item, Scope* scope, Err* err);
-
- private:
- std::vector<LabelPattern> patterns_;
-
- DISALLOW_COPY_AND_ASSIGN(Visibility);
-};
-
-#endif // TOOLS_GN_VISIBILITY_H_
diff --git a/chromium/tools/gn/visibility_unittest.cc b/chromium/tools/gn/visibility_unittest.cc
deleted file mode 100644
index 7d59540b0af..00000000000
--- a/chromium/tools/gn/visibility_unittest.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/err.h"
-#include "tools/gn/label.h"
-#include "tools/gn/scope.h"
-#include "tools/gn/value.h"
-#include "tools/gn/visibility.h"
-
-TEST(Visibility, CanSeeMe) {
- Value list(nullptr, Value::LIST);
- list.list_value().push_back(Value(nullptr, "//rec/*")); // Recursive.
- list.list_value().push_back(Value(nullptr, "//dir:*")); // One dir.
- list.list_value().push_back(Value(nullptr, "//my:name")); // Exact match.
-
- Err err;
- Visibility vis;
- ASSERT_TRUE(vis.Set(SourceDir("//"), list, &err));
-
- EXPECT_FALSE(vis.CanSeeMe(Label(SourceDir("//random/"), "thing")));
- EXPECT_FALSE(vis.CanSeeMe(Label(SourceDir("//my/"), "notname")));
-
- EXPECT_TRUE(vis.CanSeeMe(Label(SourceDir("//my/"), "name")));
- EXPECT_TRUE(vis.CanSeeMe(Label(SourceDir("//rec/"), "anything")));
- EXPECT_TRUE(vis.CanSeeMe(Label(SourceDir("//rec/a/"), "anything")));
- EXPECT_TRUE(vis.CanSeeMe(Label(SourceDir("//rec/b/"), "anything")));
- EXPECT_TRUE(vis.CanSeeMe(Label(SourceDir("//dir/"), "anything")));
- EXPECT_FALSE(vis.CanSeeMe(Label(SourceDir("//dir/a/"), "anything")));
- EXPECT_FALSE(vis.CanSeeMe(Label(SourceDir("//directory/"), "anything")));
-}
-
-TEST(Visibility, Public) {
- Err err;
- Visibility vis;
-
- Value list(nullptr, Value::LIST);
- list.list_value().push_back(Value(nullptr, "*"));
- ASSERT_TRUE(vis.Set(SourceDir("//"), list, &err));
-
- EXPECT_TRUE(vis.CanSeeMe(Label(SourceDir("//random/"), "thing")));
- EXPECT_TRUE(vis.CanSeeMe(Label(SourceDir("//"), "")));
-}
-
-TEST(Visibility, Private) {
- Err err;
- Visibility vis;
- ASSERT_TRUE(vis.Set(SourceDir("//"), Value(nullptr, Value::LIST), &err));
-
- EXPECT_FALSE(vis.CanSeeMe(Label(SourceDir("//random/"), "thing")));
- EXPECT_FALSE(vis.CanSeeMe(Label(SourceDir("//"), "")));
-}
diff --git a/chromium/tools/gn/visual_studio_utils.cc b/chromium/tools/gn/visual_studio_utils.cc
deleted file mode 100644
index 94a28833ca0..00000000000
--- a/chromium/tools/gn/visual_studio_utils.cc
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/visual_studio_utils.h"
-
-#include <vector>
-
-#include "base/md5.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-
-CompilerOptions::CompilerOptions() = default;
-
-CompilerOptions::~CompilerOptions() = default;
-
-LinkerOptions::LinkerOptions() = default;
-
-LinkerOptions::~LinkerOptions() = default;
-
-std::string MakeGuid(const std::string& entry_path, const std::string& seed) {
- std::string str = base::ToUpperASCII(base::MD5String(seed + entry_path));
- return '{' + str.substr(0, 8) + '-' + str.substr(8, 4) + '-' +
- str.substr(12, 4) + '-' + str.substr(16, 4) + '-' +
- str.substr(20, 12) + '}';
-}
-
-#define SetOption(condition, member, value) \
- if (condition) { \
- options->member = value; \
- return; \
- }
-
-#define AppendOption(condition, member, value, separator) \
- if (condition) { \
- options->member += value + separator; \
- return; \
- }
-
-void ParseCompilerOption(const std::string& cflag, CompilerOptions* options) {
- if (cflag.size() > 2 && cflag[0] == '/') {
- switch (cflag[1]) {
- case 'F':
- AppendOption(cflag.size() > 3 && cflag[2] == 'I', forced_include_files,
- cflag.substr(3), ';')
- break;
-
- case 'G':
- if (cflag[2] == 'S') {
- SetOption(cflag.size() == 3, buffer_security_check, "true")
- SetOption(cflag.size() == 4 && cflag[3] == '-',
- buffer_security_check, "false")
- }
- break;
-
- case 'M':
- switch (cflag[2]) {
- case 'D':
- SetOption(cflag.size() == 3, runtime_library, "MultiThreadedDLL")
- SetOption(cflag.size() == 4 && cflag[3] == 'd', runtime_library,
- "MultiThreadedDebugDLL")
- break;
-
- case 'T':
- SetOption(cflag.size() == 3, runtime_library, "MultiThreaded")
- SetOption(cflag.size() == 4 && cflag[3] == 'd', runtime_library,
- "MultiThreadedDebug")
- break;
- }
- break;
-
- case 'O':
- switch (cflag[2]) {
- case '1':
- SetOption(cflag.size() == 3, optimization, "MinSpace")
- break;
-
- case '2':
- SetOption(cflag.size() == 3, optimization, "MaxSpeed")
- break;
-
- case 'd':
- SetOption(cflag.size() == 3, optimization, "Disabled")
- break;
-
- case 'x':
- SetOption(cflag.size() == 3, optimization, "Full")
- break;
- }
- break;
-
- case 'T':
- // Skip flags that cause treating all source files as C and C++ files.
- if (cflag.size() == 3 && (cflag[2] == 'C' || cflag[2] == 'P'))
- return;
- break;
-
- case 'W':
- switch (cflag[2]) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- SetOption(cflag.size() == 3, warning_level,
- std::string("Level") + cflag[2])
- break;
-
- case 'X':
- SetOption(cflag.size() == 3, treat_warning_as_error, "true")
- break;
- }
- break;
-
- case 'w':
- AppendOption(cflag.size() > 3 && cflag[2] == 'd',
- disable_specific_warnings, cflag.substr(3), ';')
- break;
- }
- }
-
- // Put everything else into additional_options.
- options->additional_options += cflag + ' ';
-}
-
-// Parses |ldflags| value and stores it in |options|.
-void ParseLinkerOption(const std::string& ldflag, LinkerOptions* options) {
- const char kSubsytemPrefix[] ="/SUBSYSTEM:";
- if (base::StartsWith(ldflag, kSubsytemPrefix,
- base::CompareCase::SENSITIVE)) {
- const std::string subsystem(
- ldflag.begin() + std::string(kSubsytemPrefix).length(),
- ldflag.end());
- const std::vector<std::string> tokens = base::SplitString(
- subsystem, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- if (!tokens.empty())
- options->subsystem = tokens[0];
- }
-}
diff --git a/chromium/tools/gn/visual_studio_utils.h b/chromium/tools/gn/visual_studio_utils.h
deleted file mode 100644
index 319428fbc13..00000000000
--- a/chromium/tools/gn/visual_studio_utils.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_VISUAL_STUDIO_UTILS_H_
-#define TOOLS_GN_VISUAL_STUDIO_UTILS_H_
-
-#include <string>
-
-// Some compiler options which will be written to project file. We don't need to
-// specify all options because generated project file is going to be used only
-// for compilation of single file. For real build ninja files are used.
-struct CompilerOptions {
- CompilerOptions();
- ~CompilerOptions();
-
- std::string additional_options;
- std::string buffer_security_check;
- std::string forced_include_files;
- std::string disable_specific_warnings;
- std::string optimization;
- std::string runtime_library;
- std::string treat_warning_as_error;
- std::string warning_level;
-};
-
-// Some linker options which will be written to project file. We don't need to
-// specify all options because generated project file is going to be used only
-// for compilation of single file. For real build ninja files are used.
-struct LinkerOptions {
- LinkerOptions();
- ~LinkerOptions();
-
- std::string subsystem;
-};
-
-// Generates something which looks like a GUID, but depends only on the name and
-// seed. This means the same name / seed will always generate the same GUID, so
-// that projects and solutions which refer to each other can explicitly
-// determine the GUID to refer to explicitly. It also means that the GUID will
-// not change when the project for a target is rebuilt.
-std::string MakeGuid(const std::string& entry_path, const std::string& seed);
-
-// Parses |cflag| value and stores it in |options|.
-void ParseCompilerOption(const std::string& cflag, CompilerOptions* options);
-
-// Parses |ldflags| value and stores it in |options|.
-void ParseLinkerOption(const std::string& ldflag, LinkerOptions* options);
-
-#endif // TOOLS_GN_VISUAL_STUDIO_UTILS_H_
diff --git a/chromium/tools/gn/visual_studio_utils_unittest.cc b/chromium/tools/gn/visual_studio_utils_unittest.cc
deleted file mode 100644
index 261c030536d..00000000000
--- a/chromium/tools/gn/visual_studio_utils_unittest.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/visual_studio_utils.h"
-
-#include "base/location.h"
-#include "base/strings/string_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-TEST(VisualStudioUtils, MakeGuid) {
- std::string pattern = "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}";
- std::string guid = MakeGuid(__FILE__, "foo");
- ASSERT_EQ(pattern.size(), guid.size());
- for (size_t i = 0; i < pattern.size(); ++i) {
- if (pattern[i] == 'x')
- ASSERT_TRUE(base::IsAsciiAlpha(guid[i]) || base::IsAsciiDigit(guid[i]));
- else
- ASSERT_EQ(pattern[i], guid[i]);
- }
-
- // Calling function again should produce the same GUID.
- ASSERT_EQ(guid, MakeGuid(__FILE__, "foo"));
-
- // GUIDs should be different if path or seed is different.
- ASSERT_NE(guid, MakeGuid(std::string(__FILE__) + ".txt", "foo"));
- ASSERT_NE(guid, MakeGuid(__FILE__, "bar"));
-}
-
-TEST(VisualStudioUtils, ParseCompilerOption) {
- CompilerOptions options;
- ParseCompilerOption("/FIinclude.h", &options);
- ParseCompilerOption("/FIC:/path/file.h", &options);
- ASSERT_EQ("include.h;C:/path/file.h;", options.forced_include_files);
-
- CHECK(options.buffer_security_check.empty());
- ParseCompilerOption("/GS", &options);
- ASSERT_EQ("true", options.buffer_security_check);
- ParseCompilerOption("/GS-", &options);
- ASSERT_EQ("false", options.buffer_security_check);
-
- CHECK(options.runtime_library.empty());
- ParseCompilerOption("/MD", &options);
- ASSERT_EQ("MultiThreadedDLL", options.runtime_library);
- ParseCompilerOption("/MDd", &options);
- ASSERT_EQ("MultiThreadedDebugDLL", options.runtime_library);
- ParseCompilerOption("/MT", &options);
- ASSERT_EQ("MultiThreaded", options.runtime_library);
- ParseCompilerOption("/MTd", &options);
- ASSERT_EQ("MultiThreadedDebug", options.runtime_library);
-
- CHECK(options.optimization.empty());
- ParseCompilerOption("/O1", &options);
- ASSERT_EQ("MinSpace", options.optimization);
- ParseCompilerOption("/O2", &options);
- ASSERT_EQ("MaxSpeed", options.optimization);
- ParseCompilerOption("/Od", &options);
- ASSERT_EQ("Disabled", options.optimization);
- ParseCompilerOption("/Ox", &options);
- ASSERT_EQ("Full", options.optimization);
-
- CHECK(options.additional_options.empty());
- ParseCompilerOption("/TC", &options);
- ASSERT_TRUE(options.additional_options.empty());
- ParseCompilerOption("/TP", &options);
- ASSERT_TRUE(options.additional_options.empty());
-
- CHECK(options.warning_level.empty());
- ParseCompilerOption("/W0", &options);
- ASSERT_EQ("Level0", options.warning_level);
- ParseCompilerOption("/W1", &options);
- ASSERT_EQ("Level1", options.warning_level);
- ParseCompilerOption("/W2", &options);
- ASSERT_EQ("Level2", options.warning_level);
- ParseCompilerOption("/W3", &options);
- ASSERT_EQ("Level3", options.warning_level);
- ParseCompilerOption("/W4", &options);
- ASSERT_EQ("Level4", options.warning_level);
-
- CHECK(options.treat_warning_as_error.empty());
- ParseCompilerOption("/WX", &options);
- ASSERT_EQ("true", options.treat_warning_as_error);
-
- CHECK(options.disable_specific_warnings.empty());
- ParseCompilerOption("/wd1234", &options);
- ParseCompilerOption("/wd56", &options);
- ASSERT_EQ("1234;56;", options.disable_specific_warnings);
-
- CHECK(options.additional_options.empty());
- ParseCompilerOption("/MP", &options);
- ParseCompilerOption("/bigobj", &options);
- ParseCompilerOption("/Zc:sizedDealloc", &options);
- ASSERT_EQ("/MP /bigobj /Zc:sizedDealloc ", options.additional_options);
-}
-
-TEST(VisualStudioUtils, ParseLinkerOption) {
- LinkerOptions options;
- ParseLinkerOption("/SUBSYSTEM:CONSOLE,5.02h", &options);
- ASSERT_EQ("CONSOLE", options.subsystem);
-
- ParseLinkerOption("/SUBSYSTEM:WINDOWS", &options);
- ASSERT_EQ("WINDOWS", options.subsystem);
-}
diff --git a/chromium/tools/gn/visual_studio_writer.cc b/chromium/tools/gn/visual_studio_writer.cc
deleted file mode 100644
index 856d54856b9..00000000000
--- a/chromium/tools/gn/visual_studio_writer.cc
+++ /dev/null
@@ -1,908 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/visual_studio_writer.h"
-
-#include <algorithm>
-#include <iterator>
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-
-#include "base/containers/queue.h"
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "tools/gn/builder.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/config.h"
-#include "tools/gn/config_values_extractors.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/label_pattern.h"
-#include "tools/gn/parse_tree.h"
-#include "tools/gn/path_output.h"
-#include "tools/gn/source_file_type.h"
-#include "tools/gn/standard_out.h"
-#include "tools/gn/target.h"
-#include "tools/gn/variables.h"
-#include "tools/gn/visual_studio_utils.h"
-#include "tools/gn/xml_element_writer.h"
-
-#if defined(OS_WIN)
-#include "base/win/registry.h"
-#endif
-
-namespace {
-
-struct SemicolonSeparatedWriter {
- void operator()(const std::string& value, std::ostream& out) const {
- out << XmlEscape(value) + ';';
- }
-};
-
-struct IncludeDirWriter {
- explicit IncludeDirWriter(PathOutput& path_output)
- : path_output_(path_output) {}
- ~IncludeDirWriter() = default;
-
- void operator()(const SourceDir& dir, std::ostream& out) const {
- path_output_.WriteDir(out, dir, PathOutput::DIR_NO_LAST_SLASH);
- out << ";";
- }
-
- PathOutput& path_output_;
-};
-
-struct SourceFileWriter {
- SourceFileWriter(PathOutput& path_output, const SourceFile& source_file)
- : path_output_(path_output), source_file_(source_file) {}
- ~SourceFileWriter() = default;
-
- void operator()(std::ostream& out) const {
- path_output_.WriteFile(out, source_file_);
- }
-
- PathOutput& path_output_;
- const SourceFile& source_file_;
-};
-
-const char kToolsetVersionVs2013[] = "v120"; // Visual Studio 2013
-const char kToolsetVersionVs2015[] = "v140"; // Visual Studio 2015
-const char kToolsetVersionVs2017[] = "v141"; // Visual Studio 2017
-const char kProjectVersionVs2013[] = "12.0"; // Visual Studio 2013
-const char kProjectVersionVs2015[] = "14.0"; // Visual Studio 2015
-const char kProjectVersionVs2017[] = "15.0"; // Visual Studio 2017
-const char kVersionStringVs2013[] = "Visual Studio 2013"; // Visual Studio 2013
-const char kVersionStringVs2015[] = "Visual Studio 2015"; // Visual Studio 2015
-const char kVersionStringVs2017[] = "Visual Studio 2017"; // Visual Studio 2017
-const char kWindowsKitsVersion[] = "10"; // Windows 10 SDK
-const char kWindowsKitsDefaultVersion[] = "10.0.17134.0"; // Windows 10 SDK
-
-const char kGuidTypeProject[] = "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}";
-const char kGuidTypeFolder[] = "{2150E333-8FDC-42A3-9474-1A3956D46DE8}";
-const char kGuidSeedProject[] = "project";
-const char kGuidSeedFolder[] = "folder";
-const char kGuidSeedFilter[] = "filter";
-
-const char kConfigurationName[] = "GN";
-
-const char kCharSetUnicode[] = "_UNICODE";
-const char kCharSetMultiByte[] = "_MBCS";
-
-std::string GetWindowsKitsIncludeDirs(const std::string& win_kit) {
- std::string kits_path;
-
-#if defined(OS_WIN)
- const base::char16* const subkeys[] = {
- L"SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots",
- L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows Kits\\Installed Roots"};
-
- base::string16 value_name =
- base::ASCIIToUTF16("KitsRoot") + base::ASCIIToUTF16(kWindowsKitsVersion);
-
- for (const base::char16* subkey : subkeys) {
- base::win::RegKey key(HKEY_LOCAL_MACHINE, subkey, KEY_READ);
- base::string16 value;
- if (key.ReadValue(value_name.c_str(), &value) == ERROR_SUCCESS) {
- kits_path = base::UTF16ToUTF8(value);
- break;
- }
- }
-#endif // OS_WIN
-
- if (kits_path.empty()) {
- kits_path = std::string("C:\\Program Files (x86)\\Windows Kits\\") +
- kWindowsKitsVersion + "\\";
- }
-
- const std::string kit_prefix = kits_path + "Include\\" + win_kit + "\\";
- return kit_prefix + "shared;" + kit_prefix + "um;" + kit_prefix + "winrt;";
-}
-
-std::string GetConfigurationType(const Target* target, Err* err) {
- switch (target->output_type()) {
- case Target::EXECUTABLE:
- return "Application";
- case Target::SHARED_LIBRARY:
- case Target::LOADABLE_MODULE:
- return "DynamicLibrary";
- case Target::STATIC_LIBRARY:
- case Target::SOURCE_SET:
- return "StaticLibrary";
- case Target::GROUP:
- return "Utility";
-
- default:
- *err = Err(Location(),
- "Visual Studio doesn't support '" + target->label().name() +
- "' target output type: " +
- Target::GetStringForOutputType(target->output_type()));
- return std::string();
- }
-}
-
-void ParseCompilerOptions(const std::vector<std::string>& cflags,
- CompilerOptions* options) {
- for (const std::string& flag : cflags)
- ParseCompilerOption(flag, options);
-}
-
-void ParseCompilerOptions(const Target* target, CompilerOptions* options) {
- for (ConfigValuesIterator iter(target); !iter.done(); iter.Next()) {
- ParseCompilerOptions(iter.cur().cflags(), options);
- ParseCompilerOptions(iter.cur().cflags_c(), options);
- ParseCompilerOptions(iter.cur().cflags_cc(), options);
- }
-}
-
-void ParseLinkerOptions(const std::vector<std::string>& ldflags,
- LinkerOptions* options) {
- for (const std::string& flag : ldflags)
- ParseLinkerOption(flag, options);
-}
-
-void ParseLinkerOptions(const Target* target, LinkerOptions* options) {
- for (ConfigValuesIterator iter(target); !iter.done(); iter.Next()) {
- ParseLinkerOptions(iter.cur().ldflags(), options);
- }
-}
-
-// Returns a string piece pointing into the input string identifying the parent
-// directory path, excluding the last slash. Note that the input pointer must
-// outlive the output.
-base::StringPiece FindParentDir(const std::string* path) {
- DCHECK(path && !path->empty());
- for (int i = static_cast<int>(path->size()) - 2; i >= 0; --i) {
- if (IsSlash((*path)[i]))
- return base::StringPiece(path->data(), i);
- }
- return base::StringPiece();
-}
-
-bool FilterTargets(const BuildSettings* build_settings,
- const Builder& builder,
- const std::string& filters,
- bool no_deps,
- std::vector<const Target*>* targets,
- Err* err) {
- if (filters.empty()) {
- *targets = builder.GetAllResolvedTargets();
- return true;
- }
-
- std::vector<LabelPattern> patterns;
- if (!commands::FilterPatternsFromString(build_settings, filters, &patterns,
- err))
- return false;
-
- commands::FilterTargetsByPatterns(builder.GetAllResolvedTargets(), patterns,
- targets);
-
- if (no_deps)
- return true;
-
- std::set<Label> labels;
- base::queue<const Target*> to_process;
- for (const Target* target : *targets) {
- labels.insert(target->label());
- to_process.push(target);
- }
-
- while (!to_process.empty()) {
- const Target* target = to_process.front();
- to_process.pop();
- for (const auto& pair : target->GetDeps(Target::DEPS_ALL)) {
- if (labels.find(pair.label) == labels.end()) {
- targets->push_back(pair.ptr);
- to_process.push(pair.ptr);
- labels.insert(pair.label);
- }
- }
- }
-
- return true;
-}
-
-bool UnicodeTarget(const Target* target) {
- for (ConfigValuesIterator it(target); !it.done(); it.Next()) {
- for (const std::string& define : it.cur().defines()) {
- if (define == kCharSetUnicode)
- return true;
- if (define == kCharSetMultiByte)
- return false;
- }
- }
- return true;
-}
-
-} // namespace
-
-VisualStudioWriter::SolutionEntry::SolutionEntry(const std::string& _name,
- const std::string& _path,
- const std::string& _guid)
- : name(_name), path(_path), guid(_guid), parent_folder(nullptr) {}
-
-VisualStudioWriter::SolutionEntry::~SolutionEntry() = default;
-
-VisualStudioWriter::SolutionProject::SolutionProject(
- const std::string& _name,
- const std::string& _path,
- const std::string& _guid,
- const std::string& _label_dir_path,
- const std::string& _config_platform)
- : SolutionEntry(_name, _path, _guid),
- label_dir_path(_label_dir_path),
- config_platform(_config_platform) {
- // Make sure all paths use the same drive letter case. This is especially
- // important when searching for the common path prefix.
- label_dir_path[0] = base::ToUpperASCII(label_dir_path[0]);
-}
-
-VisualStudioWriter::SolutionProject::~SolutionProject() = default;
-
-VisualStudioWriter::SourceFileCompileTypePair::SourceFileCompileTypePair(
- const SourceFile* _file,
- const char* _compile_type)
- : file(_file), compile_type(_compile_type) {}
-
-VisualStudioWriter::SourceFileCompileTypePair::~SourceFileCompileTypePair() =
- default;
-
-VisualStudioWriter::VisualStudioWriter(const BuildSettings* build_settings,
- const char* config_platform,
- Version version,
- const std::string& win_kit)
- : build_settings_(build_settings),
- config_platform_(config_platform),
- ninja_path_output_(build_settings->build_dir(),
- build_settings->root_path_utf8(),
- EscapingMode::ESCAPE_NINJA_COMMAND),
- windows_sdk_version_(win_kit) {
- DCHECK(!win_kit.empty());
-
- switch (version) {
- case Version::Vs2013:
- project_version_ = kProjectVersionVs2013;
- toolset_version_ = kToolsetVersionVs2013;
- version_string_ = kVersionStringVs2013;
- break;
- case Version::Vs2015:
- project_version_ = kProjectVersionVs2015;
- toolset_version_ = kToolsetVersionVs2015;
- version_string_ = kVersionStringVs2015;
- break;
- case Version::Vs2017:
- project_version_ = kProjectVersionVs2017;
- toolset_version_ = kToolsetVersionVs2017;
- version_string_ = kVersionStringVs2017;
- break;
- default:
- NOTREACHED() << "Not a valid Visual Studio Version: " << version;
- }
-
- windows_kits_include_dirs_ = GetWindowsKitsIncludeDirs(win_kit);
-}
-
-VisualStudioWriter::~VisualStudioWriter() = default;
-
-// static
-bool VisualStudioWriter::RunAndWriteFiles(const BuildSettings* build_settings,
- const Builder& builder,
- Version version,
- const std::string& sln_name,
- const std::string& filters,
- const std::string& win_sdk,
- const std::string& ninja_extra_args,
- bool no_deps,
- Err* err) {
- std::vector<const Target*> targets;
- if (!FilterTargets(build_settings, builder, filters, no_deps, &targets, err))
- return false;
-
- std::string win_kit = kWindowsKitsDefaultVersion;
- if (!win_sdk.empty())
- win_kit = win_sdk;
-
- const char* config_platform = "Win32";
-
- // Assume the "target_cpu" variable does not change between different
- // toolchains.
- if (!targets.empty()) {
- const Scope* scope = targets.front()->settings()->base_config();
- const Value* target_cpu_value = scope->GetValue(variables::kTargetCpu);
- if (target_cpu_value != nullptr &&
- target_cpu_value->string_value() == "x64")
- config_platform = "x64";
- }
-
- VisualStudioWriter writer(build_settings, config_platform, version, win_kit);
- writer.projects_.reserve(targets.size());
- writer.folders_.reserve(targets.size());
-
- for (const Target* target : targets) {
- // Skip actions and bundle targets.
- if (target->output_type() == Target::COPY_FILES ||
- target->output_type() == Target::ACTION ||
- target->output_type() == Target::ACTION_FOREACH ||
- target->output_type() == Target::BUNDLE_DATA) {
- continue;
- }
-
- if (!writer.WriteProjectFiles(target, ninja_extra_args, err))
- return false;
- }
-
- if (writer.projects_.empty()) {
- *err = Err(Location(), "No Visual Studio projects generated.");
- return false;
- }
-
- // Sort projects so they appear always in the same order in solution file.
- // Otherwise solution file is rewritten and reloaded by Visual Studio.
- std::sort(writer.projects_.begin(), writer.projects_.end(),
- [](const std::unique_ptr<SolutionProject>& a,
- const std::unique_ptr<SolutionProject>& b) {
- return a->path < b->path;
- });
-
- writer.ResolveSolutionFolders();
- return writer.WriteSolutionFile(sln_name, err);
-}
-
-bool VisualStudioWriter::WriteProjectFiles(const Target* target,
- const std::string& ninja_extra_args,
- Err* err) {
- std::string project_name = target->label().name();
- const char* project_config_platform = config_platform_;
- if (!target->settings()->is_default()) {
- project_name += "_" + target->toolchain()->label().name();
- const Value* value =
- target->settings()->base_config()->GetValue(variables::kCurrentCpu);
- if (value != nullptr && value->string_value() == "x64")
- project_config_platform = "x64";
- else
- project_config_platform = "Win32";
- }
-
- SourceFile target_file =
- GetBuildDirForTargetAsSourceDir(target, BuildDirType::OBJ)
- .ResolveRelativeFile(Value(nullptr, project_name + ".vcxproj"), err);
- if (target_file.is_null())
- return false;
-
- base::FilePath vcxproj_path = build_settings_->GetFullPath(target_file);
- std::string vcxproj_path_str = FilePathToUTF8(vcxproj_path);
-
- projects_.push_back(std::make_unique<SolutionProject>(
- project_name, vcxproj_path_str,
- MakeGuid(vcxproj_path_str, kGuidSeedProject),
- FilePathToUTF8(build_settings_->GetFullPath(target->label().dir())),
- project_config_platform));
-
- std::stringstream vcxproj_string_out;
- SourceFileCompileTypePairs source_types;
- if (!WriteProjectFileContents(vcxproj_string_out, *projects_.back(), target,
- ninja_extra_args, &source_types, err)) {
- projects_.pop_back();
- return false;
- }
-
- // Only write the content to the file if it's different. That is
- // both a performance optimization and more importantly, prevents
- // Visual Studio from reloading the projects.
- if (!WriteFileIfChanged(vcxproj_path, vcxproj_string_out.str(), err))
- return false;
-
- base::FilePath filters_path = UTF8ToFilePath(vcxproj_path_str + ".filters");
- std::stringstream filters_string_out;
- WriteFiltersFileContents(filters_string_out, target, source_types);
- return WriteFileIfChanged(filters_path, filters_string_out.str(), err);
-}
-
-bool VisualStudioWriter::WriteProjectFileContents(
- std::ostream& out,
- const SolutionProject& solution_project,
- const Target* target,
- const std::string& ninja_extra_args,
- SourceFileCompileTypePairs* source_types,
- Err* err) {
- PathOutput path_output(
- GetBuildDirForTargetAsSourceDir(target, BuildDirType::OBJ),
- build_settings_->root_path_utf8(), EscapingMode::ESCAPE_NONE);
-
- out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl;
- XmlElementWriter project(
- out, "Project",
- XmlAttributes("DefaultTargets", "Build")
- .add("ToolsVersion", project_version_)
- .add("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"));
-
- {
- std::unique_ptr<XmlElementWriter> configurations = project.SubElement(
- "ItemGroup", XmlAttributes("Label", "ProjectConfigurations"));
- std::unique_ptr<XmlElementWriter> project_config =
- configurations->SubElement(
- "ProjectConfiguration",
- XmlAttributes("Include", std::string(kConfigurationName) + '|' +
- solution_project.config_platform));
- project_config->SubElement("Configuration")->Text(kConfigurationName);
- project_config->SubElement("Platform")
- ->Text(solution_project.config_platform);
- }
-
- {
- std::unique_ptr<XmlElementWriter> globals =
- project.SubElement("PropertyGroup", XmlAttributes("Label", "Globals"));
- globals->SubElement("ProjectGuid")->Text(solution_project.guid);
- globals->SubElement("Keyword")->Text("Win32Proj");
- globals->SubElement("RootNamespace")->Text(target->label().name());
- globals->SubElement("IgnoreWarnCompileDuplicatedFilename")->Text("true");
- globals->SubElement("PreferredToolArchitecture")->Text("x64");
- globals->SubElement("WindowsTargetPlatformVersion")
- ->Text(windows_sdk_version_);
- }
-
- project.SubElement(
- "Import", XmlAttributes("Project",
- "$(VCTargetsPath)\\Microsoft.Cpp.Default.props"));
-
- {
- std::unique_ptr<XmlElementWriter> configuration = project.SubElement(
- "PropertyGroup", XmlAttributes("Label", "Configuration"));
- bool unicode_target = UnicodeTarget(target);
- configuration->SubElement("CharacterSet")
- ->Text(unicode_target ? "Unicode" : "MultiByte");
- std::string configuration_type = GetConfigurationType(target, err);
- if (configuration_type.empty())
- return false;
- configuration->SubElement("ConfigurationType")->Text(configuration_type);
- }
-
- {
- std::unique_ptr<XmlElementWriter> locals =
- project.SubElement("PropertyGroup", XmlAttributes("Label", "Locals"));
- locals->SubElement("PlatformToolset")->Text(toolset_version_);
- }
-
- project.SubElement(
- "Import",
- XmlAttributes("Project", "$(VCTargetsPath)\\Microsoft.Cpp.props"));
- project.SubElement(
- "Import",
- XmlAttributes("Project",
- "$(VCTargetsPath)\\BuildCustomizations\\masm.props"));
- project.SubElement("ImportGroup",
- XmlAttributes("Label", "ExtensionSettings"));
-
- {
- std::unique_ptr<XmlElementWriter> property_sheets = project.SubElement(
- "ImportGroup", XmlAttributes("Label", "PropertySheets"));
- property_sheets->SubElement(
- "Import",
- XmlAttributes(
- "Condition",
- "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')")
- .add("Label", "LocalAppDataPlatform")
- .add("Project",
- "$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props"));
- }
-
- project.SubElement("PropertyGroup", XmlAttributes("Label", "UserMacros"));
-
- std::string ninja_target = GetNinjaTarget(target);
-
- {
- std::unique_ptr<XmlElementWriter> properties =
- project.SubElement("PropertyGroup");
- {
- std::unique_ptr<XmlElementWriter> out_dir =
- properties->SubElement("OutDir");
- path_output.WriteDir(out_dir->StartContent(false),
- build_settings_->build_dir(),
- PathOutput::DIR_INCLUDE_LAST_SLASH);
- }
- properties->SubElement("TargetName")->Text("$(ProjectName)");
- if (target->output_type() != Target::GROUP) {
- properties->SubElement("TargetPath")->Text("$(OutDir)\\" + ninja_target);
- }
- }
-
- {
- std::unique_ptr<XmlElementWriter> item_definitions =
- project.SubElement("ItemDefinitionGroup");
- {
- std::unique_ptr<XmlElementWriter> cl_compile =
- item_definitions->SubElement("ClCompile");
- {
- std::unique_ptr<XmlElementWriter> include_dirs =
- cl_compile->SubElement("AdditionalIncludeDirectories");
- RecursiveTargetConfigToStream<SourceDir>(
- target, &ConfigValues::include_dirs, IncludeDirWriter(path_output),
- include_dirs->StartContent(false));
- include_dirs->Text(windows_kits_include_dirs_ +
- "$(VSInstallDir)\\VC\\atlmfc\\include;" +
- "%(AdditionalIncludeDirectories)");
- }
- CompilerOptions options;
- ParseCompilerOptions(target, &options);
- if (!options.additional_options.empty()) {
- cl_compile->SubElement("AdditionalOptions")
- ->Text(options.additional_options + "%(AdditionalOptions)");
- }
- if (!options.buffer_security_check.empty()) {
- cl_compile->SubElement("BufferSecurityCheck")
- ->Text(options.buffer_security_check);
- }
- cl_compile->SubElement("CompileAsWinRT")->Text("false");
- cl_compile->SubElement("DebugInformationFormat")->Text("ProgramDatabase");
- if (!options.disable_specific_warnings.empty()) {
- cl_compile->SubElement("DisableSpecificWarnings")
- ->Text(options.disable_specific_warnings +
- "%(DisableSpecificWarnings)");
- }
- cl_compile->SubElement("ExceptionHandling")->Text("false");
- if (!options.forced_include_files.empty()) {
- cl_compile->SubElement("ForcedIncludeFiles")
- ->Text(options.forced_include_files);
- }
- cl_compile->SubElement("MinimalRebuild")->Text("false");
- if (!options.optimization.empty())
- cl_compile->SubElement("Optimization")->Text(options.optimization);
- cl_compile->SubElement("PrecompiledHeader")->Text("NotUsing");
- {
- std::unique_ptr<XmlElementWriter> preprocessor_definitions =
- cl_compile->SubElement("PreprocessorDefinitions");
- RecursiveTargetConfigToStream<std::string>(
- target, &ConfigValues::defines, SemicolonSeparatedWriter(),
- preprocessor_definitions->StartContent(false));
- preprocessor_definitions->Text("%(PreprocessorDefinitions)");
- }
- if (!options.runtime_library.empty())
- cl_compile->SubElement("RuntimeLibrary")->Text(options.runtime_library);
- if (!options.treat_warning_as_error.empty()) {
- cl_compile->SubElement("TreatWarningAsError")
- ->Text(options.treat_warning_as_error);
- }
- if (!options.warning_level.empty())
- cl_compile->SubElement("WarningLevel")->Text(options.warning_level);
- }
-
- std::unique_ptr<XmlElementWriter> link =
- item_definitions->SubElement("Link");
- {
- LinkerOptions options;
- ParseLinkerOptions(target, &options);
- if (!options.subsystem.empty())
- link->SubElement("SubSystem")->Text(options.subsystem);
- }
-
- // We don't include resource compilation and other link options as ninja
- // files are used to generate real build.
- }
-
- {
- std::unique_ptr<XmlElementWriter> group = project.SubElement("ItemGroup");
- std::vector<OutputFile> tool_outputs; // Prevent reallocation in loop.
-
- for (const SourceFile& file : target->sources()) {
- const char* compile_type;
- Toolchain::ToolType tool_type = Toolchain::TYPE_NONE;
- if (target->GetOutputFilesForSource(file, &tool_type, &tool_outputs)) {
- compile_type = "CustomBuild";
- std::unique_ptr<XmlElementWriter> build = group->SubElement(
- compile_type, "Include", SourceFileWriter(path_output, file));
- build->SubElement("Command")->Text("call ninja.exe -C $(OutDir) " +
- ninja_extra_args + " " +
- tool_outputs[0].value());
- build->SubElement("Outputs")->Text("$(OutDir)" +
- tool_outputs[0].value());
- } else {
- compile_type = "None";
- group->SubElement(compile_type, "Include",
- SourceFileWriter(path_output, file));
- }
- source_types->push_back(SourceFileCompileTypePair(&file, compile_type));
- }
- }
-
- project.SubElement(
- "Import",
- XmlAttributes("Project", "$(VCTargetsPath)\\Microsoft.Cpp.targets"));
- project.SubElement(
- "Import",
- XmlAttributes("Project",
- "$(VCTargetsPath)\\BuildCustomizations\\masm.targets"));
- project.SubElement("ImportGroup", XmlAttributes("Label", "ExtensionTargets"));
-
- {
- std::unique_ptr<XmlElementWriter> build =
- project.SubElement("Target", XmlAttributes("Name", "Build"));
- build->SubElement(
- "Exec",
- XmlAttributes("Command", "call ninja.exe -C $(OutDir) " +
- ninja_extra_args + " " + ninja_target));
- }
-
- {
- std::unique_ptr<XmlElementWriter> clean =
- project.SubElement("Target", XmlAttributes("Name", "Clean"));
- clean->SubElement(
- "Exec",
- XmlAttributes("Command",
- "call ninja.exe -C $(OutDir) -tclean " + ninja_target));
- }
-
- return true;
-}
-
-void VisualStudioWriter::WriteFiltersFileContents(
- std::ostream& out,
- const Target* target,
- const SourceFileCompileTypePairs& source_types) {
- out << "<?xml version=\"1.0\" encoding=\"utf-8\"?>" << std::endl;
- XmlElementWriter project(
- out, "Project",
- XmlAttributes("ToolsVersion", "4.0")
- .add("xmlns", "http://schemas.microsoft.com/developer/msbuild/2003"));
-
- std::ostringstream files_out;
-
- {
- std::unique_ptr<XmlElementWriter> filters_group =
- project.SubElement("ItemGroup");
- XmlElementWriter files_group(files_out, "ItemGroup", XmlAttributes(), 2);
-
- // File paths are relative to vcxproj files which are generated to out dirs.
- // Filters tree structure need to reflect source directories and be relative
- // to target file. We need two path outputs then.
- PathOutput file_path_output(
- GetBuildDirForTargetAsSourceDir(target, BuildDirType::OBJ),
- build_settings_->root_path_utf8(), EscapingMode::ESCAPE_NONE);
- PathOutput filter_path_output(target->label().dir(),
- build_settings_->root_path_utf8(),
- EscapingMode::ESCAPE_NONE);
-
- std::set<std::string> processed_filters;
-
- for (const auto& file_and_type : source_types) {
- std::unique_ptr<XmlElementWriter> cl_item = files_group.SubElement(
- file_and_type.compile_type, "Include",
- SourceFileWriter(file_path_output, *file_and_type.file));
-
- std::ostringstream target_relative_out;
- filter_path_output.WriteFile(target_relative_out, *file_and_type.file);
- std::string target_relative_path = target_relative_out.str();
- ConvertPathToSystem(&target_relative_path);
- base::StringPiece filter_path = FindParentDir(&target_relative_path);
-
- if (!filter_path.empty()) {
- std::string filter_path_str = filter_path.as_string();
- while (processed_filters.find(filter_path_str) ==
- processed_filters.end()) {
- auto it = processed_filters.insert(filter_path_str).first;
- filters_group
- ->SubElement("Filter", XmlAttributes("Include", filter_path_str))
- ->SubElement("UniqueIdentifier")
- ->Text(MakeGuid(filter_path_str, kGuidSeedFilter));
- filter_path_str = FindParentDir(&(*it)).as_string();
- if (filter_path_str.empty())
- break;
- }
- cl_item->SubElement("Filter")->Text(filter_path);
- }
- }
- }
-
- project.Text(files_out.str());
-}
-
-bool VisualStudioWriter::WriteSolutionFile(const std::string& sln_name,
- Err* err) {
- std::string name = sln_name.empty() ? "all" : sln_name;
- SourceFile sln_file = build_settings_->build_dir().ResolveRelativeFile(
- Value(nullptr, name + ".sln"), err);
- if (sln_file.is_null())
- return false;
-
- base::FilePath sln_path = build_settings_->GetFullPath(sln_file);
-
- std::stringstream string_out;
- WriteSolutionFileContents(string_out, sln_path.DirName());
-
- // Only write the content to the file if it's different. That is
- // both a performance optimization and more importantly, prevents
- // Visual Studio from reloading the projects.
- return WriteFileIfChanged(sln_path, string_out.str(), err);
-}
-
-void VisualStudioWriter::WriteSolutionFileContents(
- std::ostream& out,
- const base::FilePath& solution_dir_path) {
- out << "Microsoft Visual Studio Solution File, Format Version 12.00"
- << std::endl;
- out << "# " << version_string_ << std::endl;
-
- SourceDir solution_dir(FilePathToUTF8(solution_dir_path));
- for (const std::unique_ptr<SolutionEntry>& folder : folders_) {
- out << "Project(\"" << kGuidTypeFolder << "\") = \"(" << folder->name
- << ")\", \"" << RebasePath(folder->path, solution_dir) << "\", \""
- << folder->guid << "\"" << std::endl;
- out << "EndProject" << std::endl;
- }
-
- for (const std::unique_ptr<SolutionProject>& project : projects_) {
- out << "Project(\"" << kGuidTypeProject << "\") = \"" << project->name
- << "\", \"" << RebasePath(project->path, solution_dir) << "\", \""
- << project->guid << "\"" << std::endl;
- out << "EndProject" << std::endl;
- }
-
- out << "Global" << std::endl;
-
- out << "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution"
- << std::endl;
- const std::string config_mode_prefix = std::string(kConfigurationName) + '|';
- const std::string config_mode = config_mode_prefix + config_platform_;
- out << "\t\t" << config_mode << " = " << config_mode << std::endl;
- out << "\tEndGlobalSection" << std::endl;
-
- out << "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"
- << std::endl;
- for (const std::unique_ptr<SolutionProject>& project : projects_) {
- const std::string project_config_mode =
- config_mode_prefix + project->config_platform;
- out << "\t\t" << project->guid << '.' << config_mode
- << ".ActiveCfg = " << project_config_mode << std::endl;
- out << "\t\t" << project->guid << '.' << config_mode
- << ".Build.0 = " << project_config_mode << std::endl;
- }
- out << "\tEndGlobalSection" << std::endl;
-
- out << "\tGlobalSection(SolutionProperties) = preSolution" << std::endl;
- out << "\t\tHideSolutionNode = FALSE" << std::endl;
- out << "\tEndGlobalSection" << std::endl;
-
- out << "\tGlobalSection(NestedProjects) = preSolution" << std::endl;
- for (const std::unique_ptr<SolutionEntry>& folder : folders_) {
- if (folder->parent_folder) {
- out << "\t\t" << folder->guid << " = " << folder->parent_folder->guid
- << std::endl;
- }
- }
- for (const std::unique_ptr<SolutionProject>& project : projects_) {
- out << "\t\t" << project->guid << " = " << project->parent_folder->guid
- << std::endl;
- }
- out << "\tEndGlobalSection" << std::endl;
-
- out << "EndGlobal" << std::endl;
-}
-
-void VisualStudioWriter::ResolveSolutionFolders() {
- root_folder_path_.clear();
-
- // Get all project directories. Create solution folder for each directory.
- std::map<base::StringPiece, SolutionEntry*> processed_paths;
- for (const std::unique_ptr<SolutionProject>& project : projects_) {
- base::StringPiece folder_path = project->label_dir_path;
- if (IsSlash(folder_path[folder_path.size() - 1]))
- folder_path = folder_path.substr(0, folder_path.size() - 1);
- auto it = processed_paths.find(folder_path);
- if (it != processed_paths.end()) {
- project->parent_folder = it->second;
- } else {
- std::string folder_path_str = folder_path.as_string();
- std::unique_ptr<SolutionEntry> folder = std::make_unique<SolutionEntry>(
- FindLastDirComponent(SourceDir(folder_path)).as_string(),
- folder_path_str, MakeGuid(folder_path_str, kGuidSeedFolder));
- project->parent_folder = folder.get();
- processed_paths[folder_path] = folder.get();
- folders_.push_back(std::move(folder));
-
- if (root_folder_path_.empty()) {
- root_folder_path_ = folder_path_str;
- } else {
- size_t common_prefix_len = 0;
- size_t max_common_length =
- std::min(root_folder_path_.size(), folder_path.size());
- size_t i;
- for (i = common_prefix_len; i < max_common_length; ++i) {
- if (IsSlash(root_folder_path_[i]) && IsSlash(folder_path[i]))
- common_prefix_len = i + 1;
- else if (root_folder_path_[i] != folder_path[i])
- break;
- }
- if (i == max_common_length &&
- (i == folder_path.size() || IsSlash(folder_path[i])))
- common_prefix_len = max_common_length;
- if (common_prefix_len < root_folder_path_.size()) {
- if (IsSlash(root_folder_path_[common_prefix_len - 1]))
- --common_prefix_len;
- root_folder_path_ = root_folder_path_.substr(0, common_prefix_len);
- }
- }
- }
- }
-
- // Create also all parent folders up to |root_folder_path_|.
- SolutionFolders additional_folders;
- for (const std::unique_ptr<SolutionEntry>& solution_folder : folders_) {
- if (solution_folder->path == root_folder_path_)
- continue;
-
- SolutionEntry* folder = solution_folder.get();
- base::StringPiece parent_path;
- while ((parent_path = FindParentDir(&folder->path)) != root_folder_path_) {
- auto it = processed_paths.find(parent_path);
- if (it != processed_paths.end()) {
- folder = it->second;
- } else {
- std::unique_ptr<SolutionEntry> new_folder =
- std::make_unique<SolutionEntry>(
- FindLastDirComponent(SourceDir(parent_path)).as_string(),
- parent_path.as_string(),
- MakeGuid(parent_path.as_string(), kGuidSeedFolder));
- processed_paths[parent_path] = new_folder.get();
- folder = new_folder.get();
- additional_folders.push_back(std::move(new_folder));
- }
- }
- }
- folders_.insert(folders_.end(),
- std::make_move_iterator(additional_folders.begin()),
- std::make_move_iterator(additional_folders.end()));
-
- // Sort folders by path.
- std::sort(folders_.begin(), folders_.end(),
- [](const std::unique_ptr<SolutionEntry>& a,
- const std::unique_ptr<SolutionEntry>& b) {
- return a->path < b->path;
- });
-
- // Match subfolders with their parents. Since |folders_| are sorted by path we
- // know that parent folder always precedes its children in vector.
- std::vector<SolutionEntry*> parents;
- for (const std::unique_ptr<SolutionEntry>& folder : folders_) {
- while (!parents.empty()) {
- if (base::StartsWith(folder->path, parents.back()->path,
- base::CompareCase::SENSITIVE)) {
- folder->parent_folder = parents.back();
- break;
- } else {
- parents.pop_back();
- }
- }
- parents.push_back(folder.get());
- }
-}
-
-std::string VisualStudioWriter::GetNinjaTarget(const Target* target) {
- std::ostringstream ninja_target_out;
- DCHECK(!target->dependency_output_file().value().empty());
- ninja_path_output_.WriteFile(ninja_target_out,
- target->dependency_output_file());
- return ninja_target_out.str();
-}
diff --git a/chromium/tools/gn/visual_studio_writer.h b/chromium/tools/gn/visual_studio_writer.h
deleted file mode 100644
index d9bb8839100..00000000000
--- a/chromium/tools/gn/visual_studio_writer.h
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_VISUAL_STUDIO_WRITER_H_
-#define TOOLS_GN_VISUAL_STUDIO_WRITER_H_
-
-#include <iosfwd>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "tools/gn/path_output.h"
-
-namespace base {
-class FilePath;
-}
-
-class Builder;
-class BuildSettings;
-class Err;
-class SourceFile;
-class Target;
-
-class VisualStudioWriter {
- public:
- enum Version {
- Vs2013 = 1, // Visual Studio 2013
- Vs2015, // Visual Studio 2015
- Vs2017 // Visual Studio 2017
- };
-
- // Writes Visual Studio project and solution files. |sln_name| is the optional
- // solution file name ("all" is used if not specified). |filters| is optional
- // semicolon-separated list of label patterns used to limit the set of
- // generated projects. Only matching targets and their dependencies (unless
- // |no_deps| is true) will be included to the solution. On failure will
- // populate |err| and will return false. |win_sdk| is the Windows SDK version
- // which will be used by Visual Studio IntelliSense.
- static bool RunAndWriteFiles(const BuildSettings* build_settings,
- const Builder& builder,
- Version version,
- const std::string& sln_name,
- const std::string& filters,
- const std::string& win_sdk,
- const std::string& ninja_extra_args,
- bool no_deps,
- Err* err);
-
- private:
- FRIEND_TEST_ALL_PREFIXES(VisualStudioWriterTest, ResolveSolutionFolders);
- FRIEND_TEST_ALL_PREFIXES(VisualStudioWriterTest,
- ResolveSolutionFolders_AbsPath);
-
- // Solution project or folder.
- struct SolutionEntry {
- SolutionEntry(const std::string& name,
- const std::string& path,
- const std::string& guid);
- virtual ~SolutionEntry();
-
- // Entry name. For projects must be unique in the solution.
- std::string name;
- // Absolute project file or folder directory path.
- std::string path;
- // GUID-like string.
- std::string guid;
- // Pointer to parent folder. nullptr if entry has no parent.
- SolutionEntry* parent_folder;
- };
-
- struct SolutionProject : public SolutionEntry {
- SolutionProject(const std::string& name,
- const std::string& path,
- const std::string& guid,
- const std::string& label_dir_path,
- const std::string& config_platform);
- ~SolutionProject() override;
-
- // Absolute label dir path.
- std::string label_dir_path;
- // Configuration platform. May be different than solution config platform.
- std::string config_platform;
- };
-
- struct SourceFileCompileTypePair {
- SourceFileCompileTypePair(const SourceFile* file, const char* compile_type);
- ~SourceFileCompileTypePair();
-
- // Source file.
- const SourceFile* file;
- // Compile type string.
- const char* compile_type;
- };
-
- using SolutionProjects = std::vector<std::unique_ptr<SolutionProject>>;
- using SolutionFolders = std::vector<std::unique_ptr<SolutionEntry>>;
- using SourceFileCompileTypePairs = std::vector<SourceFileCompileTypePair>;
-
- VisualStudioWriter(const BuildSettings* build_settings,
- const char* config_platform,
- Version version,
- const std::string& win_kit);
- ~VisualStudioWriter();
-
- bool WriteProjectFiles(const Target* target,
- const std::string& ninja_extra_args,
- Err* err);
- bool WriteProjectFileContents(std::ostream& out,
- const SolutionProject& solution_project,
- const Target* target,
- const std::string& ninja_extra_args,
- SourceFileCompileTypePairs* source_types,
- Err* err);
- void WriteFiltersFileContents(std::ostream& out,
- const Target* target,
- const SourceFileCompileTypePairs& source_types);
- bool WriteSolutionFile(const std::string& sln_name, Err* err);
- void WriteSolutionFileContents(std::ostream& out,
- const base::FilePath& solution_dir_path);
-
- // Resolves all solution folders (parent folders for projects) into |folders_|
- // and updates |root_folder_dir_|. Also sets |parent_folder| for |projects_|.
- void ResolveSolutionFolders();
-
- std::string GetNinjaTarget(const Target* target);
-
- const BuildSettings* build_settings_;
-
- // Toolset version.
- const char* toolset_version_;
-
- // Project version.
- const char* project_version_;
-
- // Visual Studio version string.
- const char* version_string_;
-
- // Platform for solution configuration (Win32, x64). Some projects may be
- // configured for different platform.
- const char* config_platform_;
-
- // All projects contained by solution.
- SolutionProjects projects_;
-
- // Absolute root solution folder path.
- std::string root_folder_path_;
-
- // Folders for all solution projects.
- SolutionFolders folders_;
-
- // Semicolon-separated Windows SDK include directories.
- std::string windows_kits_include_dirs_;
-
- // Path formatter for ninja targets.
- PathOutput ninja_path_output_;
-
- // Windows 10 SDK version string (e.g. 10.0.14393.0)
- std::string windows_sdk_version_;
-
- DISALLOW_COPY_AND_ASSIGN(VisualStudioWriter);
-};
-
-#endif // TOOLS_GN_VISUAL_STUDIO_WRITER_H_
diff --git a/chromium/tools/gn/visual_studio_writer_unittest.cc b/chromium/tools/gn/visual_studio_writer_unittest.cc
deleted file mode 100644
index bd9ab961616..00000000000
--- a/chromium/tools/gn/visual_studio_writer_unittest.cc
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/visual_studio_writer.h"
-
-#include <memory>
-
-#include "base/strings/string_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/test_with_scope.h"
-#include "tools/gn/visual_studio_utils.h"
-
-namespace {
-
-class VisualStudioWriterTest : public testing::Test {
- protected:
- TestWithScope setup_;
-};
-
-std::string MakeTestPath(const std::string& path) {
-#if defined(OS_WIN)
- return "C:" + path;
-#else
- return path;
-#endif
-}
-
-} // namespace
-
-TEST_F(VisualStudioWriterTest, ResolveSolutionFolders) {
- VisualStudioWriter writer(setup_.build_settings(), "Win32",
- VisualStudioWriter::Version::Vs2015,
- "10.0.17134.0");
-
- std::string path =
- MakeTestPath("/foo/chromium/src/out/Debug/obj/base/base.vcxproj");
- writer.projects_.push_back(
- std::make_unique<VisualStudioWriter::SolutionProject>(
- "base", path, MakeGuid(path, "project"),
- MakeTestPath("/foo/chromium/src/base"), "Win32"));
-
- path = MakeTestPath("/foo/chromium/src/out/Debug/obj/tools/gn/gn.vcxproj");
- writer.projects_.push_back(
- std::make_unique<VisualStudioWriter::SolutionProject>(
- "gn", path, MakeGuid(path, "project"),
- MakeTestPath("/foo/chromium/src/tools/gn"), "Win32"));
-
- path = MakeTestPath("/foo/chromium/src/out/Debug/obj/chrome/chrome.vcxproj");
- writer.projects_.push_back(
- std::make_unique<VisualStudioWriter::SolutionProject>(
- "chrome", path, MakeGuid(path, "project"),
- MakeTestPath("/foo/chromium/src/chrome"), "Win32"));
-
- path = MakeTestPath("/foo/chromium/src/out/Debug/obj/base/bar.vcxproj");
- writer.projects_.push_back(
- std::make_unique<VisualStudioWriter::SolutionProject>(
- "bar", path, MakeGuid(path, "project"),
- MakeTestPath("/foo/chromium/src/base"), "Win32"));
-
- writer.ResolveSolutionFolders();
-
- ASSERT_EQ(MakeTestPath("/foo/chromium/src"), writer.root_folder_path_);
-
- ASSERT_EQ(4u, writer.folders_.size());
-
- ASSERT_EQ("base", writer.folders_[0]->name);
- ASSERT_EQ(MakeTestPath("/foo/chromium/src/base"), writer.folders_[0]->path);
- ASSERT_EQ(nullptr, writer.folders_[0]->parent_folder);
-
- ASSERT_EQ("chrome", writer.folders_[1]->name);
- ASSERT_EQ(MakeTestPath("/foo/chromium/src/chrome"), writer.folders_[1]->path);
- ASSERT_EQ(nullptr, writer.folders_[1]->parent_folder);
-
- ASSERT_EQ("tools", writer.folders_[2]->name);
- ASSERT_EQ(MakeTestPath("/foo/chromium/src/tools"), writer.folders_[2]->path);
- ASSERT_EQ(nullptr, writer.folders_[2]->parent_folder);
-
- ASSERT_EQ("gn", writer.folders_[3]->name);
- ASSERT_EQ(MakeTestPath("/foo/chromium/src/tools/gn"),
- writer.folders_[3]->path);
- ASSERT_EQ(writer.folders_[2].get(), writer.folders_[3]->parent_folder);
-
- ASSERT_EQ(writer.folders_[0].get(), writer.projects_[0]->parent_folder);
- ASSERT_EQ(writer.folders_[3].get(), writer.projects_[1]->parent_folder);
- ASSERT_EQ(writer.folders_[1].get(), writer.projects_[2]->parent_folder);
- ASSERT_EQ(writer.folders_[0].get(), writer.projects_[3]->parent_folder);
-}
-
-TEST_F(VisualStudioWriterTest, ResolveSolutionFolders_AbsPath) {
- VisualStudioWriter writer(setup_.build_settings(), "Win32",
- VisualStudioWriter::Version::Vs2015,
- "10.0.17134.0");
-
- std::string path =
- MakeTestPath("/foo/chromium/src/out/Debug/obj/base/base.vcxproj");
- writer.projects_.push_back(
- std::make_unique<VisualStudioWriter::SolutionProject>(
- "base", path, MakeGuid(path, "project"),
- MakeTestPath("/foo/chromium/src/base"), "Win32"));
-
- path = MakeTestPath("/foo/chromium/src/out/Debug/obj/tools/gn/gn.vcxproj");
- writer.projects_.push_back(
- std::make_unique<VisualStudioWriter::SolutionProject>(
- "gn", path, MakeGuid(path, "project"),
- MakeTestPath("/foo/chromium/src/tools/gn"), "Win32"));
-
- path = MakeTestPath(
- "/foo/chromium/src/out/Debug/obj/ABS_PATH/C/foo/bar/bar.vcxproj");
- writer.projects_.push_back(
- std::make_unique<VisualStudioWriter::SolutionProject>(
- "bar", path, MakeGuid(path, "project"), MakeTestPath("/foo/bar"),
- "Win32"));
-
- std::string baz_label_dir_path = MakeTestPath("/foo/bar/baz");
-#if defined(OS_WIN)
- // Make sure mixed lower and upper-case drive letters are handled properly.
- baz_label_dir_path[0] = base::ToLowerASCII(baz_label_dir_path[0]);
-#endif
- path = MakeTestPath(
- "/foo/chromium/src/out/Debug/obj/ABS_PATH/C/foo/bar/baz/baz.vcxproj");
- writer.projects_.push_back(
- std::make_unique<VisualStudioWriter::SolutionProject>(
- "baz", path, MakeGuid(path, "project"), baz_label_dir_path, "Win32"));
-
- writer.ResolveSolutionFolders();
-
- ASSERT_EQ(MakeTestPath("/foo"), writer.root_folder_path_);
-
- ASSERT_EQ(7u, writer.folders_.size());
-
- ASSERT_EQ("bar", writer.folders_[0]->name);
- ASSERT_EQ(MakeTestPath("/foo/bar"), writer.folders_[0]->path);
- ASSERT_EQ(nullptr, writer.folders_[0]->parent_folder);
-
- ASSERT_EQ("baz", writer.folders_[1]->name);
- ASSERT_EQ(MakeTestPath("/foo/bar/baz"), writer.folders_[1]->path);
- ASSERT_EQ(writer.folders_[0].get(), writer.folders_[1]->parent_folder);
-
- ASSERT_EQ("chromium", writer.folders_[2]->name);
- ASSERT_EQ(MakeTestPath("/foo/chromium"), writer.folders_[2]->path);
- ASSERT_EQ(nullptr, writer.folders_[2]->parent_folder);
-
- ASSERT_EQ("src", writer.folders_[3]->name);
- ASSERT_EQ(MakeTestPath("/foo/chromium/src"), writer.folders_[3]->path);
- ASSERT_EQ(writer.folders_[2].get(), writer.folders_[3]->parent_folder);
-
- ASSERT_EQ("base", writer.folders_[4]->name);
- ASSERT_EQ(MakeTestPath("/foo/chromium/src/base"), writer.folders_[4]->path);
- ASSERT_EQ(writer.folders_[3].get(), writer.folders_[4]->parent_folder);
-
- ASSERT_EQ("tools", writer.folders_[5]->name);
- ASSERT_EQ(MakeTestPath("/foo/chromium/src/tools"), writer.folders_[5]->path);
- ASSERT_EQ(writer.folders_[3].get(), writer.folders_[5]->parent_folder);
-
- ASSERT_EQ("gn", writer.folders_[6]->name);
- ASSERT_EQ(MakeTestPath("/foo/chromium/src/tools/gn"),
- writer.folders_[6]->path);
- ASSERT_EQ(writer.folders_[5].get(), writer.folders_[6]->parent_folder);
-
- ASSERT_EQ(writer.folders_[4].get(), writer.projects_[0]->parent_folder);
- ASSERT_EQ(writer.folders_[6].get(), writer.projects_[1]->parent_folder);
- ASSERT_EQ(writer.folders_[0].get(), writer.projects_[2]->parent_folder);
- ASSERT_EQ(writer.folders_[1].get(), writer.projects_[3]->parent_folder);
-}
diff --git a/chromium/tools/gn/xcode_object.cc b/chromium/tools/gn/xcode_object.cc
deleted file mode 100644
index bd5c440b984..00000000000
--- a/chromium/tools/gn/xcode_object.cc
+++ /dev/null
@@ -1,990 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/xcode_object.h"
-
-#include <iomanip>
-#include <memory>
-#include <sstream>
-#include <utility>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/string_util.h"
-#include "tools/gn/filesystem_utils.h"
-
-// Helper methods -------------------------------------------------------------
-
-namespace {
-struct IndentRules {
- bool one_line;
- unsigned level;
-};
-
-std::vector<std::unique_ptr<PBXObject>> EmptyPBXObjectVector() {
- return std::vector<std::unique_ptr<PBXObject>>();
-}
-
-bool CharNeedEscaping(char c) {
- if (base::IsAsciiAlpha(c) || base::IsAsciiDigit(c))
- return false;
- if (c == '$' || c == '.' || c == '/' || c == '_')
- return false;
- return true;
-}
-
-bool StringNeedEscaping(const std::string& string) {
- if (string.empty())
- return true;
- if (string.find("___") != std::string::npos)
- return true;
-
- for (char c : string) {
- if (CharNeedEscaping(c))
- return true;
- }
- return false;
-}
-
-std::string EncodeString(const std::string& string) {
- if (!StringNeedEscaping(string))
- return string;
-
- std::stringstream buffer;
- buffer << '"';
- for (char c : string) {
- if (c <= 31) {
- switch (c) {
- case '\a':
- buffer << "\\a";
- break;
- case '\b':
- buffer << "\\b";
- break;
- case '\t':
- buffer << "\\t";
- break;
- case '\n':
- case '\r':
- buffer << "\\n";
- break;
- case '\v':
- buffer << "\\v";
- break;
- case '\f':
- buffer << "\\f";
- break;
- default:
- buffer << std::hex << std::setw(4) << std::left << "\\U"
- << static_cast<unsigned>(c);
- break;
- }
- } else {
- if (c == '"' || c == '\\')
- buffer << '\\';
- buffer << c;
- }
- }
- buffer << '"';
- return buffer.str();
-}
-
-struct SourceTypeForExt {
- const char* ext;
- const char* source_type;
-};
-
-const SourceTypeForExt kSourceTypeForExt[] = {
- {"a", "archive.ar"},
- {"app", "wrapper.application"},
- {"appex", "wrapper.app-extension"},
- {"bdic", "file"},
- {"bundle", "wrapper.cfbundle"},
- {"c", "sourcecode.c.c"},
- {"cc", "sourcecode.cpp.cpp"},
- {"cpp", "sourcecode.cpp.cpp"},
- {"css", "text.css"},
- {"cxx", "sourcecode.cpp.cpp"},
- {"dart", "sourcecode"},
- {"dylib", "compiled.mach-o.dylib"},
- {"framework", "wrapper.framework"},
- {"h", "sourcecode.c.h"},
- {"hxx", "sourcecode.cpp.h"},
- {"icns", "image.icns"},
- {"java", "sourcecode.java"},
- {"js", "sourcecode.javascript"},
- {"kext", "wrapper.kext"},
- {"m", "sourcecode.c.objc"},
- {"mm", "sourcecode.cpp.objcpp"},
- {"nib", "wrapper.nib"},
- {"o", "compiled.mach-o.objfile"},
- {"pdf", "image.pdf"},
- {"pl", "text.script.perl"},
- {"plist", "text.plist.xml"},
- {"pm", "text.script.perl"},
- {"png", "image.png"},
- {"py", "text.script.python"},
- {"r", "sourcecode.rez"},
- {"rez", "sourcecode.rez"},
- {"s", "sourcecode.asm"},
- {"storyboard", "file.storyboard"},
- {"strings", "text.plist.strings"},
- {"swift", "sourcecode.swift"},
- {"ttf", "file"},
- {"xcassets", "folder.assetcatalog"},
- {"xcconfig", "text.xcconfig"},
- {"xcdatamodel", "wrapper.xcdatamodel"},
- {"xcdatamodeld", "wrapper.xcdatamodeld"},
- {"xib", "file.xib"},
- {"y", "sourcecode.yacc"},
-};
-
-const char* GetSourceType(const base::StringPiece& ext) {
- for (size_t i = 0; i < arraysize(kSourceTypeForExt); ++i) {
- if (kSourceTypeForExt[i].ext == ext)
- return kSourceTypeForExt[i].source_type;
- }
-
- return "text";
-}
-
-bool HasExplicitFileType(const base::StringPiece& ext) {
- return ext == "dart";
-}
-
-bool IsSourceFileForIndexing(const base::StringPiece& ext) {
- return ext == "c" || ext == "cc" || ext == "cpp" || ext == "cxx" ||
- ext == "m" || ext == "mm";
-}
-
-void PrintValue(std::ostream& out, IndentRules rules, unsigned value) {
- out << value;
-}
-
-void PrintValue(std::ostream& out, IndentRules rules, const char* value) {
- out << EncodeString(value);
-}
-
-void PrintValue(std::ostream& out,
- IndentRules rules,
- const std::string& value) {
- out << EncodeString(value);
-}
-
-void PrintValue(std::ostream& out, IndentRules rules, const PBXObject* value) {
- out << value->Reference();
-}
-
-template <typename ObjectClass>
-void PrintValue(std::ostream& out,
- IndentRules rules,
- const std::unique_ptr<ObjectClass>& value) {
- PrintValue(out, rules, value.get());
-}
-
-template <typename ValueType>
-void PrintValue(std::ostream& out,
- IndentRules rules,
- const std::vector<ValueType>& values) {
- IndentRules sub_rule{rules.one_line, rules.level + 1};
- out << "(" << (rules.one_line ? " " : "\n");
- for (const auto& value : values) {
- if (!sub_rule.one_line)
- out << std::string(sub_rule.level, '\t');
-
- PrintValue(out, sub_rule, value);
- out << "," << (rules.one_line ? " " : "\n");
- }
-
- if (!rules.one_line && rules.level)
- out << std::string(rules.level, '\t');
- out << ")";
-}
-
-template <typename ValueType>
-void PrintValue(std::ostream& out,
- IndentRules rules,
- const std::map<std::string, ValueType>& values) {
- IndentRules sub_rule{rules.one_line, rules.level + 1};
- out << "{" << (rules.one_line ? " " : "\n");
- for (const auto& pair : values) {
- if (!sub_rule.one_line)
- out << std::string(sub_rule.level, '\t');
-
- out << pair.first << " = ";
- PrintValue(out, sub_rule, pair.second);
- out << ";" << (rules.one_line ? " " : "\n");
- }
-
- if (!rules.one_line && rules.level)
- out << std::string(rules.level, '\t');
- out << "}";
-}
-
-template <typename ValueType>
-void PrintProperty(std::ostream& out,
- IndentRules rules,
- const char* name,
- ValueType&& value) {
- if (!rules.one_line && rules.level)
- out << std::string(rules.level, '\t');
-
- out << name << " = ";
- PrintValue(out, rules, std::forward<ValueType>(value));
- out << ";" << (rules.one_line ? " " : "\n");
-}
-} // namespace
-
-// PBXObjectClass -------------------------------------------------------------
-
-const char* ToString(PBXObjectClass cls) {
- switch (cls) {
- case PBXAggregateTargetClass:
- return "PBXAggregateTarget";
- case PBXBuildFileClass:
- return "PBXBuildFile";
- case PBXContainerItemProxyClass:
- return "PBXContainerItemProxy";
- case PBXFileReferenceClass:
- return "PBXFileReference";
- case PBXFrameworksBuildPhaseClass:
- return "PBXFrameworksBuildPhase";
- case PBXGroupClass:
- return "PBXGroup";
- case PBXNativeTargetClass:
- return "PBXNativeTarget";
- case PBXProjectClass:
- return "PBXProject";
- case PBXShellScriptBuildPhaseClass:
- return "PBXShellScriptBuildPhase";
- case PBXSourcesBuildPhaseClass:
- return "PBXSourcesBuildPhase";
- case PBXTargetDependencyClass:
- return "PBXTargetDependency";
- case XCBuildConfigurationClass:
- return "XCBuildConfiguration";
- case XCConfigurationListClass:
- return "XCConfigurationList";
- }
- NOTREACHED();
- return nullptr;
-}
-
-// PBXObjectVisitor -----------------------------------------------------------
-
-PBXObjectVisitor::PBXObjectVisitor() = default;
-
-PBXObjectVisitor::~PBXObjectVisitor() = default;
-
-// PBXObject ------------------------------------------------------------------
-
-PBXObject::PBXObject() = default;
-
-PBXObject::~PBXObject() = default;
-
-void PBXObject::SetId(const std::string& id) {
- DCHECK(id_.empty());
- DCHECK(!id.empty());
- id_.assign(id);
-}
-
-std::string PBXObject::Reference() const {
- std::string comment = Comment();
- if (comment.empty())
- return id_;
-
- return id_ + " /* " + comment + " */";
-}
-
-std::string PBXObject::Comment() const {
- return Name();
-}
-
-void PBXObject::Visit(PBXObjectVisitor& visitor) {
- visitor.Visit(this);
-}
-
-// PBXBuildPhase --------------------------------------------------------------
-
-PBXBuildPhase::PBXBuildPhase() = default;
-
-PBXBuildPhase::~PBXBuildPhase() = default;
-
-// PBXTarget ------------------------------------------------------------------
-
-PBXTarget::PBXTarget(const std::string& name,
- const std::string& shell_script,
- const std::string& config_name,
- const PBXAttributes& attributes)
- : configurations_(new XCConfigurationList(config_name, attributes, this)),
- name_(name) {
- if (!shell_script.empty()) {
- build_phases_.push_back(
- std::make_unique<PBXShellScriptBuildPhase>(name, shell_script));
- }
-}
-
-PBXTarget::~PBXTarget() = default;
-
-void PBXTarget::AddDependency(std::unique_ptr<PBXTargetDependency> dependency) {
- DCHECK(dependency);
- dependencies_.push_back(std::move(dependency));
-}
-
-std::string PBXTarget::Name() const {
- return name_;
-}
-
-void PBXTarget::Visit(PBXObjectVisitor& visitor) {
- PBXObject::Visit(visitor);
- configurations_->Visit(visitor);
- for (const auto& dependency : dependencies_)
- dependency->Visit(visitor);
- for (const auto& build_phase : build_phases_)
- build_phase->Visit(visitor);
-}
-
-// PBXAggregateTarget ---------------------------------------------------------
-
-PBXAggregateTarget::PBXAggregateTarget(const std::string& name,
- const std::string& shell_script,
- const std::string& config_name,
- const PBXAttributes& attributes)
- : PBXTarget(name, shell_script, config_name, attributes) {}
-
-PBXAggregateTarget::~PBXAggregateTarget() = default;
-
-PBXObjectClass PBXAggregateTarget::Class() const {
- return PBXAggregateTargetClass;
-}
-
-void PBXAggregateTarget::Print(std::ostream& out, unsigned indent) const {
- const std::string indent_str(indent, '\t');
- const IndentRules rules = {false, indent + 1};
- out << indent_str << Reference() << " = {\n";
- PrintProperty(out, rules, "isa", ToString(Class()));
- PrintProperty(out, rules, "buildConfigurationList", configurations_);
- PrintProperty(out, rules, "buildPhases", build_phases_);
- PrintProperty(out, rules, "dependencies", EmptyPBXObjectVector());
- PrintProperty(out, rules, "name", name_);
- PrintProperty(out, rules, "productName", name_);
- out << indent_str << "};\n";
-}
-
-// PBXBuildFile ---------------------------------------------------------------
-
-PBXBuildFile::PBXBuildFile(const PBXFileReference* file_reference,
- const PBXSourcesBuildPhase* build_phase,
- const CompilerFlags compiler_flag)
- : file_reference_(file_reference),
- build_phase_(build_phase),
- compiler_flag_(compiler_flag) {
- DCHECK(file_reference_);
- DCHECK(build_phase_);
-}
-
-PBXBuildFile::~PBXBuildFile() = default;
-
-PBXObjectClass PBXBuildFile::Class() const {
- return PBXBuildFileClass;
-}
-
-std::string PBXBuildFile::Name() const {
- return file_reference_->Name() + " in " + build_phase_->Name();
-}
-
-void PBXBuildFile::Print(std::ostream& out, unsigned indent) const {
- const std::string indent_str(indent, '\t');
- const IndentRules rules = {true, 0};
- out << indent_str << Reference() << " = {";
- PrintProperty(out, rules, "isa", ToString(Class()));
- PrintProperty(out, rules, "fileRef", file_reference_);
- if (compiler_flag_ == CompilerFlags::HELP) {
- std::map<std::string, std::string> settings = {
- {"COMPILER_FLAGS", "--help"},
- };
- PrintProperty(out, rules, "settings", settings);
- }
- out << "};\n";
-}
-
-// PBXContainerItemProxy ------------------------------------------------------
-PBXContainerItemProxy::PBXContainerItemProxy(const PBXProject* project,
- const PBXTarget* target)
- : project_(project), target_(target) {}
-
-PBXContainerItemProxy::~PBXContainerItemProxy() = default;
-
-PBXObjectClass PBXContainerItemProxy::Class() const {
- return PBXContainerItemProxyClass;
-}
-
-void PBXContainerItemProxy::Visit(PBXObjectVisitor& visitor) {
- PBXObject::Visit(visitor);
-}
-
-std::string PBXContainerItemProxy::Name() const {
- return "PBXContainerItemProxy";
-}
-
-void PBXContainerItemProxy::Print(std::ostream& out, unsigned indent) const {
- const std::string indent_str(indent, '\t');
- const IndentRules rules = {true, 0};
- out << indent_str << Reference() << " = {";
- PrintProperty(out, rules, "isa", ToString(Class()));
- PrintProperty(out, rules, "containerPortal", project_);
- PrintProperty(out, rules, "proxyType", 1u);
- PrintProperty(out, rules, "remoteGlobalIDString", target_);
- PrintProperty(out, rules, "remoteInfo", target_->Name());
- out << indent_str << "};\n";
-}
-
-// PBXFileReference -----------------------------------------------------------
-
-PBXFileReference::PBXFileReference(const std::string& name,
- const std::string& path,
- const std::string& type)
- : name_(name), path_(path), type_(type) {}
-
-PBXFileReference::~PBXFileReference() = default;
-
-PBXObjectClass PBXFileReference::Class() const {
- return PBXFileReferenceClass;
-}
-
-std::string PBXFileReference::Name() const {
- return name_;
-}
-
-void PBXFileReference::Print(std::ostream& out, unsigned indent) const {
- const std::string indent_str(indent, '\t');
- const IndentRules rules = {true, 0};
- out << indent_str << Reference() << " = {";
- PrintProperty(out, rules, "isa", ToString(Class()));
-
- if (!type_.empty()) {
- PrintProperty(out, rules, "explicitFileType", type_);
- PrintProperty(out, rules, "includeInIndex", 0u);
- } else {
- base::StringPiece ext = FindExtension(&name_);
- if (HasExplicitFileType(ext))
- PrintProperty(out, rules, "explicitFileType", GetSourceType(ext));
- else
- PrintProperty(out, rules, "lastKnownFileType", GetSourceType(ext));
- }
-
- if (!name_.empty())
- PrintProperty(out, rules, "name", name_);
-
- DCHECK(!path_.empty());
- PrintProperty(out, rules, "path", path_);
- PrintProperty(out, rules, "sourceTree",
- type_.empty() ? "<group>" : "BUILT_PRODUCTS_DIR");
- out << "};\n";
-}
-
-// PBXFrameworksBuildPhase ----------------------------------------------------
-
-PBXFrameworksBuildPhase::PBXFrameworksBuildPhase() = default;
-
-PBXFrameworksBuildPhase::~PBXFrameworksBuildPhase() = default;
-
-PBXObjectClass PBXFrameworksBuildPhase::Class() const {
- return PBXFrameworksBuildPhaseClass;
-}
-
-std::string PBXFrameworksBuildPhase::Name() const {
- return "Frameworks";
-}
-
-void PBXFrameworksBuildPhase::Print(std::ostream& out, unsigned indent) const {
- const std::string indent_str(indent, '\t');
- const IndentRules rules = {false, indent + 1};
- out << indent_str << Reference() << " = {\n";
- PrintProperty(out, rules, "isa", ToString(Class()));
- PrintProperty(out, rules, "buildActionMask", 0x7fffffffu);
- PrintProperty(out, rules, "files", EmptyPBXObjectVector());
- PrintProperty(out, rules, "runOnlyForDeploymentPostprocessing", 0u);
- out << indent_str << "};\n";
-}
-
-// PBXGroup -------------------------------------------------------------------
-
-PBXGroup::PBXGroup(const std::string& path, const std::string& name)
- : name_(name), path_(path) {}
-
-PBXGroup::~PBXGroup() = default;
-
-PBXObject* PBXGroup::AddChild(std::unique_ptr<PBXObject> child) {
- DCHECK(child);
- children_.push_back(std::move(child));
- return children_.back().get();
-}
-
-PBXFileReference* PBXGroup::AddSourceFile(const std::string& navigator_path,
- const std::string& source_path) {
- DCHECK(!navigator_path.empty());
- DCHECK(!source_path.empty());
- std::string::size_type sep = navigator_path.find("/");
- if (sep == std::string::npos) {
- // Prevent same file reference being created and added multiple times.
- for (const auto& child : children_) {
- if (child->Class() != PBXFileReferenceClass)
- continue;
-
- PBXFileReference* child_as_file_reference =
- static_cast<PBXFileReference*>(child.get());
- if (child_as_file_reference->Name() == navigator_path &&
- child_as_file_reference->path() == source_path) {
- return child_as_file_reference;
- }
- }
-
- children_.push_back(std::make_unique<PBXFileReference>(
- navigator_path, source_path, std::string()));
- return static_cast<PBXFileReference*>(children_.back().get());
- }
-
- PBXGroup* group = nullptr;
- base::StringPiece component(navigator_path.data(), sep);
- for (const auto& child : children_) {
- if (child->Class() != PBXGroupClass)
- continue;
-
- PBXGroup* child_as_group = static_cast<PBXGroup*>(child.get());
- if (child_as_group->name_ == component) {
- group = child_as_group;
- break;
- }
- }
-
- if (!group) {
- children_.push_back(std::make_unique<PBXGroup>(component.as_string(),
- component.as_string()));
- group = static_cast<PBXGroup*>(children_.back().get());
- }
-
- DCHECK(group);
- DCHECK(group->name_ == component);
- return group->AddSourceFile(navigator_path.substr(sep + 1), source_path);
-}
-
-PBXObjectClass PBXGroup::Class() const {
- return PBXGroupClass;
-}
-
-std::string PBXGroup::Name() const {
- if (!name_.empty())
- return name_;
- if (!path_.empty())
- return path_;
- return std::string();
-}
-
-void PBXGroup::Visit(PBXObjectVisitor& visitor) {
- PBXObject::Visit(visitor);
- for (const auto& child : children_) {
- child->Visit(visitor);
- }
-}
-
-void PBXGroup::Print(std::ostream& out, unsigned indent) const {
- const std::string indent_str(indent, '\t');
- const IndentRules rules = {false, indent + 1};
- out << indent_str << Reference() << " = {\n";
- PrintProperty(out, rules, "isa", ToString(Class()));
- PrintProperty(out, rules, "children", children_);
- if (!name_.empty())
- PrintProperty(out, rules, "name", name_);
- if (is_source_ && !path_.empty())
- PrintProperty(out, rules, "path", path_);
- PrintProperty(out, rules, "sourceTree", "<group>");
- out << indent_str << "};\n";
-}
-
-// PBXNativeTarget ------------------------------------------------------------
-
-PBXNativeTarget::PBXNativeTarget(const std::string& name,
- const std::string& shell_script,
- const std::string& config_name,
- const PBXAttributes& attributes,
- const std::string& product_type,
- const std::string& product_name,
- const PBXFileReference* product_reference)
- : PBXTarget(name, shell_script, config_name, attributes),
- product_reference_(product_reference),
- product_type_(product_type),
- product_name_(product_name) {
- DCHECK(product_reference_);
- build_phases_.push_back(std::make_unique<PBXSourcesBuildPhase>());
- source_build_phase_ =
- static_cast<PBXSourcesBuildPhase*>(build_phases_.back().get());
-
- build_phases_.push_back(std::make_unique<PBXFrameworksBuildPhase>());
-}
-
-PBXNativeTarget::~PBXNativeTarget() = default;
-
-void PBXNativeTarget::AddFileForIndexing(const PBXFileReference* file_reference,
- const CompilerFlags compiler_flag) {
- DCHECK(file_reference);
- source_build_phase_->AddBuildFile(std::make_unique<PBXBuildFile>(
- file_reference, source_build_phase_, compiler_flag));
-}
-
-PBXObjectClass PBXNativeTarget::Class() const {
- return PBXNativeTargetClass;
-}
-
-void PBXNativeTarget::Print(std::ostream& out, unsigned indent) const {
- const std::string indent_str(indent, '\t');
- const IndentRules rules = {false, indent + 1};
- out << indent_str << Reference() << " = {\n";
- PrintProperty(out, rules, "isa", ToString(Class()));
- PrintProperty(out, rules, "buildConfigurationList", configurations_);
- PrintProperty(out, rules, "buildPhases", build_phases_);
- PrintProperty(out, rules, "buildRules", EmptyPBXObjectVector());
- PrintProperty(out, rules, "dependencies", dependencies_);
- PrintProperty(out, rules, "name", name_);
- PrintProperty(out, rules, "productName", product_name_);
- PrintProperty(out, rules, "productReference", product_reference_);
- PrintProperty(out, rules, "productType", product_type_);
- out << indent_str << "};\n";
-}
-
-// PBXProject -----------------------------------------------------------------
-
-PBXProject::PBXProject(const std::string& name,
- const std::string& config_name,
- const std::string& source_path,
- const PBXAttributes& attributes)
- : name_(name), config_name_(config_name), target_for_indexing_(nullptr) {
- attributes_["BuildIndependentTargetsInParallel"] = "YES";
-
- main_group_.reset(new PBXGroup);
- sources_ = static_cast<PBXGroup*>(
- main_group_->AddChild(std::make_unique<PBXGroup>(source_path, "Source")));
- sources_->set_is_source(true);
- products_ = static_cast<PBXGroup*>(main_group_->AddChild(
- std::make_unique<PBXGroup>(std::string(), "Product")));
- main_group_->AddChild(std::make_unique<PBXGroup>(std::string(), "Build"));
-
- configurations_.reset(new XCConfigurationList(config_name, attributes, this));
-}
-
-PBXProject::~PBXProject() = default;
-
-void PBXProject::AddSourceFileToIndexingTarget(
- const std::string& navigator_path,
- const std::string& source_path,
- const CompilerFlags compiler_flag) {
- if (!target_for_indexing_) {
- AddIndexingTarget();
- }
- AddSourceFile(navigator_path, source_path, compiler_flag,
- target_for_indexing_);
-}
-
-void PBXProject::AddSourceFile(const std::string& navigator_path,
- const std::string& source_path,
- const CompilerFlags compiler_flag,
- PBXNativeTarget* target) {
- PBXFileReference* file_reference =
- sources_->AddSourceFile(navigator_path, source_path);
- base::StringPiece ext = FindExtension(&source_path);
- if (!IsSourceFileForIndexing(ext))
- return;
-
- DCHECK(target);
- target->AddFileForIndexing(file_reference, compiler_flag);
-}
-
-void PBXProject::AddAggregateTarget(const std::string& name,
- const std::string& shell_script) {
- PBXAttributes attributes;
- attributes["CODE_SIGNING_REQUIRED"] = "NO";
- attributes["CONFIGURATION_BUILD_DIR"] = ".";
- attributes["PRODUCT_NAME"] = name;
-
- targets_.push_back(std::make_unique<PBXAggregateTarget>(
- name, shell_script, config_name_, attributes));
-}
-
-void PBXProject::AddIndexingTarget() {
- DCHECK(!target_for_indexing_);
- PBXAttributes attributes;
- attributes["EXECUTABLE_PREFIX"] = "";
- attributes["HEADER_SEARCH_PATHS"] = sources_->path();
- attributes["PRODUCT_NAME"] = "sources";
-
- PBXFileReference* product_reference = static_cast<PBXFileReference*>(
- products_->AddChild(std::make_unique<PBXFileReference>(
- std::string(), "sources", "compiled.mach-o.executable")));
-
- const char product_type[] = "com.apple.product-type.tool";
- targets_.push_back(std::make_unique<PBXNativeTarget>(
- "sources", std::string(), config_name_, attributes, product_type,
- "sources", product_reference));
- target_for_indexing_ = static_cast<PBXNativeTarget*>(targets_.back().get());
-}
-
-PBXNativeTarget* PBXProject::AddNativeTarget(
- const std::string& name,
- const std::string& type,
- const std::string& output_name,
- const std::string& output_type,
- const std::string& shell_script,
- const PBXAttributes& extra_attributes) {
- base::StringPiece ext = FindExtension(&output_name);
- PBXFileReference* product = static_cast<PBXFileReference*>(
- products_->AddChild(std::make_unique<PBXFileReference>(
- std::string(), output_name,
- type.empty() ? GetSourceType(ext) : type)));
-
- // Per Xcode build settings documentation: Product Name (PRODUCT_NAME) should
- // the basename of the product generated by the target.
- // Therefore, take the basename of output name without file extension as the
- // "PRODUCT_NAME".
- size_t basename_offset = FindFilenameOffset(output_name);
- std::string output_basename = basename_offset != std::string::npos
- ? output_name.substr(basename_offset)
- : output_name;
- size_t ext_offset = FindExtensionOffset(output_basename);
- std::string product_name = ext_offset != std::string::npos
- ? output_basename.substr(0, ext_offset - 1)
- : output_basename;
-
- PBXAttributes attributes = extra_attributes;
- attributes["CODE_SIGNING_REQUIRED"] = "NO";
- attributes["CONFIGURATION_BUILD_DIR"] = ".";
- attributes["PRODUCT_NAME"] = product_name;
-
- targets_.push_back(std::make_unique<PBXNativeTarget>(
- name, shell_script, config_name_, attributes, output_type, product_name,
- product));
- return static_cast<PBXNativeTarget*>(targets_.back().get());
-}
-
-void PBXProject::SetProjectDirPath(const std::string& project_dir_path) {
- DCHECK(!project_dir_path.empty());
- project_dir_path_.assign(project_dir_path);
-}
-
-void PBXProject::SetProjectRoot(const std::string& project_root) {
- DCHECK(!project_root.empty());
- project_root_.assign(project_root);
-}
-
-void PBXProject::AddTarget(std::unique_ptr<PBXTarget> target) {
- DCHECK(target);
- targets_.push_back(std::move(target));
-}
-
-PBXObjectClass PBXProject::Class() const {
- return PBXProjectClass;
-}
-
-std::string PBXProject::Name() const {
- return name_;
-}
-
-std::string PBXProject::Comment() const {
- return "Project object";
-}
-
-void PBXProject::Visit(PBXObjectVisitor& visitor) {
- PBXObject::Visit(visitor);
- configurations_->Visit(visitor);
- main_group_->Visit(visitor);
- for (const auto& target : targets_) {
- target->Visit(visitor);
- }
-}
-
-void PBXProject::Print(std::ostream& out, unsigned indent) const {
- const std::string indent_str(indent, '\t');
- const IndentRules rules = {false, indent + 1};
- out << indent_str << Reference() << " = {\n";
- PrintProperty(out, rules, "isa", ToString(Class()));
- PrintProperty(out, rules, "attributes", attributes_);
- PrintProperty(out, rules, "buildConfigurationList", configurations_);
- PrintProperty(out, rules, "compatibilityVersion", "Xcode 3.2");
- PrintProperty(out, rules, "developmentRegion", "English");
- PrintProperty(out, rules, "hasScannedForEncodings", 1u);
- PrintProperty(out, rules, "knownRegions", std::vector<std::string>({"en"}));
- PrintProperty(out, rules, "mainGroup", main_group_);
- PrintProperty(out, rules, "projectDirPath", project_dir_path_);
- PrintProperty(out, rules, "projectRoot", project_root_);
- PrintProperty(out, rules, "targets", targets_);
- out << indent_str << "};\n";
-}
-
-// PBXShellScriptBuildPhase ---------------------------------------------------
-
-PBXShellScriptBuildPhase::PBXShellScriptBuildPhase(
- const std::string& name,
- const std::string& shell_script)
- : name_("Action \"Compile and copy " + name + " via ninja\""),
- shell_script_(shell_script) {}
-
-PBXShellScriptBuildPhase::~PBXShellScriptBuildPhase() = default;
-
-PBXObjectClass PBXShellScriptBuildPhase::Class() const {
- return PBXShellScriptBuildPhaseClass;
-}
-
-std::string PBXShellScriptBuildPhase::Name() const {
- return name_;
-}
-
-void PBXShellScriptBuildPhase::Print(std::ostream& out, unsigned indent) const {
- const std::string indent_str(indent, '\t');
- const IndentRules rules = {false, indent + 1};
- out << indent_str << Reference() << " = {\n";
- PrintProperty(out, rules, "isa", ToString(Class()));
- PrintProperty(out, rules, "buildActionMask", 0x7fffffffu);
- PrintProperty(out, rules, "files", EmptyPBXObjectVector());
- PrintProperty(out, rules, "inputPaths", EmptyPBXObjectVector());
- PrintProperty(out, rules, "name", name_);
- PrintProperty(out, rules, "outputPaths", EmptyPBXObjectVector());
- PrintProperty(out, rules, "runOnlyForDeploymentPostprocessing", 0u);
- PrintProperty(out, rules, "shellPath", "/bin/sh");
- PrintProperty(out, rules, "shellScript", shell_script_);
- PrintProperty(out, rules, "showEnvVarsInLog", 0u);
- out << indent_str << "};\n";
-}
-
-// PBXSourcesBuildPhase -------------------------------------------------------
-
-PBXSourcesBuildPhase::PBXSourcesBuildPhase() = default;
-
-PBXSourcesBuildPhase::~PBXSourcesBuildPhase() = default;
-
-void PBXSourcesBuildPhase::AddBuildFile(
- std::unique_ptr<PBXBuildFile> build_file) {
- files_.push_back(std::move(build_file));
-}
-
-PBXObjectClass PBXSourcesBuildPhase::Class() const {
- return PBXSourcesBuildPhaseClass;
-}
-
-std::string PBXSourcesBuildPhase::Name() const {
- return "Sources";
-}
-
-void PBXSourcesBuildPhase::Visit(PBXObjectVisitor& visitor) {
- PBXBuildPhase::Visit(visitor);
- for (const auto& file : files_) {
- file->Visit(visitor);
- }
-}
-
-void PBXSourcesBuildPhase::Print(std::ostream& out, unsigned indent) const {
- const std::string indent_str(indent, '\t');
- const IndentRules rules = {false, indent + 1};
- out << indent_str << Reference() << " = {\n";
- PrintProperty(out, rules, "isa", ToString(Class()));
- PrintProperty(out, rules, "buildActionMask", 0x7fffffffu);
- PrintProperty(out, rules, "files", files_);
- PrintProperty(out, rules, "runOnlyForDeploymentPostprocessing", 0u);
- out << indent_str << "};\n";
-}
-
-PBXTargetDependency::PBXTargetDependency(
- const PBXTarget* target,
- std::unique_ptr<PBXContainerItemProxy> container_item_proxy)
- : target_(target), container_item_proxy_(std::move(container_item_proxy)) {}
-
-PBXTargetDependency::~PBXTargetDependency() = default;
-
-PBXObjectClass PBXTargetDependency::Class() const {
- return PBXTargetDependencyClass;
-}
-std::string PBXTargetDependency::Name() const {
- return "PBXTargetDependency";
-}
-void PBXTargetDependency::Visit(PBXObjectVisitor& visitor) {
- PBXObject::Visit(visitor);
- container_item_proxy_->Visit(visitor);
-}
-void PBXTargetDependency::Print(std::ostream& out, unsigned indent) const {
- const std::string indent_str(indent, '\t');
- const IndentRules rules = {false, indent + 1};
- out << indent_str << Reference() << " = {\n";
- PrintProperty(out, rules, "isa", ToString(Class()));
- PrintProperty(out, rules, "target", target_);
- PrintProperty(out, rules, "targetProxy", container_item_proxy_);
- out << indent_str << "};\n";
-}
-
-// XCBuildConfiguration -------------------------------------------------------
-
-XCBuildConfiguration::XCBuildConfiguration(const std::string& name,
- const PBXAttributes& attributes)
- : attributes_(attributes), name_(name) {}
-
-XCBuildConfiguration::~XCBuildConfiguration() = default;
-
-PBXObjectClass XCBuildConfiguration::Class() const {
- return XCBuildConfigurationClass;
-}
-
-std::string XCBuildConfiguration::Name() const {
- return name_;
-}
-
-void XCBuildConfiguration::Print(std::ostream& out, unsigned indent) const {
- const std::string indent_str(indent, '\t');
- const IndentRules rules = {false, indent + 1};
- out << indent_str << Reference() << " = {\n";
- PrintProperty(out, rules, "isa", ToString(Class()));
- PrintProperty(out, rules, "buildSettings", attributes_);
- PrintProperty(out, rules, "name", name_);
- out << indent_str << "};\n";
-}
-
-// XCConfigurationList --------------------------------------------------------
-
-XCConfigurationList::XCConfigurationList(const std::string& name,
- const PBXAttributes& attributes,
- const PBXObject* owner_reference)
- : owner_reference_(owner_reference) {
- DCHECK(owner_reference_);
- configurations_.push_back(
- std::make_unique<XCBuildConfiguration>(name, attributes));
-}
-
-XCConfigurationList::~XCConfigurationList() = default;
-
-PBXObjectClass XCConfigurationList::Class() const {
- return XCConfigurationListClass;
-}
-
-std::string XCConfigurationList::Name() const {
- std::stringstream buffer;
- buffer << "Build configuration list for "
- << ToString(owner_reference_->Class()) << " \""
- << owner_reference_->Name() << "\"";
- return buffer.str();
-}
-
-void XCConfigurationList::Visit(PBXObjectVisitor& visitor) {
- PBXObject::Visit(visitor);
- for (const auto& configuration : configurations_) {
- configuration->Visit(visitor);
- }
-}
-
-void XCConfigurationList::Print(std::ostream& out, unsigned indent) const {
- const std::string indent_str(indent, '\t');
- const IndentRules rules = {false, indent + 1};
- out << indent_str << Reference() << " = {\n";
- PrintProperty(out, rules, "isa", ToString(Class()));
- PrintProperty(out, rules, "buildConfigurations", configurations_);
- PrintProperty(out, rules, "defaultConfigurationIsVisible", 1u);
- PrintProperty(out, rules, "defaultConfigurationName",
- configurations_[0]->Name());
- out << indent_str << "};\n";
-}
diff --git a/chromium/tools/gn/xcode_object.h b/chromium/tools/gn/xcode_object.h
deleted file mode 100644
index c695dbbeaad..00000000000
--- a/chromium/tools/gn/xcode_object.h
+++ /dev/null
@@ -1,464 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_XCODE_OBJECT_H_
-#define TOOLS_GN_XCODE_OBJECT_H_
-
-#include <iosfwd>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-
-// Helper classes to generate Xcode project files.
-//
-// This code is based on gyp xcodeproj_file.py generator. It does not support
-// all features of Xcode project but instead just enough to implement a hybrid
-// mode where Xcode uses external scripts to perform the compilation steps.
-//
-// See https://chromium.googlesource.com/external/gyp/+/master/pylib/gyp/xcodeproj_file.py
-// for more information on Xcode project file format.
-
-enum class CompilerFlags {
- NONE,
- HELP,
-};
-
-// PBXObjectClass -------------------------------------------------------------
-
-enum PBXObjectClass {
- // Those values needs to stay sorted in alphabetic order.
- PBXAggregateTargetClass,
- PBXBuildFileClass,
- PBXContainerItemProxyClass,
- PBXFileReferenceClass,
- PBXFrameworksBuildPhaseClass,
- PBXGroupClass,
- PBXNativeTargetClass,
- PBXProjectClass,
- PBXShellScriptBuildPhaseClass,
- PBXSourcesBuildPhaseClass,
- PBXTargetDependencyClass,
- XCBuildConfigurationClass,
- XCConfigurationListClass,
-};
-
-const char* ToString(PBXObjectClass cls);
-
-// Forward-declarations -------------------------------------------------------
-
-class PBXAggregateTarget;
-class PBXBuildFile;
-class PBXBuildPhase;
-class PBXContainerItemProxy;
-class PBXFileReference;
-class PBXFrameworksBuildPhase;
-class PBXGroup;
-class PBXNativeTarget;
-class PBXObject;
-class PBXProject;
-class PBXShellScriptBuildPhase;
-class PBXSourcesBuildPhase;
-class PBXTarget;
-class PBXTargetDependency;
-class XCBuildConfiguration;
-class XCConfigurationList;
-
-using PBXAttributes = std::map<std::string, std::string>;
-
-// PBXObjectVisitor -----------------------------------------------------------
-
-class PBXObjectVisitor {
- public:
- PBXObjectVisitor();
- virtual ~PBXObjectVisitor();
- virtual void Visit(PBXObject* object) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PBXObjectVisitor);
-};
-
-// PBXObject ------------------------------------------------------------------
-
-class PBXObject {
- public:
- PBXObject();
- virtual ~PBXObject();
-
- const std::string id() const { return id_; }
- void SetId(const std::string& id);
-
- std::string Reference() const;
-
- virtual PBXObjectClass Class() const = 0;
- virtual std::string Name() const = 0;
- virtual std::string Comment() const;
- virtual void Visit(PBXObjectVisitor& visitor);
- virtual void Print(std::ostream& out, unsigned indent) const = 0;
-
- private:
- std::string id_;
-
- DISALLOW_COPY_AND_ASSIGN(PBXObject);
-};
-
-// PBXBuildPhase --------------------------------------------------------------
-
-class PBXBuildPhase : public PBXObject {
- public:
- PBXBuildPhase();
- ~PBXBuildPhase() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PBXBuildPhase);
-};
-
-// PBXTarget ------------------------------------------------------------------
-
-class PBXTarget : public PBXObject {
- public:
- PBXTarget(const std::string& name,
- const std::string& shell_script,
- const std::string& config_name,
- const PBXAttributes& attributes);
- ~PBXTarget() override;
-
- void AddDependency(std::unique_ptr<PBXTargetDependency> dependency);
-
- // PBXObject implementation.
- std::string Name() const override;
- void Visit(PBXObjectVisitor& visitor) override;
-
- protected:
- std::unique_ptr<XCConfigurationList> configurations_;
- std::vector<std::unique_ptr<PBXBuildPhase>> build_phases_;
- std::vector<std::unique_ptr<PBXTargetDependency>> dependencies_;
- PBXSourcesBuildPhase* source_build_phase_;
- std::string name_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PBXTarget);
-};
-
-// PBXAggregateTarget ---------------------------------------------------------
-
-class PBXAggregateTarget : public PBXTarget {
- public:
- PBXAggregateTarget(const std::string& name,
- const std::string& shell_script,
- const std::string& config_name,
- const PBXAttributes& attributes);
- ~PBXAggregateTarget() override;
-
- // PBXObject implementation.
- PBXObjectClass Class() const override;
- void Print(std::ostream& out, unsigned indent) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PBXAggregateTarget);
-};
-
-// PBXBuildFile ---------------------------------------------------------------
-
-class PBXBuildFile : public PBXObject {
- public:
- PBXBuildFile(const PBXFileReference* file_reference,
- const PBXSourcesBuildPhase* build_phase,
- const CompilerFlags compiler_flag);
- ~PBXBuildFile() override;
-
- // PBXObject implementation.
- PBXObjectClass Class() const override;
- std::string Name() const override;
- void Print(std::ostream& out, unsigned indent) const override;
-
- private:
- const PBXFileReference* file_reference_;
- const PBXSourcesBuildPhase* build_phase_;
- const CompilerFlags compiler_flag_;
-
- DISALLOW_COPY_AND_ASSIGN(PBXBuildFile);
-};
-
-// PBXContainerItemProxy ------------------------------------------------------
-class PBXContainerItemProxy : public PBXObject {
- public:
- PBXContainerItemProxy(const PBXProject* project, const PBXTarget* target);
- ~PBXContainerItemProxy() override;
-
- // PBXObject implementation.
- PBXObjectClass Class() const override;
- std::string Name() const override;
- void Visit(PBXObjectVisitor& visitor) override;
- void Print(std::ostream& out, unsigned indent) const override;
-
- private:
- const PBXProject* project_;
- const PBXTarget* target_;
-
- DISALLOW_COPY_AND_ASSIGN(PBXContainerItemProxy);
-};
-
-// PBXFileReference -----------------------------------------------------------
-
-class PBXFileReference : public PBXObject {
- public:
- PBXFileReference(const std::string& name,
- const std::string& path,
- const std::string& type);
- ~PBXFileReference() override;
-
- // PBXObject implementation.
- PBXObjectClass Class() const override;
- std::string Name() const override;
- void Print(std::ostream& out, unsigned indent) const override;
-
- const std::string& path() const { return path_; }
-
- private:
- std::string name_;
- std::string path_;
- std::string type_;
-
- DISALLOW_COPY_AND_ASSIGN(PBXFileReference);
-};
-
-// PBXFrameworksBuildPhase ----------------------------------------------------
-
-class PBXFrameworksBuildPhase : public PBXBuildPhase {
- public:
- PBXFrameworksBuildPhase();
- ~PBXFrameworksBuildPhase() override;
-
- // PBXObject implementation.
- PBXObjectClass Class() const override;
- std::string Name() const override;
- void Print(std::ostream& out, unsigned indent) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PBXFrameworksBuildPhase);
-};
-
-// PBXGroup -------------------------------------------------------------------
-
-class PBXGroup : public PBXObject {
- public:
- explicit PBXGroup(const std::string& path = std::string(),
- const std::string& name = std::string());
- ~PBXGroup() override;
-
- const std::string& path() const { return path_; }
-
- PBXObject* AddChild(std::unique_ptr<PBXObject> child);
- PBXFileReference* AddSourceFile(const std::string& navigator_path,
- const std::string& source_path);
- bool is_source() { return is_source_; }
- void set_is_source(const bool is_source) { is_source_ = is_source; }
-
- // PBXObject implementation.
- PBXObjectClass Class() const override;
- std::string Name() const override;
- void Visit(PBXObjectVisitor& visitor) override;
- void Print(std::ostream& out, unsigned indent) const override;
-
- private:
- std::vector<std::unique_ptr<PBXObject>> children_;
- std::string name_;
- std::string path_;
- bool is_source_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(PBXGroup);
-};
-
-// PBXNativeTarget ------------------------------------------------------------
-
-class PBXNativeTarget : public PBXTarget {
- public:
- PBXNativeTarget(const std::string& name,
- const std::string& shell_script,
- const std::string& config_name,
- const PBXAttributes& attributes,
- const std::string& product_type,
- const std::string& product_name,
- const PBXFileReference* product_reference);
- ~PBXNativeTarget() override;
-
- void AddFileForIndexing(const PBXFileReference* file_reference,
- const CompilerFlags compiler_flag);
-
- // PBXObject implementation.
- PBXObjectClass Class() const override;
- void Print(std::ostream& out, unsigned indent) const override;
-
- private:
- const PBXFileReference* product_reference_;
- std::string product_type_;
- std::string product_name_;
-
- DISALLOW_COPY_AND_ASSIGN(PBXNativeTarget);
-};
-
-// PBXProject -----------------------------------------------------------------
-
-class PBXProject : public PBXObject {
- public:
- PBXProject(const std::string& name,
- const std::string& config_name,
- const std::string& source_path,
- const PBXAttributes& attributes);
- ~PBXProject() override;
-
- void AddSourceFileToIndexingTarget(const std::string& navigator_path,
- const std::string& source_path,
- const CompilerFlags compiler_flag);
- void AddSourceFile(const std::string& navigator_path,
- const std::string& source_path,
- const CompilerFlags compiler_flag,
- PBXNativeTarget* target);
- void AddAggregateTarget(const std::string& name,
- const std::string& shell_script);
- void AddIndexingTarget();
- PBXNativeTarget* AddNativeTarget(
- const std::string& name,
- const std::string& type,
- const std::string& output_name,
- const std::string& output_type,
- const std::string& shell_script,
- const PBXAttributes& extra_attributes = PBXAttributes());
-
- void SetProjectDirPath(const std::string& project_dir_path);
- void SetProjectRoot(const std::string& project_root);
- void AddTarget(std::unique_ptr<PBXTarget> target);
-
- // PBXObject implementation.
- PBXObjectClass Class() const override;
- std::string Name() const override;
- std::string Comment() const override;
- void Visit(PBXObjectVisitor& visitor) override;
- void Print(std::ostream& out, unsigned indent) const override;
-
- private:
- PBXAttributes attributes_;
- std::unique_ptr<XCConfigurationList> configurations_;
- std::unique_ptr<PBXGroup> main_group_;
- std::string project_dir_path_;
- std::string project_root_;
- std::vector<std::unique_ptr<PBXTarget>> targets_;
- std::string name_;
- std::string config_name_;
-
- PBXGroup* sources_;
- PBXGroup* products_;
- PBXNativeTarget* target_for_indexing_;
-
- DISALLOW_COPY_AND_ASSIGN(PBXProject);
-};
-
-// PBXShellScriptBuildPhase ---------------------------------------------------
-
-class PBXShellScriptBuildPhase : public PBXBuildPhase {
- public:
- PBXShellScriptBuildPhase(const std::string& name,
- const std::string& shell_script);
- ~PBXShellScriptBuildPhase() override;
-
- // PBXObject implementation.
- PBXObjectClass Class() const override;
- std::string Name() const override;
- void Print(std::ostream& out, unsigned indent) const override;
-
- private:
- std::string name_;
- std::string shell_script_;
-
- DISALLOW_COPY_AND_ASSIGN(PBXShellScriptBuildPhase);
-};
-
-// PBXSourcesBuildPhase -------------------------------------------------------
-
-class PBXSourcesBuildPhase : public PBXBuildPhase {
- public:
- PBXSourcesBuildPhase();
- ~PBXSourcesBuildPhase() override;
-
- void AddBuildFile(std::unique_ptr<PBXBuildFile> build_file);
-
- // PBXObject implementation.
- PBXObjectClass Class() const override;
- std::string Name() const override;
- void Visit(PBXObjectVisitor& visitor) override;
- void Print(std::ostream& out, unsigned indent) const override;
-
- private:
- std::vector<std::unique_ptr<PBXBuildFile>> files_;
-
- DISALLOW_COPY_AND_ASSIGN(PBXSourcesBuildPhase);
-};
-
-// PBXTargetDependency -----------------------------------------------------
-class PBXTargetDependency : public PBXObject {
- public:
- PBXTargetDependency(
- const PBXTarget* target,
- std::unique_ptr<PBXContainerItemProxy> container_item_proxy);
- ~PBXTargetDependency() override;
-
- // PBXObject implementation.
- PBXObjectClass Class() const override;
- std::string Name() const override;
- void Visit(PBXObjectVisitor& visitor) override;
- void Print(std::ostream& out, unsigned indent) const override;
-
- private:
- const PBXTarget* target_;
- std::unique_ptr<PBXContainerItemProxy> container_item_proxy_;
-
- DISALLOW_COPY_AND_ASSIGN(PBXTargetDependency);
-};
-
-// XCBuildConfiguration -------------------------------------------------------
-
-class XCBuildConfiguration : public PBXObject {
- public:
- XCBuildConfiguration(const std::string& name,
- const PBXAttributes& attributes);
- ~XCBuildConfiguration() override;
-
- // PBXObject implementation.
- PBXObjectClass Class() const override;
- std::string Name() const override;
- void Print(std::ostream& out, unsigned indent) const override;
-
- private:
- PBXAttributes attributes_;
- std::string name_;
-
- DISALLOW_COPY_AND_ASSIGN(XCBuildConfiguration);
-};
-
-// XCConfigurationList --------------------------------------------------------
-
-class XCConfigurationList : public PBXObject {
- public:
- XCConfigurationList(const std::string& name,
- const PBXAttributes& attributes,
- const PBXObject* owner_reference);
- ~XCConfigurationList() override;
-
- // PBXObject implementation.
- PBXObjectClass Class() const override;
- std::string Name() const override;
- void Visit(PBXObjectVisitor& visitor) override;
- void Print(std::ostream& out, unsigned indent) const override;
-
- private:
- std::vector<std::unique_ptr<XCBuildConfiguration>> configurations_;
- const PBXObject* owner_reference_;
-
- DISALLOW_COPY_AND_ASSIGN(XCConfigurationList);
-};
-
-#endif // TOOLS_GN_XCODE_OBJECT_H_
diff --git a/chromium/tools/gn/xcode_object_unittest.cc b/chromium/tools/gn/xcode_object_unittest.cc
deleted file mode 100644
index 656d0b7463c..00000000000
--- a/chromium/tools/gn/xcode_object_unittest.cc
+++ /dev/null
@@ -1,435 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/xcode_object.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// Instantiate a PBXSourcesBuildPhase object.
-std::unique_ptr<PBXSourcesBuildPhase> GetPBXSourcesBuildPhaseObject() {
- std::unique_ptr<PBXSourcesBuildPhase> pbx_sources_build_phase(
- new PBXSourcesBuildPhase());
- return pbx_sources_build_phase;
-}
-
-// Instantiate a PBXFrameworksBuildPhase object.
-std::unique_ptr<PBXFrameworksBuildPhase> GetPBXFrameworksBuildPhaseObject() {
- std::unique_ptr<PBXFrameworksBuildPhase> pbx_frameworks_build_phase(
- new PBXFrameworksBuildPhase());
- return pbx_frameworks_build_phase;
-}
-
-// Instantiate a PBXShellScriptBuildPhase object with arbitrary names.
-std::unique_ptr<PBXShellScriptBuildPhase> GetPBXShellScriptBuildPhaseObject() {
- std::unique_ptr<PBXShellScriptBuildPhase> pbx_shell_script_build_phase(
- new PBXShellScriptBuildPhase("name", "shell_script"));
- return pbx_shell_script_build_phase;
-}
-
-// Instantiate a PBXGroup object with arbitrary names.
-std::unique_ptr<PBXGroup> GetPBXGroupObject() {
- std::unique_ptr<PBXGroup> pbx_group(new PBXGroup("/dir1/dir2", "group"));
- return pbx_group;
-}
-
-// Instantiate a PBXProject object with arbitrary names.
-std::unique_ptr<PBXProject> GetPBXProjectObject() {
- std::unique_ptr<PBXProject> pbx_project(
- new PBXProject("project", "config", "out/build", PBXAttributes()));
- return pbx_project;
-}
-
-// Instantiate a PBXFileReference object with arbitrary names.
-std::unique_ptr<PBXFileReference> GetPBXFileReferenceObject() {
- std::unique_ptr<PBXFileReference> pbx_file_reference(new PBXFileReference(
- "product.app", "product.app", "wrapper.application"));
- return pbx_file_reference;
-}
-
-// Instantiate a PBXBuildFile object.
-std::unique_ptr<PBXBuildFile> GetPBXBuildFileObject(
- const PBXFileReference* file_reference,
- const PBXSourcesBuildPhase* build_phase) {
- std::unique_ptr<PBXBuildFile> pbx_build_file(
- new PBXBuildFile(file_reference, build_phase, CompilerFlags::NONE));
- return pbx_build_file;
-}
-
-// Instantiate a PBXAggregateTarget object with arbitrary names.
-std::unique_ptr<PBXAggregateTarget> GetPBXAggregateTargetObject() {
- std::unique_ptr<PBXAggregateTarget> pbx_aggregate_target(
- new PBXAggregateTarget("target_name", "shell_script", "config_name",
- PBXAttributes()));
- return pbx_aggregate_target;
-}
-
-// Instantiate a PBXNativeTarget object with arbitrary names.
-std::unique_ptr<PBXNativeTarget> GetPBXNativeTargetObject(
- const PBXFileReference* product_reference) {
- std::unique_ptr<PBXNativeTarget> pbx_native_target(new PBXNativeTarget(
- "target_name", "ninja gn_unittests", "config_name", PBXAttributes(),
- "com.apple.product-type.application", "product_name", product_reference));
- return pbx_native_target;
-}
-
-// Instantiate a PBXContainerItemProxy object.
-std::unique_ptr<PBXContainerItemProxy> GetPBXContainerItemProxyObject(
- const PBXProject* project,
- const PBXTarget* target) {
- std::unique_ptr<PBXContainerItemProxy> pbx_container_item_proxy(
- new PBXContainerItemProxy(project, target));
- return pbx_container_item_proxy;
-}
-
-// Instantiate a PBXTargetDependency object.
-std::unique_ptr<PBXTargetDependency> GetPBXTargetDependencyObject(
- const PBXTarget* target,
- std::unique_ptr<PBXContainerItemProxy> container_item_proxy) {
- std::unique_ptr<PBXTargetDependency> pbx_target_dependency(
- new PBXTargetDependency(target, std::move(container_item_proxy)));
- return pbx_target_dependency;
-}
-
-// Instantiate a XCBuildConfiguration object with arbitrary names.
-std::unique_ptr<XCBuildConfiguration> GetXCBuildConfigurationObject() {
- std::unique_ptr<XCBuildConfiguration> xc_build_configuration(
- new XCBuildConfiguration("config_name", PBXAttributes()));
- return xc_build_configuration;
-}
-
-// Instantiate a XCConfigurationList object with arbitrary names.
-std::unique_ptr<XCConfigurationList> GetXCConfigurationListObject(
- const PBXObject* owner_reference) {
- std::unique_ptr<XCConfigurationList> xc_configuration_list(
- new XCConfigurationList("config_list_name", PBXAttributes(),
- owner_reference));
- return xc_configuration_list;
-}
-
-} // namespace
-
-// Tests that instantiating Xcode objects doesn't crash.
-TEST(XcodeObject, InstantiatePBXSourcesBuildPhase) {
- std::unique_ptr<PBXSourcesBuildPhase> pbx_sources_build_phase =
- GetPBXSourcesBuildPhaseObject();
-}
-
-TEST(XcodeObject, InstantiatePBXFrameworksBuildPhase) {
- std::unique_ptr<PBXFrameworksBuildPhase> pbx_frameworks_build_phase =
- GetPBXFrameworksBuildPhaseObject();
-}
-
-TEST(XcodeObject, InstantiatePBXShellScriptBuildPhase) {
- std::unique_ptr<PBXShellScriptBuildPhase> pbx_shell_script_build_phase =
- GetPBXShellScriptBuildPhaseObject();
-}
-
-TEST(XcodeObject, InstantiatePBXGroup) {
- std::unique_ptr<PBXGroup> pbx_group = GetPBXGroupObject();
-}
-
-TEST(XcodeObject, InstantiatePBXProject) {
- std::unique_ptr<PBXProject> pbx_project = GetPBXProjectObject();
-}
-
-TEST(XcodeObject, InstantiatePBXFileReference) {
- std::unique_ptr<PBXFileReference> pbx_file_reference =
- GetPBXFileReferenceObject();
-}
-
-TEST(XcodeObject, InstantiatePBXBuildFile) {
- std::unique_ptr<PBXFileReference> pbx_file_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXSourcesBuildPhase> pbx_sources_build_phase =
- GetPBXSourcesBuildPhaseObject();
- std::unique_ptr<PBXBuildFile> pbx_build_file = GetPBXBuildFileObject(
- pbx_file_reference.get(), pbx_sources_build_phase.get());
-}
-
-TEST(XcodeObject, InstantiatePBXAggregateTarget) {
- std::unique_ptr<PBXAggregateTarget> pbx_aggregate_target =
- GetPBXAggregateTargetObject();
-}
-
-TEST(XcodeObject, InstantiatePBXNativeTarget) {
- std::unique_ptr<PBXFileReference> product_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXNativeTarget> pbx_native_target =
- GetPBXNativeTargetObject(product_reference.get());
-}
-
-TEST(XcodeObject, InstantiatePBXContainerItemProxy) {
- std::unique_ptr<PBXFileReference> product_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXNativeTarget> pbx_native_target =
- GetPBXNativeTargetObject(product_reference.get());
- std::unique_ptr<PBXProject> pbx_project = GetPBXProjectObject();
- std::unique_ptr<PBXContainerItemProxy> pbx_container_item_proxy =
- GetPBXContainerItemProxyObject(pbx_project.get(),
- pbx_native_target.get());
-}
-
-TEST(XcodeObject, InstantiatePBXTargetDependency) {
- std::unique_ptr<PBXFileReference> product_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXProject> pbx_project = GetPBXProjectObject();
- std::unique_ptr<PBXNativeTarget> pbx_native_target =
- GetPBXNativeTargetObject(product_reference.get());
- std::unique_ptr<PBXContainerItemProxy> pbx_container_item_proxy =
- GetPBXContainerItemProxyObject(pbx_project.get(),
- pbx_native_target.get());
- std::unique_ptr<PBXTargetDependency> pbx_target_dependency =
- GetPBXTargetDependencyObject(pbx_native_target.get(),
- std::move(pbx_container_item_proxy));
-}
-
-TEST(XcodeObject, InstantiateXCBuildConfiguration) {
- std::unique_ptr<XCBuildConfiguration> xc_build_configuration =
- GetXCBuildConfigurationObject();
-}
-
-TEST(XcodeObject, InstantiateXCConfigurationList) {
- std::unique_ptr<PBXFileReference> product_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXNativeTarget> pbx_native_target =
- GetPBXNativeTargetObject(product_reference.get());
- std::unique_ptr<XCConfigurationList> xc_configuration_list =
- GetXCConfigurationListObject(pbx_native_target.get());
-}
-
-// Tests that the mapping between PBXObject and PBXObjectClass.
-TEST(XcodeObject, PBXSourcesBuildPhaseObjectToClass) {
- std::unique_ptr<PBXSourcesBuildPhase> pbx_sources_build_phase =
- GetPBXSourcesBuildPhaseObject();
- EXPECT_EQ(PBXSourcesBuildPhaseClass, pbx_sources_build_phase->Class());
-}
-
-TEST(XcodeObject, PBXFrameworksBuildPhaseObjectToClass) {
- std::unique_ptr<PBXFrameworksBuildPhase> pbx_frameworks_build_phase =
- GetPBXFrameworksBuildPhaseObject();
- EXPECT_EQ(PBXFrameworksBuildPhaseClass, pbx_frameworks_build_phase->Class());
-}
-
-TEST(XcodeObject, PBXShellScriptBuildPhaseObjectToClass) {
- std::unique_ptr<PBXShellScriptBuildPhase> pbx_shell_script_build_phase =
- GetPBXShellScriptBuildPhaseObject();
- EXPECT_EQ(PBXShellScriptBuildPhaseClass,
- pbx_shell_script_build_phase->Class());
-}
-
-TEST(XcodeObject, PBXGroupObjectToClass) {
- std::unique_ptr<PBXGroup> pbx_group = GetPBXGroupObject();
- EXPECT_EQ(PBXGroupClass, pbx_group->Class());
-}
-
-TEST(XcodeObject, PBXProjectObjectToClass) {
- std::unique_ptr<PBXProject> pbx_project = GetPBXProjectObject();
- EXPECT_EQ(PBXProjectClass, pbx_project->Class());
-}
-
-TEST(XcodeObject, PBXFileReferenceObjectToClass) {
- std::unique_ptr<PBXFileReference> pbx_file_reference =
- GetPBXFileReferenceObject();
- EXPECT_EQ(PBXFileReferenceClass, pbx_file_reference->Class());
-}
-
-TEST(XcodeObject, PBXBuildFileObjectToClass) {
- std::unique_ptr<PBXFileReference> pbx_file_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXSourcesBuildPhase> pbx_sources_build_phase =
- GetPBXSourcesBuildPhaseObject();
- std::unique_ptr<PBXBuildFile> pbx_build_file = GetPBXBuildFileObject(
- pbx_file_reference.get(), pbx_sources_build_phase.get());
- EXPECT_EQ(PBXBuildFileClass, pbx_build_file->Class());
-}
-
-TEST(XcodeObject, PBXAggregateTargetObjectToClass) {
- std::unique_ptr<PBXAggregateTarget> pbx_aggregate_target =
- GetPBXAggregateTargetObject();
- EXPECT_EQ(PBXAggregateTargetClass, pbx_aggregate_target->Class());
-}
-
-TEST(XcodeObject, PBXNativeTargetObjectToClass) {
- std::unique_ptr<PBXFileReference> product_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXNativeTarget> pbx_native_target =
- GetPBXNativeTargetObject(product_reference.get());
- EXPECT_EQ(PBXNativeTargetClass, pbx_native_target->Class());
-}
-
-TEST(XcodeObject, PBXContainerItemProxyObjectToClass) {
- std::unique_ptr<PBXFileReference> product_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXNativeTarget> pbx_native_target =
- GetPBXNativeTargetObject(product_reference.get());
- std::unique_ptr<PBXProject> pbx_project = GetPBXProjectObject();
- std::unique_ptr<PBXContainerItemProxy> pbx_container_item_proxy =
- GetPBXContainerItemProxyObject(pbx_project.get(),
- pbx_native_target.get());
- EXPECT_EQ(PBXContainerItemProxyClass, pbx_container_item_proxy->Class());
-}
-
-TEST(XcodeObject, PBXTargetDependencyObjectToClass) {
- std::unique_ptr<PBXFileReference> product_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXProject> pbx_project = GetPBXProjectObject();
- std::unique_ptr<PBXNativeTarget> pbx_native_target =
- GetPBXNativeTargetObject(product_reference.get());
- std::unique_ptr<PBXContainerItemProxy> pbx_container_item_proxy =
- GetPBXContainerItemProxyObject(pbx_project.get(),
- pbx_native_target.get());
- std::unique_ptr<PBXTargetDependency> pbx_target_dependency =
- GetPBXTargetDependencyObject(pbx_native_target.get(),
- std::move(pbx_container_item_proxy));
- EXPECT_EQ(PBXTargetDependencyClass, pbx_target_dependency->Class());
-}
-
-TEST(XcodeObject, XCBuildConfigurationObjectToClass) {
- std::unique_ptr<XCBuildConfiguration> xc_build_configuration =
- GetXCBuildConfigurationObject();
- EXPECT_EQ(XCBuildConfigurationClass, xc_build_configuration->Class());
-}
-
-TEST(XcodeObject, XCConfigurationListObjectToClass) {
- std::unique_ptr<PBXFileReference> product_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXNativeTarget> pbx_native_target =
- GetPBXNativeTargetObject(product_reference.get());
- std::unique_ptr<XCConfigurationList> xc_configuration_list =
- GetXCConfigurationListObject(pbx_native_target.get());
- EXPECT_EQ(XCConfigurationListClass, xc_configuration_list->Class());
-}
-
-// Tests the mapping between PBXObjectClass and it's name as a string.
-TEST(XcodeObject, ClassToString) {
- EXPECT_STREQ("PBXAggregateTarget", ToString(PBXAggregateTargetClass));
- EXPECT_STREQ("PBXBuildFile", ToString(PBXBuildFileClass));
- EXPECT_STREQ("PBXAggregateTarget", ToString(PBXAggregateTargetClass));
- EXPECT_STREQ("PBXBuildFile", ToString(PBXBuildFileClass));
- EXPECT_STREQ("PBXContainerItemProxy", ToString(PBXContainerItemProxyClass));
- EXPECT_STREQ("PBXFileReference", ToString(PBXFileReferenceClass));
- EXPECT_STREQ("PBXFrameworksBuildPhase",
- ToString(PBXFrameworksBuildPhaseClass));
- EXPECT_STREQ("PBXGroup", ToString(PBXGroupClass));
- EXPECT_STREQ("PBXNativeTarget", ToString(PBXNativeTargetClass));
- EXPECT_STREQ("PBXProject", ToString(PBXProjectClass));
- EXPECT_STREQ("PBXSourcesBuildPhase", ToString(PBXSourcesBuildPhaseClass));
- EXPECT_STREQ("PBXTargetDependency", ToString(PBXTargetDependencyClass));
- EXPECT_STREQ("XCBuildConfiguration", ToString(XCBuildConfigurationClass));
- EXPECT_STREQ("XCConfigurationList", ToString(XCConfigurationListClass));
- EXPECT_STREQ("PBXShellScriptBuildPhase",
- ToString(PBXShellScriptBuildPhaseClass));
-}
-
-// Tests the mapping between PBXObject and it's name as a string.
-TEST(XcodeObject, PBXSourcesBuildPhaseName) {
- std::unique_ptr<PBXSourcesBuildPhase> pbx_sources_build_phase =
- GetPBXSourcesBuildPhaseObject();
- EXPECT_EQ("Sources", pbx_sources_build_phase->Name());
-}
-
-TEST(XcodeObject, PBXFrameworksBuildPhaseName) {
- std::unique_ptr<PBXFrameworksBuildPhase> pbx_frameworks_build_phase =
- GetPBXFrameworksBuildPhaseObject();
- EXPECT_EQ("Frameworks", pbx_frameworks_build_phase->Name());
-}
-
-TEST(XcodeObject, PBXShellScriptBuildPhaseName) {
- std::unique_ptr<PBXShellScriptBuildPhase> pbx_shell_script_build_phase =
- GetPBXShellScriptBuildPhaseObject();
- EXPECT_EQ("Action \"Compile and copy name via ninja\"",
- pbx_shell_script_build_phase->Name());
-}
-
-TEST(XcodeObject, PBXGroupName) {
- PBXGroup pbx_group_with_name(std::string(), "name");
- EXPECT_EQ("name", pbx_group_with_name.Name());
-
- PBXGroup pbx_group_with_path("path", std::string());
- EXPECT_EQ("path", pbx_group_with_path.Name());
-
- PBXGroup pbx_group_empty{std::string(), std::string()};
- EXPECT_EQ(std::string(), pbx_group_empty.Name());
-}
-
-TEST(XcodeObject, PBXProjectName) {
- std::unique_ptr<PBXProject> pbx_project = GetPBXProjectObject();
- EXPECT_EQ("project", pbx_project->Name());
-}
-
-TEST(XcodeObject, PBXFileReferenceName) {
- std::unique_ptr<PBXFileReference> pbx_file_reference =
- GetPBXFileReferenceObject();
- EXPECT_EQ("product.app", pbx_file_reference->Name());
-}
-
-TEST(XcodeObject, PBXBuildFileName) {
- std::unique_ptr<PBXFileReference> pbx_file_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXSourcesBuildPhase> pbx_sources_build_phase =
- GetPBXSourcesBuildPhaseObject();
- std::unique_ptr<PBXBuildFile> pbx_build_file = GetPBXBuildFileObject(
- pbx_file_reference.get(), pbx_sources_build_phase.get());
- EXPECT_EQ("product.app in Sources", pbx_build_file->Name());
-}
-
-TEST(XcodeObject, PBXAggregateTargetName) {
- std::unique_ptr<PBXAggregateTarget> pbx_aggregate_target =
- GetPBXAggregateTargetObject();
- EXPECT_EQ("target_name", pbx_aggregate_target->Name());
-}
-
-TEST(XcodeObject, PBXNativeTargetName) {
- std::unique_ptr<PBXFileReference> product_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXNativeTarget> pbx_native_target =
- GetPBXNativeTargetObject(product_reference.get());
- EXPECT_EQ("target_name", pbx_native_target->Name());
-}
-
-TEST(XcodeObject, PBXContainerItemProxyName) {
- std::unique_ptr<PBXFileReference> product_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXNativeTarget> pbx_native_target =
- GetPBXNativeTargetObject(product_reference.get());
- std::unique_ptr<PBXProject> pbx_project = GetPBXProjectObject();
- std::unique_ptr<PBXContainerItemProxy> pbx_container_item_proxy =
- GetPBXContainerItemProxyObject(pbx_project.get(),
- pbx_native_target.get());
- EXPECT_EQ("PBXContainerItemProxy", pbx_container_item_proxy->Name());
-}
-
-TEST(XcodeObject, PBXTargetDependencyName) {
- std::unique_ptr<PBXFileReference> product_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXProject> pbx_project = GetPBXProjectObject();
- std::unique_ptr<PBXNativeTarget> pbx_native_target =
- GetPBXNativeTargetObject(product_reference.get());
- std::unique_ptr<PBXContainerItemProxy> pbx_container_item_proxy =
- GetPBXContainerItemProxyObject(pbx_project.get(),
- pbx_native_target.get());
- std::unique_ptr<PBXTargetDependency> pbx_target_dependency =
- GetPBXTargetDependencyObject(pbx_native_target.get(),
- std::move(pbx_container_item_proxy));
- EXPECT_EQ("PBXTargetDependency", pbx_target_dependency->Name());
-}
-
-TEST(XcodeObject, XCBuildConfigurationName) {
- std::unique_ptr<XCBuildConfiguration> xc_build_configuration =
- GetXCBuildConfigurationObject();
- EXPECT_EQ("config_name", xc_build_configuration->Name());
-}
-
-TEST(XcodeObject, XCConfigurationListName) {
- std::unique_ptr<PBXFileReference> product_reference =
- GetPBXFileReferenceObject();
- std::unique_ptr<PBXNativeTarget> pbx_native_target =
- GetPBXNativeTargetObject(product_reference.get());
- std::unique_ptr<XCConfigurationList> xc_configuration_list =
- GetXCConfigurationListObject(pbx_native_target.get());
- EXPECT_EQ("Build configuration list for PBXNativeTarget \"target_name\"",
- xc_configuration_list->Name());
-}
diff --git a/chromium/tools/gn/xcode_writer.cc b/chromium/tools/gn/xcode_writer.cc
deleted file mode 100644
index 37c23e2301b..00000000000
--- a/chromium/tools/gn/xcode_writer.cc
+++ /dev/null
@@ -1,664 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/xcode_writer.h"
-
-#include <iomanip>
-#include <map>
-#include <memory>
-#include <sstream>
-#include <string>
-#include <utility>
-
-#include "base/environment.h"
-#include "base/logging.h"
-#include "base/sha1.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "tools/gn/args.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/builder.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/deps_iterator.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/target.h"
-#include "tools/gn/value.h"
-#include "tools/gn/variables.h"
-#include "tools/gn/xcode_object.h"
-
-namespace {
-
-using TargetToFileList = std::unordered_map<const Target*, Target::FileList>;
-using TargetToTarget = std::unordered_map<const Target*, const Target*>;
-using TargetToPBXTarget = std::unordered_map<const Target*, PBXTarget*>;
-
-const char* kXCTestFileSuffixes[] = {
- "egtest.m", "egtest.mm", "xctest.m", "xctest.mm",
-};
-
-const char kXCTestModuleTargetNamePostfix[] = "_module";
-const char kXCUITestRunnerTargetNamePostfix[] = "_runner";
-
-struct SafeEnvironmentVariableInfo {
- const char* name;
- bool capture_at_generation;
-};
-
-SafeEnvironmentVariableInfo kSafeEnvironmentVariables[] = {
- {"HOME", true},
- {"LANG", true},
- {"PATH", true},
- {"USER", true},
- {"TMPDIR", false},
- {"ICECC_VERSION", true},
- {"ICECC_CLANG_REMOTE_CPP", true}};
-
-XcodeWriter::TargetOsType GetTargetOs(const Args& args) {
- const Value* target_os_value = args.GetArgOverride(variables::kTargetOs);
- if (target_os_value) {
- if (target_os_value->type() == Value::STRING) {
- if (target_os_value->string_value() == "ios")
- return XcodeWriter::WRITER_TARGET_OS_IOS;
- }
- }
- return XcodeWriter::WRITER_TARGET_OS_MACOS;
-}
-
-std::string GetBuildScript(const std::string& target_name,
- const std::string& ninja_extra_args,
- base::Environment* environment) {
- std::stringstream script;
- script << "echo note: \"Compile and copy " << target_name << " via ninja\"\n"
- << "exec ";
-
- // Launch ninja with a sanitized environment (Xcode sets many environment
- // variable overridding settings, including the SDK, thus breaking hermetic
- // build).
- script << "env -i ";
- for (const auto& variable : kSafeEnvironmentVariables) {
- script << variable.name << "=\"";
-
- std::string value;
- if (variable.capture_at_generation)
- environment->GetVar(variable.name, &value);
-
- if (!value.empty())
- script << value;
- else
- script << "$" << variable.name;
- script << "\" ";
- }
-
- script << "ninja -C .";
- if (!ninja_extra_args.empty())
- script << " " << ninja_extra_args;
- if (!target_name.empty())
- script << " " << target_name;
- script << "\nexit 1\n";
- return script.str();
-}
-
-bool IsApplicationTarget(const Target* target) {
- return target->output_type() == Target::CREATE_BUNDLE &&
- target->bundle_data().product_type() ==
- "com.apple.product-type.application";
-}
-
-bool IsXCUITestRunnerTarget(const Target* target) {
- return IsApplicationTarget(target) &&
- base::EndsWith(target->label().name(),
- kXCUITestRunnerTargetNamePostfix,
- base::CompareCase::SENSITIVE);
-}
-
-bool IsXCTestModuleTarget(const Target* target) {
- return target->output_type() == Target::CREATE_BUNDLE &&
- target->bundle_data().product_type() ==
- "com.apple.product-type.bundle.unit-test" &&
- base::EndsWith(target->label().name(), kXCTestModuleTargetNamePostfix,
- base::CompareCase::SENSITIVE);
-}
-
-bool IsXCUITestModuleTarget(const Target* target) {
- return target->output_type() == Target::CREATE_BUNDLE &&
- target->bundle_data().product_type() ==
- "com.apple.product-type.bundle.ui-testing" &&
- base::EndsWith(target->label().name(), kXCTestModuleTargetNamePostfix,
- base::CompareCase::SENSITIVE);
-}
-
-bool IsXCTestFile(const SourceFile& file) {
- std::string file_name = file.GetName();
- for (size_t i = 0; i < arraysize(kXCTestFileSuffixes); ++i) {
- if (base::EndsWith(file_name, kXCTestFileSuffixes[i],
- base::CompareCase::SENSITIVE)) {
- return true;
- }
- }
-
- return false;
-}
-
-const Target* FindApplicationTargetByName(
- const std::string& target_name,
- const std::vector<const Target*>& targets) {
- for (const Target* target : targets) {
- if (target->label().name() == target_name) {
- DCHECK(IsApplicationTarget(target));
- return target;
- }
- }
- NOTREACHED();
- return nullptr;
-}
-
-// Adds |base_pbxtarget| as a dependency of |dependent_pbxtarget| in the
-// generated Xcode project.
-void AddPBXTargetDependency(const PBXTarget* base_pbxtarget,
- PBXTarget* dependent_pbxtarget,
- const PBXProject* project) {
- auto container_item_proxy =
- std::make_unique<PBXContainerItemProxy>(project, base_pbxtarget);
- auto dependency = std::make_unique<PBXTargetDependency>(
- base_pbxtarget, std::move(container_item_proxy));
-
- dependent_pbxtarget->AddDependency(std::move(dependency));
-}
-
-// Adds the corresponding test application target as dependency of xctest or
-// xcuitest module target in the generated Xcode project.
-void AddDependencyTargetForTestModuleTargets(
- const std::vector<const Target*>& targets,
- const TargetToPBXTarget& bundle_target_to_pbxtarget,
- const PBXProject* project) {
- for (const Target* target : targets) {
- if (!IsXCTestModuleTarget(target) && !IsXCUITestModuleTarget(target))
- continue;
-
- const Target* test_application_target = FindApplicationTargetByName(
- target->bundle_data().xcode_test_application_name(), targets);
- const PBXTarget* test_application_pbxtarget =
- bundle_target_to_pbxtarget.at(test_application_target);
- PBXTarget* module_pbxtarget = bundle_target_to_pbxtarget.at(target);
- DCHECK(test_application_pbxtarget);
- DCHECK(module_pbxtarget);
-
- AddPBXTargetDependency(test_application_pbxtarget, module_pbxtarget,
- project);
- }
-}
-
-// Searches the list of xctest files recursively under |target|.
-void SearchXCTestFilesForTarget(const Target* target,
- TargetToFileList* xctest_files_per_target) {
- // Early return if already visited and processed.
- if (xctest_files_per_target->find(target) != xctest_files_per_target->end())
- return;
-
- Target::FileList xctest_files;
- for (const SourceFile& file : target->sources()) {
- if (IsXCTestFile(file)) {
- xctest_files.push_back(file);
- }
- }
-
- // Call recursively on public and private deps.
- for (const auto& t : target->public_deps()) {
- SearchXCTestFilesForTarget(t.ptr, xctest_files_per_target);
- const Target::FileList& deps_xctest_files =
- (*xctest_files_per_target)[t.ptr];
- xctest_files.insert(xctest_files.end(), deps_xctest_files.begin(),
- deps_xctest_files.end());
- }
-
- for (const auto& t : target->private_deps()) {
- SearchXCTestFilesForTarget(t.ptr, xctest_files_per_target);
- const Target::FileList& deps_xctest_files =
- (*xctest_files_per_target)[t.ptr];
- xctest_files.insert(xctest_files.end(), deps_xctest_files.begin(),
- deps_xctest_files.end());
- }
-
- // Sort xctest_files to remove duplicates.
- std::sort(xctest_files.begin(), xctest_files.end());
- xctest_files.erase(std::unique(xctest_files.begin(), xctest_files.end()),
- xctest_files.end());
-
- xctest_files_per_target->insert(std::make_pair(target, xctest_files));
-}
-
-// Add all source files for indexing, both private and public.
-void AddSourceFilesToProjectForIndexing(
- const std::vector<const Target*>& targets,
- PBXProject* project,
- SourceDir source_dir,
- const BuildSettings* build_settings) {
- std::vector<SourceFile> sources;
- for (const Target* target : targets) {
- for (const SourceFile& source : target->sources()) {
- if (IsStringInOutputDir(build_settings->build_dir(), source.value()))
- continue;
-
- sources.push_back(source);
- }
-
- if (target->all_headers_public())
- continue;
-
- for (const SourceFile& source : target->public_headers()) {
- if (IsStringInOutputDir(build_settings->build_dir(), source.value()))
- continue;
-
- sources.push_back(source);
- }
- }
-
- // Sort sources to ensure determinism of the project file generation and
- // remove duplicate reference to the source files (can happen due to the
- // bundle_data targets).
- std::sort(sources.begin(), sources.end());
- sources.erase(std::unique(sources.begin(), sources.end()), sources.end());
-
- for (const SourceFile& source : sources) {
- std::string source_file = RebasePath(source.value(), source_dir,
- build_settings->root_path_utf8());
- project->AddSourceFileToIndexingTarget(source_file, source_file,
- CompilerFlags::NONE);
- }
-}
-
-// Add xctest files to the "Compiler Sources" of corresponding test module
-// native targets.
-void AddXCTestFilesToTestModuleTarget(const Target::FileList& xctest_file_list,
- PBXNativeTarget* native_target,
- PBXProject* project,
- SourceDir source_dir,
- const BuildSettings* build_settings) {
- for (const SourceFile& source : xctest_file_list) {
- std::string source_path = RebasePath(source.value(), source_dir,
- build_settings->root_path_utf8());
-
- // Test files need to be known to Xcode for proper indexing and for
- // discovery of tests function for XCTest and XCUITest, but the compilation
- // is done via ninja and thus must prevent Xcode from compiling the files by
- // adding '-help' as per file compiler flag.
- project->AddSourceFile(source_path, source_path, CompilerFlags::HELP,
- native_target);
- }
-}
-
-class CollectPBXObjectsPerClassHelper : public PBXObjectVisitor {
- public:
- CollectPBXObjectsPerClassHelper() = default;
-
- void Visit(PBXObject* object) override {
- DCHECK(object);
- objects_per_class_[object->Class()].push_back(object);
- }
-
- const std::map<PBXObjectClass, std::vector<const PBXObject*>>&
- objects_per_class() const {
- return objects_per_class_;
- }
-
- private:
- std::map<PBXObjectClass, std::vector<const PBXObject*>> objects_per_class_;
-
- DISALLOW_COPY_AND_ASSIGN(CollectPBXObjectsPerClassHelper);
-};
-
-std::map<PBXObjectClass, std::vector<const PBXObject*>>
-CollectPBXObjectsPerClass(PBXProject* project) {
- CollectPBXObjectsPerClassHelper visitor;
- project->Visit(visitor);
- return visitor.objects_per_class();
-}
-
-class RecursivelyAssignIdsHelper : public PBXObjectVisitor {
- public:
- RecursivelyAssignIdsHelper(const std::string& seed)
- : seed_(seed), counter_(0) {}
-
- void Visit(PBXObject* object) override {
- std::stringstream buffer;
- buffer << seed_ << " " << object->Name() << " " << counter_;
- std::string hash = base::SHA1HashString(buffer.str());
- DCHECK_EQ(hash.size() % 4, 0u);
-
- uint32_t id[3] = {0, 0, 0};
- const uint32_t* ptr = reinterpret_cast<const uint32_t*>(hash.data());
- for (size_t i = 0; i < hash.size() / 4; i++)
- id[i % 3] ^= ptr[i];
-
- object->SetId(base::HexEncode(id, sizeof(id)));
- ++counter_;
- }
-
- private:
- std::string seed_;
- int64_t counter_;
-
- DISALLOW_COPY_AND_ASSIGN(RecursivelyAssignIdsHelper);
-};
-
-void RecursivelyAssignIds(PBXProject* project) {
- RecursivelyAssignIdsHelper visitor(project->Name());
- project->Visit(visitor);
-}
-
-} // namespace
-
-// static
-bool XcodeWriter::RunAndWriteFiles(const std::string& workspace_name,
- const std::string& root_target_name,
- const std::string& ninja_extra_args,
- const std::string& dir_filters_string,
- const BuildSettings* build_settings,
- const Builder& builder,
- Err* err) {
- const XcodeWriter::TargetOsType target_os =
- GetTargetOs(build_settings->build_args());
-
- PBXAttributes attributes;
- switch (target_os) {
- case XcodeWriter::WRITER_TARGET_OS_IOS:
- attributes["SDKROOT"] = "iphoneos";
- attributes["TARGETED_DEVICE_FAMILY"] = "1,2";
- break;
- case XcodeWriter::WRITER_TARGET_OS_MACOS:
- attributes["SDKROOT"] = "macosx";
- break;
- }
-
- const std::string source_path =
- base::FilePath::FromUTF8Unsafe(
- RebasePath("//", build_settings->build_dir()))
- .StripTrailingSeparators()
- .AsUTF8Unsafe();
-
- std::string config_name = build_settings->build_dir()
- .Resolve(base::FilePath())
- .StripTrailingSeparators()
- .BaseName()
- .AsUTF8Unsafe();
- DCHECK(!config_name.empty());
-
- std::string::size_type separator = config_name.find('-');
- if (separator != std::string::npos)
- config_name = config_name.substr(0, separator);
-
- std::vector<const Target*> targets;
- std::vector<const Target*> all_targets = builder.GetAllResolvedTargets();
- if (!XcodeWriter::FilterTargets(build_settings, all_targets,
- dir_filters_string, &targets, err)) {
- return false;
- }
-
- XcodeWriter workspace(workspace_name);
- workspace.CreateProductsProject(targets, all_targets, attributes, source_path,
- config_name, root_target_name,
- ninja_extra_args, build_settings, target_os);
-
- return workspace.WriteFiles(build_settings, err);
-}
-
-XcodeWriter::XcodeWriter(const std::string& name) : name_(name) {
- if (name_.empty())
- name_.assign("all");
-}
-
-XcodeWriter::~XcodeWriter() = default;
-
-// static
-bool XcodeWriter::FilterTargets(const BuildSettings* build_settings,
- const std::vector<const Target*>& all_targets,
- const std::string& dir_filters_string,
- std::vector<const Target*>* targets,
- Err* err) {
- // Filter targets according to the semicolon-delimited list of label patterns,
- // if defined, first.
- targets->reserve(all_targets.size());
- if (dir_filters_string.empty()) {
- *targets = all_targets;
- } else {
- std::vector<LabelPattern> filters;
- if (!commands::FilterPatternsFromString(build_settings, dir_filters_string,
- &filters, err)) {
- return false;
- }
-
- commands::FilterTargetsByPatterns(all_targets, filters, targets);
- }
-
- // Filter out all target of type EXECUTABLE that are direct dependency of
- // a BUNDLE_DATA target (under the assumption that they will be part of a
- // CREATE_BUNDLE target generating an application bundle). Sort the list
- // of targets per pointer to use binary search for the removal.
- std::sort(targets->begin(), targets->end());
-
- for (const Target* target : all_targets) {
- if (!target->settings()->is_default())
- continue;
-
- if (target->output_type() != Target::BUNDLE_DATA)
- continue;
-
- for (const auto& pair : target->GetDeps(Target::DEPS_LINKED)) {
- if (pair.ptr->output_type() != Target::EXECUTABLE)
- continue;
-
- auto iter = std::lower_bound(targets->begin(), targets->end(), pair.ptr);
- if (iter != targets->end() && *iter == pair.ptr)
- targets->erase(iter);
- }
- }
-
- // Sort the list of targets per-label to get a consistent ordering of them
- // in the generated Xcode project (and thus stability of the file generated).
- std::sort(targets->begin(), targets->end(),
- [](const Target* a, const Target* b) {
- return a->label().name() < b->label().name();
- });
-
- return true;
-}
-
-void XcodeWriter::CreateProductsProject(
- const std::vector<const Target*>& targets,
- const std::vector<const Target*>& all_targets,
- const PBXAttributes& attributes,
- const std::string& source_path,
- const std::string& config_name,
- const std::string& root_target,
- const std::string& ninja_extra_args,
- const BuildSettings* build_settings,
- TargetOsType target_os) {
- std::unique_ptr<PBXProject> main_project(
- new PBXProject("products", config_name, source_path, attributes));
-
- std::vector<const Target*> bundle_targets;
- TargetToPBXTarget bundle_target_to_pbxtarget;
-
- std::string build_path;
- std::unique_ptr<base::Environment> env(base::Environment::Create());
- SourceDir source_dir("//");
- AddSourceFilesToProjectForIndexing(all_targets, main_project.get(),
- source_dir, build_settings);
- main_project->AddAggregateTarget(
- "All", GetBuildScript(root_target, ninja_extra_args, env.get()));
-
- // Needs to search for xctest files under the application targets, and this
- // variable is used to store the results of visited targets, thus making the
- // search more efficient.
- TargetToFileList xctest_files_per_target;
-
- for (const Target* target : targets) {
- switch (target->output_type()) {
- case Target::EXECUTABLE:
- if (target_os == XcodeWriter::WRITER_TARGET_OS_IOS)
- continue;
-
- main_project->AddNativeTarget(
- target->label().name(), "compiled.mach-o.executable",
- target->output_name().empty() ? target->label().name()
- : target->output_name(),
- "com.apple.product-type.tool",
- GetBuildScript(target->label().name(), ninja_extra_args,
- env.get()));
- break;
-
- case Target::CREATE_BUNDLE: {
- if (target->bundle_data().product_type().empty())
- continue;
-
- // For XCUITest, two CREATE_BUNDLE targets are generated:
- // ${target_name}_runner and ${target_name}_module, however, Xcode
- // requires only one target named ${target_name} to run tests.
- if (IsXCUITestRunnerTarget(target))
- continue;
- std::string pbxtarget_name = target->label().name();
- if (IsXCUITestModuleTarget(target)) {
- std::string target_name = target->label().name();
- pbxtarget_name = target_name.substr(
- 0, target_name.rfind(kXCTestModuleTargetNamePostfix));
- }
-
- PBXAttributes xcode_extra_attributes =
- target->bundle_data().xcode_extra_attributes();
-
- const std::string& target_output_name =
- RebasePath(target->bundle_data()
- .GetBundleRootDirOutput(target->settings())
- .value(),
- build_settings->build_dir());
- PBXNativeTarget* native_target = main_project->AddNativeTarget(
- pbxtarget_name, std::string(), target_output_name,
- target->bundle_data().product_type(),
- GetBuildScript(pbxtarget_name, ninja_extra_args, env.get()),
- xcode_extra_attributes);
-
- bundle_targets.push_back(target);
- bundle_target_to_pbxtarget.insert(
- std::make_pair(target, native_target));
-
- if (!IsXCTestModuleTarget(target) && !IsXCUITestModuleTarget(target))
- continue;
-
- // For XCTest, test files are compiled into the application bundle.
- // For XCUITest, test files are compiled into the test module bundle.
- const Target* target_with_xctest_files = nullptr;
- if (IsXCTestModuleTarget(target)) {
- target_with_xctest_files = FindApplicationTargetByName(
- target->bundle_data().xcode_test_application_name(), targets);
- } else if (IsXCUITestModuleTarget(target)) {
- target_with_xctest_files = target;
- } else {
- NOTREACHED();
- }
-
- SearchXCTestFilesForTarget(target_with_xctest_files,
- &xctest_files_per_target);
- const Target::FileList& xctest_file_list =
- xctest_files_per_target[target_with_xctest_files];
-
- // Add xctest files to the "Compiler Sources" of corresponding xctest
- // and xcuitest native targets for proper indexing and for discovery of
- // tests function.
- AddXCTestFilesToTestModuleTarget(xctest_file_list, native_target,
- main_project.get(), source_dir,
- build_settings);
- break;
- }
-
- default:
- break;
- }
- }
-
- // Adding the corresponding test application target as a dependency of xctest
- // or xcuitest module target in the generated Xcode project so that the
- // application target is re-compiled when compiling the test module target.
- AddDependencyTargetForTestModuleTargets(
- bundle_targets, bundle_target_to_pbxtarget, main_project.get());
-
- projects_.push_back(std::move(main_project));
-}
-
-bool XcodeWriter::WriteFiles(const BuildSettings* build_settings, Err* err) {
- for (const auto& project : projects_) {
- if (!WriteProjectFile(build_settings, project.get(), err))
- return false;
- }
-
- SourceFile xcworkspacedata_file =
- build_settings->build_dir().ResolveRelativeFile(
- Value(nullptr, name_ + ".xcworkspace/contents.xcworkspacedata"), err);
- if (xcworkspacedata_file.is_null())
- return false;
-
- std::stringstream xcworkspacedata_string_out;
- WriteWorkspaceContent(xcworkspacedata_string_out);
-
- return WriteFileIfChanged(build_settings->GetFullPath(xcworkspacedata_file),
- xcworkspacedata_string_out.str(), err);
-}
-
-bool XcodeWriter::WriteProjectFile(const BuildSettings* build_settings,
- PBXProject* project,
- Err* err) {
- SourceFile pbxproj_file = build_settings->build_dir().ResolveRelativeFile(
- Value(nullptr, project->Name() + ".xcodeproj/project.pbxproj"), err);
- if (pbxproj_file.is_null())
- return false;
-
- std::stringstream pbxproj_string_out;
- WriteProjectContent(pbxproj_string_out, project);
-
- if (!WriteFileIfChanged(build_settings->GetFullPath(pbxproj_file),
- pbxproj_string_out.str(), err))
- return false;
-
- return true;
-}
-
-void XcodeWriter::WriteWorkspaceContent(std::ostream& out) {
- out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- << "<Workspace version = \"1.0\">\n";
- for (const auto& project : projects_) {
- out << " <FileRef location = \"group:" << project->Name()
- << ".xcodeproj\"></FileRef>\n";
- }
- out << "</Workspace>\n";
-}
-
-void XcodeWriter::WriteProjectContent(std::ostream& out, PBXProject* project) {
- RecursivelyAssignIds(project);
-
- out << "// !$*UTF8*$!\n"
- << "{\n"
- << "\tarchiveVersion = 1;\n"
- << "\tclasses = {\n"
- << "\t};\n"
- << "\tobjectVersion = 46;\n"
- << "\tobjects = {\n";
-
- for (auto& pair : CollectPBXObjectsPerClass(project)) {
- out << "\n"
- << "/* Begin " << ToString(pair.first) << " section */\n";
- std::sort(pair.second.begin(), pair.second.end(),
- [](const PBXObject* a, const PBXObject* b) {
- return a->id() < b->id();
- });
- for (auto* object : pair.second) {
- object->Print(out, 2);
- }
- out << "/* End " << ToString(pair.first) << " section */\n";
- }
-
- out << "\t};\n"
- << "\trootObject = " << project->Reference() << ";\n"
- << "}\n";
-}
diff --git a/chromium/tools/gn/xcode_writer.h b/chromium/tools/gn/xcode_writer.h
deleted file mode 100644
index 24953dcb9cd..00000000000
--- a/chromium/tools/gn/xcode_writer.h
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_XCODE_WRITER_H_
-#define TOOLS_GN_XCODE_WRITER_H_
-
-#include <iosfwd>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-
-class Builder;
-class BuildSettings;
-class Err;
-class Target;
-
-using PBXAttributes = std::map<std::string, std::string>;
-class PBXProject;
-
-class XcodeWriter {
- public:
- enum TargetOsType {
- WRITER_TARGET_OS_IOS,
- WRITER_TARGET_OS_MACOS,
- };
-
- // Writes Xcode workspace and project files.
- //
- // |workspace_name| is the optional name of the workspace file name ("all"
- // is used if not specified). |root_target_name| is the name of the main
- // target corresponding to building "All" (for example "gn_all" in Chromium).
- // |ninja_extra_args| are additional arguments to pass to ninja invocation
- // (can be used to increase limit of concurrent processes when using goma).
- // |dir_filters_string| is optional semicolon-separated list of label patterns
- // used to limit the set of generated projects. Only matching targets will be
- // included to the workspace. On failure will populate |err| and return false.
- static bool RunAndWriteFiles(const std::string& workspace_name,
- const std::string& root_target_name,
- const std::string& ninja_extra_args,
- const std::string& dir_filters_string,
- const BuildSettings* build_settings,
- const Builder& builder,
- Err* err);
-
- private:
- XcodeWriter(const std::string& name);
- ~XcodeWriter();
-
- // Filters the list of targets to only return the targets with artifacts
- // usable from Xcode (mostly application bundles). On failure populate |err|
- // and return false.
- static bool FilterTargets(const BuildSettings* build_settings,
- const std::vector<const Target*>& all_targets,
- const std::string& dir_filters_string,
- std::vector<const Target*>* targets,
- Err* err);
-
- // Generate the "products.xcodeproj" project that reference all products
- // (i.e. targets that have a build artefact usable from Xcode, mostly
- // application bundles).
- void CreateProductsProject(const std::vector<const Target*>& targets,
- const std::vector<const Target*>& all_targets,
- const PBXAttributes& attributes,
- const std::string& source_path,
- const std::string& config_name,
- const std::string& root_target,
- const std::string& ninja_extra_args,
- const BuildSettings* build_settings,
- TargetOsType target_os);
-
- bool WriteFiles(const BuildSettings* build_settings, Err* err);
- bool WriteProjectFile(const BuildSettings* build_settings,
- PBXProject* project,
- Err* err);
-
- void WriteWorkspaceContent(std::ostream& out);
- void WriteProjectContent(std::ostream& out, PBXProject* project);
-
- std::string name_;
- std::vector<std::unique_ptr<PBXProject>> projects_;
-
- DISALLOW_COPY_AND_ASSIGN(XcodeWriter);
-};
-
-#endif // TOOLS_GN_XCODE_WRITER_H_
diff --git a/chromium/tools/gn/xml_element_writer.cc b/chromium/tools/gn/xml_element_writer.cc
deleted file mode 100644
index 360d8af18d5..00000000000
--- a/chromium/tools/gn/xml_element_writer.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/xml_element_writer.h"
-
-#include <memory>
-
-XmlAttributes::XmlAttributes() = default;
-
-XmlAttributes::XmlAttributes(const base::StringPiece& attr_key,
- const base::StringPiece& attr_value) {
- add(attr_key, attr_value);
-}
-
-XmlAttributes& XmlAttributes::add(const base::StringPiece& attr_key,
- const base::StringPiece& attr_value) {
- push_back(std::make_pair(attr_key, attr_value));
- return *this;
-}
-
-XmlElementWriter::XmlElementWriter(std::ostream& out,
- const std::string& tag,
- const XmlAttributes& attributes)
- : XmlElementWriter(out, tag, attributes, 0) {}
-
-XmlElementWriter::XmlElementWriter(std::ostream& out,
- const std::string& tag,
- const XmlAttributes& attributes,
- int indent)
- : out_(out),
- tag_(tag),
- indent_(indent),
- opening_tag_finished_(false),
- one_line_(true) {
- out << std::string(indent, ' ') << '<' << tag;
- for (auto attribute : attributes)
- out << ' ' << attribute.first << "=\"" << attribute.second << '"';
-}
-
-XmlElementWriter::~XmlElementWriter() {
- if (!opening_tag_finished_) {
- // The XML spec does not require a space before the closing slash. However,
- // Eclipse is unable to parse XML settings files if there is no space.
- out_ << " />" << std::endl;
- } else {
- if (!one_line_)
- out_ << std::string(indent_, ' ');
- out_ << "</" << tag_ << '>' << std::endl;
- }
-}
-
-void XmlElementWriter::Text(const base::StringPiece& content) {
- StartContent(false);
- out_ << content;
-}
-
-std::unique_ptr<XmlElementWriter> XmlElementWriter::SubElement(
- const std::string& tag) {
- return SubElement(tag, XmlAttributes());
-}
-
-std::unique_ptr<XmlElementWriter> XmlElementWriter::SubElement(
- const std::string& tag,
- const XmlAttributes& attributes) {
- StartContent(true);
- return std::make_unique<XmlElementWriter>(out_, tag, attributes, indent_ + 2);
-}
-
-std::ostream& XmlElementWriter::StartContent(bool start_new_line) {
- if (!opening_tag_finished_) {
- out_ << '>';
- opening_tag_finished_ = true;
-
- if (start_new_line && one_line_) {
- out_ << std::endl;
- one_line_ = false;
- }
- }
-
- return out_;
-}
-
-std::string XmlEscape(const std::string& value) {
- std::string result;
- for (char c : value) {
- switch (c) {
- case '\n':
- result += "&#10;";
- break;
- case '\r':
- result += "&#13;";
- break;
- case '\t':
- result += "&#9;";
- break;
- case '"':
- result += "&quot;";
- break;
- case '<':
- result += "&lt;";
- break;
- case '>':
- result += "&gt;";
- break;
- case '&':
- result += "&amp;";
- break;
- default:
- result += c;
- }
- }
- return result;
-}
diff --git a/chromium/tools/gn/xml_element_writer.h b/chromium/tools/gn/xml_element_writer.h
deleted file mode 100644
index 4aa5f7e34a4..00000000000
--- a/chromium/tools/gn/xml_element_writer.h
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_XML_ELEMENT_WRITER_H_
-#define TOOLS_GN_XML_ELEMENT_WRITER_H_
-
-#include <iosfwd>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-
-// Vector of XML attribute key-value pairs.
-class XmlAttributes
- : public std::vector<std::pair<base::StringPiece, base::StringPiece>> {
- public:
- XmlAttributes();
- XmlAttributes(const base::StringPiece& attr_key,
- const base::StringPiece& attr_value);
-
- XmlAttributes& add(const base::StringPiece& attr_key,
- const base::StringPiece& attr_value);
-};
-
-// Helper class for writing XML elements. New XML element is started in
-// XmlElementWriter constructor and ended in its destructor. XmlElementWriter
-// handles XML file formatting in order to produce human-readable document.
-class XmlElementWriter {
- public:
- // Starts new XML element. This constructor adds no indentation and is
- // designed for XML root element.
- XmlElementWriter(std::ostream& out,
- const std::string& tag,
- const XmlAttributes& attributes);
- // Starts new XML element with specified indentation.
- XmlElementWriter(std::ostream& out,
- const std::string& tag,
- const XmlAttributes& attributes,
- int indent);
- // Starts new XML element with specified indentation. Specialized constructor
- // that allows writting XML element with single attribute without copying
- // attribute value.
- template <class Writer>
- XmlElementWriter(std::ostream& out,
- const std::string& tag,
- const std::string& attribute_name,
- const Writer& attribute_value_writer,
- int indent);
- // Ends XML element. All sub-elements should be ended at this point.
- ~XmlElementWriter();
-
- // Writes arbitrary XML element text.
- void Text(const base::StringPiece& content);
-
- // Starts new XML sub-element. Caller must ensure that parent element outlives
- // its children.
- std::unique_ptr<XmlElementWriter> SubElement(const std::string& tag);
- std::unique_ptr<XmlElementWriter> SubElement(const std::string& tag,
- const XmlAttributes& attributes);
- template <class Writer>
- std::unique_ptr<XmlElementWriter> SubElement(
- const std::string& tag,
- const std::string& attribute_name,
- const Writer& attribute_value_writer);
-
- // Finishes opening tag if it isn't finished yet and optionally starts new
- // document line. Returns the stream where XML element content can be written.
- // This is an alternative to Text() and SubElement() methods.
- std::ostream& StartContent(bool start_new_line);
-
- private:
- // Output stream. XmlElementWriter objects for XML element and its
- // sub-elements share the same output stream.
- std::ostream& out_;
-
- // XML element tag name.
- std::string tag_;
-
- // XML element indentation in the document.
- int indent_;
-
- // Flag indicating if opening tag is finished with '>' character already.
- bool opening_tag_finished_;
-
- // Flag indicating if XML element should be written in one document line.
- bool one_line_;
-
- DISALLOW_COPY_AND_ASSIGN(XmlElementWriter);
-};
-
-template <class Writer>
-XmlElementWriter::XmlElementWriter(std::ostream& out,
- const std::string& tag,
- const std::string& attribute_name,
- const Writer& attribute_value_writer,
- int indent)
- : out_(out),
- tag_(tag),
- indent_(indent),
- opening_tag_finished_(false),
- one_line_(true) {
- out << std::string(indent, ' ') << '<' << tag;
- out << ' ' << attribute_name << "=\"";
- attribute_value_writer(out);
- out << '\"';
-}
-
-template <class Writer>
-std::unique_ptr<XmlElementWriter> XmlElementWriter::SubElement(
- const std::string& tag,
- const std::string& attribute_name,
- const Writer& attribute_value_writer) {
- StartContent(true);
- return std::make_unique<XmlElementWriter>(
- out_, tag, attribute_name, attribute_value_writer, indent_ + 2);
-}
-
-std::string XmlEscape(const std::string& value);
-
-#endif // TOOLS_GN_XML_ELEMENT_WRITER_H_
diff --git a/chromium/tools/gn/xml_element_writer_unittest.cc b/chromium/tools/gn/xml_element_writer_unittest.cc
deleted file mode 100644
index cc21c4bb66c..00000000000
--- a/chromium/tools/gn/xml_element_writer_unittest.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/xml_element_writer.h"
-
-#include <sstream>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-class MockValueWriter {
- public:
- explicit MockValueWriter(const std::string& value) : value_(value) {}
- void operator()(std::ostream& out) const { out << value_; }
-
- private:
- std::string value_;
-};
-
-} // namespace
-
-TEST(XmlElementWriter, EmptyElement) {
- std::ostringstream out;
- { XmlElementWriter writer(out, "foo", XmlAttributes()); }
- EXPECT_EQ("<foo />\n", out.str());
-
- std::ostringstream out_attr;
- {
- XmlElementWriter writer(out_attr, "foo",
- XmlAttributes("bar", "abc").add("baz", "123"));
- }
- EXPECT_EQ("<foo bar=\"abc\" baz=\"123\" />\n", out_attr.str());
-
- std::ostringstream out_indent;
- {
- XmlElementWriter writer(out_indent, "foo", XmlAttributes("bar", "baz"), 2);
- }
- EXPECT_EQ(" <foo bar=\"baz\" />\n", out_indent.str());
-
- std::ostringstream out_writer;
- {
- XmlElementWriter writer(out_writer, "foo", "bar", MockValueWriter("baz"),
- 2);
- }
- EXPECT_EQ(" <foo bar=\"baz\" />\n", out_writer.str());
-}
-
-TEST(XmlElementWriter, ElementWithText) {
- std::ostringstream out;
- {
- XmlElementWriter writer(out, "foo", XmlAttributes("bar", "baz"));
- writer.Text("Hello world!");
- }
- EXPECT_EQ("<foo bar=\"baz\">Hello world!</foo>\n", out.str());
-}
-
-TEST(XmlElementWriter, SubElements) {
- std::ostringstream out;
- {
- XmlElementWriter writer(out, "root", XmlAttributes("aaa", "000"));
- writer.SubElement("foo", XmlAttributes());
- writer.SubElement("bar", XmlAttributes("bbb", "111"))->Text("hello");
- writer.SubElement("baz", "ccc", MockValueWriter("222"))
- ->SubElement("grandchild");
- }
- std::string expected =
- "<root aaa=\"000\">\n"
- " <foo />\n"
- " <bar bbb=\"111\">hello</bar>\n"
- " <baz ccc=\"222\">\n"
- " <grandchild />\n"
- " </baz>\n"
- "</root>\n";
- EXPECT_EQ(expected, out.str());
-}
-
-TEST(XmlElementWriter, StartContent) {
- std::ostringstream out;
- {
- XmlElementWriter writer(out, "foo", XmlAttributes("bar", "baz"));
- writer.StartContent(false) << "Hello world!";
- }
- EXPECT_EQ("<foo bar=\"baz\">Hello world!</foo>\n", out.str());
-}
-
-TEST(XmlElementWriter, TestXmlEscape) {
- std::string input = "\r \n \t & < > \"";
- std::string output = XmlEscape(input);
- std::string expected = "&#13; &#10; &#9; &amp; &lt; &gt; &quot;";
- EXPECT_EQ(expected, output);
-}
diff --git a/chromium/tools/grit/grit/format/chrome_messages_json.py b/chromium/tools/grit/grit/format/chrome_messages_json.py
index 4c701c67fa6..27a9da1c5f0 100644
--- a/chromium/tools/grit/grit/format/chrome_messages_json.py
+++ b/chromium/tools/grit/grit/format/chrome_messages_json.py
@@ -17,7 +17,7 @@ def Format(root, lang='en', output_dir='.'):
"""Format the messages as JSON."""
yield '{\n'
- encoder = JSONEncoder();
+ encoder = JSONEncoder(ensure_ascii=False)
format = (' "%s": {\n'
' "message": %s%s\n'
' }')
diff --git a/chromium/tools/grit/grit/format/chrome_messages_json_unittest.py b/chromium/tools/grit/grit/format/chrome_messages_json_unittest.py
index 0a3ae2e940c..cf6de6c77be 100755
--- a/chromium/tools/grit/grit/format/chrome_messages_json_unittest.py
+++ b/chromium/tools/grit/grit/format/chrome_messages_json_unittest.py
@@ -63,7 +63,7 @@ class ChromeMessagesJsonFormatUnittest(unittest.TestCase):
"message": "Simple message."
},
"QUOTES": {
- "message": "element\\u2019s \\u201c%s\\u201d attribute"
+ "message": "element\u2019s \u201c%s\u201d attribute"
},
"PLACEHOLDERS": {
"message": "%1$d error, %2$d warning"
@@ -114,10 +114,10 @@ class ChromeMessagesJsonFormatUnittest(unittest.TestCase):
test = u"""
{
"ID_HELLO": {
- "message": "H\\u00e9P\\u00e9ll\\u00f4P\\u00f4!"
+ "message": "H\u00e9P\u00e9ll\u00f4P\u00f4!"
},
"ID_HELLO_USER": {
- "message": "H\\u00e9P\\u00e9ll\\u00f4P\\u00f4 %s"
+ "message": "H\u00e9P\u00e9ll\u00f4P\u00f4 %s"
}
}
"""
diff --git a/chromium/tools/grit/grit/format/html_inline.py b/chromium/tools/grit/grit/format/html_inline.py
index 3c8e21be466..d777019e54a 100755
--- a/chromium/tools/grit/grit/format/html_inline.py
+++ b/chromium/tools/grit/grit/format/html_inline.py
@@ -28,6 +28,9 @@ from grit.format import minifier
mimetypes.init([])
mimetypes.add_type('image/svg+xml', '.svg')
+# webm video type is not always available if mimetype package is outdated.
+mimetypes.add_type('video/webm', '.webm')
+
DIST_DEFAULT = 'chromium'
DIST_ENV_VAR = 'CHROMIUM_BUILD'
DIST_SUBSTR = '%DISTRIBUTION%'
@@ -367,6 +370,7 @@ def DoInline(
if names_only:
inlined_files.update(GetResourceFilenames(
filepath,
+ grd_node,
allow_external_script,
rewrite_function,
filename_expansion_function=filename_expansion_function))
@@ -555,6 +559,7 @@ def InlineToFile(input_filename, output_filename, grd_node):
def GetResourceFilenames(filename,
+ grd_node,
allow_external_script=False,
rewrite_function=None,
filename_expansion_function=None):
@@ -562,7 +567,7 @@ def GetResourceFilenames(filename,
try:
return DoInline(
filename,
- None,
+ grd_node,
names_only=True,
preprocess_only=False,
allow_external_script=allow_external_script,
diff --git a/chromium/tools/grit/grit/format/html_inline_unittest.py b/chromium/tools/grit/grit/format/html_inline_unittest.py
index 062296c9187..5040fa38ee2 100755
--- a/chromium/tools/grit/grit/format/html_inline_unittest.py
+++ b/chromium/tools/grit/grit/format/html_inline_unittest.py
@@ -75,7 +75,8 @@ class HtmlInlineUnittest(unittest.TestCase):
for filename in files:
source_resources.add(tmp_dir.GetPath(filename))
- resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'))
+ resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'),
+ None)
resources.add(tmp_dir.GetPath('index.html'))
self.failUnlessEqual(resources, source_resources)
tmp_dir.CleanUp()
@@ -101,7 +102,7 @@ class HtmlInlineUnittest(unittest.TestCase):
tmp_dir = util.TempDir(files)
with self.assertRaises(Exception) as cm:
- html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'))
+ html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'), None)
self.failUnlessEqual(cm.exception.message, 'Unmatched </if>')
tmp_dir.CleanUp()
@@ -119,7 +120,8 @@ class HtmlInlineUnittest(unittest.TestCase):
for filename in files:
source_resources.add(tmp_dir.GetPath(filename))
- resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.js'))
+ resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.js'),
+ None)
resources.add(tmp_dir.GetPath('index.js'))
self.failUnlessEqual(resources, source_resources)
tmp_dir.CleanUp()
@@ -266,7 +268,8 @@ class HtmlInlineUnittest(unittest.TestCase):
for filename in files:
source_resources.add(tmp_dir.GetPath(filename))
- resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'))
+ resources = html_inline.GetResourceFilenames(tmp_dir.GetPath('index.html'),
+ None)
resources.add(tmp_dir.GetPath('index.html'))
self.failUnlessEqual(resources, source_resources)
tmp_dir.CleanUp()
@@ -560,6 +563,82 @@ class HtmlInlineUnittest(unittest.TestCase):
self.failUnlessEqual(expected_inlined,
util.FixLineEnd(result.inlined_data, '\n'))
+ def testConditionalInclude(self):
+ '''Tests that output and dependency generation includes only files not'''\
+ ''' blocked by <if> macros.'''
+
+ files = {
+ 'index.html': '''
+ <html>
+ <if expr="True">
+ <img src="img1.png" srcset="img2.png 1x, img3.png 2x">
+ </if>
+ <if expr="False">
+ <img src="img4.png" srcset=" img5.png 1x, img6.png 2x ">
+ </if>
+ <if expr="True">
+ <img src="chrome://theme/img11.png" srcset="img7.png 1x, '''\
+ '''chrome://theme/img13.png 2x">
+ </if>
+ <img srcset="img8.png 300w, img9.png 11E-2w,img10.png -1e2w">
+ </html>
+ ''',
+ 'img1.png': '''a1''',
+ 'img2.png': '''a2''',
+ 'img3.png': '''a3''',
+ 'img4.png': '''a4''',
+ 'img5.png': '''a5''',
+ 'img6.png': '''a6''',
+ 'img7.png': '''a7''',
+ 'img8.png': '''a8''',
+ 'img9.png': '''a9''',
+ 'img10.png': '''a10''',
+ }
+
+ expected_inlined = '''
+ <html>
+ <img src="data:image/png;base64,YTE=" srcset="data:image/png;base64,'''\
+ '''YTI= 1x,data:image/png;base64,YTM= 2x">
+ <img src="chrome://theme/img11.png" srcset="data:image/png;base64,'''\
+ '''YTc= 1x,chrome://theme/img13.png 2x">
+ <img srcset="data:image/png;base64,YTg= 300w,data:image/png;base64,'''\
+ '''YTk= 11E-2w,data:image/png;base64,YTEw -1e2w">
+ </html>
+ '''
+
+ expected_files = [
+ 'index.html',
+ 'img1.png',
+ 'img2.png',
+ 'img3.png',
+ 'img7.png',
+ 'img8.png',
+ 'img9.png',
+ 'img10.png'
+ ]
+
+ source_resources = set()
+ tmp_dir = util.TempDir(files)
+ for filename in expected_files:
+ source_resources.add(tmp_dir.GetPath(filename))
+
+ class FakeGrdNode(object):
+ def EvaluateCondition(self, cond):
+ return eval(cond)
+
+ # Test normal inlining.
+ result = html_inline.DoInline(
+ tmp_dir.GetPath('index.html'),
+ FakeGrdNode())
+ resources = result.inlined_files
+ resources.add(tmp_dir.GetPath('index.html'))
+ self.failUnlessEqual(resources, source_resources)
+
+ # ignore whitespace
+ expected_inlined = re.sub(r'\s+', ' ', expected_inlined)
+ actually_inlined = re.sub(r'\s+', ' ',
+ util.FixLineEnd(result.inlined_data, '\n'))
+ self.failUnlessEqual(expected_inlined, actually_inlined);
if __name__ == '__main__':
unittest.main()
diff --git a/chromium/tools/grit/grit/gather/chrome_html.py b/chromium/tools/grit/grit/gather/chrome_html.py
index a2156478e60..a0bd999680e 100755
--- a/chromium/tools/grit/grit/gather/chrome_html.py
+++ b/chromium/tools/grit/grit/gather/chrome_html.py
@@ -320,6 +320,7 @@ class ChromeHtml(interface.GathererBase):
if self.flatten_html_:
return html_inline.GetResourceFilenames(
self.grd_node.ToRealPath(self.GetInputPath()),
+ self.grd_node,
allow_external_script=self.allow_external_script_,
rewrite_function=lambda fp, t, d: ProcessImageSets(
fp, t, self.scale_factors_, d,
diff --git a/chromium/tools/grit/grit/node/include.py b/chromium/tools/grit/grit/node/include.py
index 3538cc7bc7a..f7a51ed1270 100755
--- a/chromium/tools/grit/grit/node/include.py
+++ b/chromium/tools/grit/grit/node/include.py
@@ -116,6 +116,7 @@ class IncludeNode(base.Node):
allow_external_script = self.attrs['allowexternalscript'] == 'true'
return grit.format.html_inline.GetResourceFilenames(
self.ToRealPath(self.GetInputPath()),
+ self,
allow_external_script=allow_external_script)
def IsResourceMapSource(self):
diff --git a/chromium/tools/grit/grit/tool/build.py b/chromium/tools/grit/grit/tool/build.py
index 0f5b001045b..4eb18b3d49e 100755
--- a/chromium/tools/grit/grit/tool/build.py
+++ b/chromium/tools/grit/grit/tool/build.py
@@ -148,6 +148,7 @@ are exported to translation interchange files (e.g. XMB files), etc.
return 'A tool that builds RC files for compilation.'
def Run(self, opts, args):
+ os.environ['cwd'] = os.getcwd()
self.output_directory = '.'
first_ids_file = None
predetermined_ids_file = None
@@ -338,11 +339,9 @@ are exported to translation interchange files (e.g. XMB files), etc.
'gzipped_resource_file_map_source'):
return 'cp1252'
if output_type in ('android', 'c_format', 'js_map_format', 'plist',
- 'plist_strings', 'doc', 'json', 'android_policy'):
+ 'plist_strings', 'doc', 'json', 'android_policy',
+ 'chrome_messages_json'):
return 'utf_8'
- if output_type in ('chrome_messages_json'):
- # Chrome Web Store currently expects BOM for UTF-8 files :-(
- return 'utf-8-sig'
# TODO(gfeher) modify here to set utf-8 encoding for admx/adml
return 'utf_16'
diff --git a/chromium/tools/grit/grit/tool/xmb.py b/chromium/tools/grit/grit/tool/xmb.py
index c25dbf143d1..eb10e7164e9 100755
--- a/chromium/tools/grit/grit/tool/xmb.py
+++ b/chromium/tools/grit/grit/tool/xmb.py
@@ -165,6 +165,8 @@ Other options:
return 'Exports all translateable messages into an XMB file.'
def Run(self, opts, args):
+ os.environ['cwd'] = os.getcwd()
+
self.SetOptions(opts)
limit_file = None
diff --git a/chromium/tools/grit/grit_info.py b/chromium/tools/grit/grit_info.py
index a7f960142d6..3b85dab068f 100755
--- a/chromium/tools/grit/grit_info.py
+++ b/chromium/tools/grit/grit_info.py
@@ -110,6 +110,8 @@ def PrintUsage():
def DoMain(argv):
+ os.environ['cwd'] = os.getcwd()
+
parser = optparse.OptionParser()
parser.add_option("--inputs", action="store_true", dest="inputs")
parser.add_option("--outputs", action="store_true", dest="outputs")
diff --git a/chromium/tools/grit/grit_rule.gni b/chromium/tools/grit/grit_rule.gni
index 6a6a19ff024..0afe4b38b0d 100644
--- a/chromium/tools/grit/grit_rule.gni
+++ b/chromium/tools/grit/grit_rule.gni
@@ -13,7 +13,7 @@
# source_is_generated (optional, defaults to false)
# Declares that the input (or one of its dependencies) is generated so
# that grit_info is not run on the file when
-# compute_grit_inputs_for_analyze is set (because the file will not
+# compute_inputs_for_analyze is set (because the file will not
# exist at analyze time). For "analyze" to be correct in this case, the
# inputs to the grit file must either be listed in the inputs variable
# or are listed as inputs to dependencies of this target.
@@ -86,6 +86,7 @@
# }
import("//build/config/android/config.gni")
import("//build/config/chrome_build.gni")
+import("//build/config/compute_inputs_for_analyze.gni")
import("//build/config/crypto.gni")
import("//build/config/features.gni")
import("//build/config/ui.gni")
@@ -94,18 +95,6 @@ import("//third_party/closure_compiler/closure_args.gni")
assert(!enable_resource_whitelist_generation || is_android,
"resource whitelist generation only works on android")
-declare_args() {
- # When set, this will fork out to grit at GN-time to get all inputs
- # referenced by the .grd file.
- #
- # Normal builds don't need this since proper incremental builds are handled
- # by grit writing out the inputs in .d files at build-time. But for analyze
- # to work on the bots, it needs to know about all input files at GN-time so
- # it knows which tests to trigger when something changes. This option will
- # slow down the GN run.
- compute_grit_inputs_for_analyze = false
-}
-
grit_defines = []
# Mac and iOS want Title Case strings.
@@ -415,7 +404,7 @@ template("grit") {
# Must be after the args are computed since they are re-used.
# See the comments for the two variables used in this condition for
# why this works this way.
- if (compute_grit_inputs_for_analyze && !source_is_generated) {
+ if (compute_inputs_for_analyze && !source_is_generated) {
grit_info_script = "//tools/grit/grit_info.py"
grit_info_args = [
"--inputs",
diff --git a/chromium/tools/gritsettings/resource_ids b/chromium/tools/gritsettings/resource_ids
index fc16a42e623..efa6e5c90b8 100644
--- a/chromium/tools/gritsettings/resource_ids
+++ b/chromium/tools/gritsettings/resource_ids
@@ -81,56 +81,56 @@
# START chrome/browser section.
"chrome/browser/browser_resources.grd": {
"includes": [11000],
- "structures": [11470],
+ "structures": [11480],
},
"chrome/browser/resources/chromeos/multidevice_setup/multidevice_setup_resources.grd": {
- "structures": [11515],
+ "structures": [11525],
},
"chrome/browser/resources/component_extension_resources.grd": {
- "includes": [11560],
- "structures": [11810],
+ "includes": [11570],
+ "structures": [11820],
},
"chrome/browser/resources/invalidations_resources.grd": {
- "includes": [11860],
+ "includes": [11870],
},
"chrome/browser/resources/md_extensions/extensions_resources_vulcanized.grd": {
- "includes": [11900],
+ "includes": [11910],
},
"chrome/browser/resources/md_extensions/extensions_resources.grd": {
- "structures": [11910],
+ "structures": [11920],
},
"chrome/browser/resources/net_internals_resources.grd": {
- "includes": [12000],
+ "includes": [12010],
},
"chrome/browser/resources/print_preview/print_preview_resources_vulcanized.grd": {
- "includes": [12010],
+ "includes": [12020],
},
"chrome/browser/resources/print_preview/print_preview_resources.grd": {
- "structures": [12020],
+ "structures": [12030],
},
"chrome/browser/resources/quota_internals_resources.grd": {
- "includes": [12210],
+ "includes": [12220],
},
"chrome/browser/resources/settings/settings_resources_vulcanized.grd": {
- "includes": [12230],
+ "includes": [12240],
},
"chrome/browser/resources/settings/settings_resources.grd": {
- "structures": [12240],
+ "structures": [12250],
},
"chrome/browser/resources/sync_file_system_internals_resources.grd": {
- "includes": [12740],
+ "includes": [12750],
},
"chrome/browser/resources/task_scheduler_internals/resources.grd": {
- "includes": [12770],
+ "includes": [12780],
},
"chrome/browser/resources/translate_internals_resources.grd": {
- "includes": [12780],
+ "includes": [12790],
},
"chrome/browser/resources/webapks_ui_resources.grd": {
- "includes": [12800],
+ "includes": [12810],
},
"chrome/browser/vr/testapp/vr_testapp_resources.grd": {
- "includes": [12810],
+ "includes": [12820],
},
# END chrome/browser section.
@@ -188,7 +188,7 @@
"components/resources/components_scaled_resources.grd": {
"structures": [17200],
},
- "components/web_contents_delegate_android/web_contents_delegate_android_strings.grd": {
+ "components/embedder_suppport/android/java/strings/web_contents_delegate_android_strings.grd": {
"messages": [17400],
},
# END components/ section.
@@ -285,7 +285,7 @@
"messages": [23520],
},
"ash/components/ash_components_strings.grd": {
- "messages": [23950],
+ "messages": [24050],
},
"ash/components/resources/ash_components_resources.grd": {
"structures": [24250],
@@ -357,7 +357,7 @@
"messages": [25800],
},
- "ui/app_list/resources/app_list_resources.grd": {
+ "ash/app_list/resources/app_list_resources.grd": {
"structures": [25900],
},
"ui/chromeos/resources/ui_chromeos_resources.grd": {
diff --git a/chromium/tools/gritsettings/startup_resources_mac.txt b/chromium/tools/gritsettings/startup_resources_mac.txt
index 2d02128500d..c1fd297750c 100644
--- a/chromium/tools/gritsettings/startup_resources_mac.txt
+++ b/chromium/tools/gritsettings/startup_resources_mac.txt
@@ -172,7 +172,6 @@ IDS_RELOAD_MENU_HARD_RELOAD_ITEM 271
IDS_RELOAD_MENU_EMPTY_AND_HARD_RELOAD_ITEM 272
IDS_TOOLTIP_STAR 273
IDS_REGISTER_PROTOCOL_HANDLER_TOOLTIP 274
-IDS_VIEW_INCOMPATIBILITIES 275
IDR_INPUT_ALERT_MENU 276
IDS_NEW_TAB 277
IDS_NEW_WINDOW 278
diff --git a/chromium/tools/gritsettings/translation_expectations.pyl b/chromium/tools/gritsettings/translation_expectations.pyl
index cb6e8d2861b..83ae19b104a 100644
--- a/chromium/tools/gritsettings/translation_expectations.pyl
+++ b/chromium/tools/gritsettings/translation_expectations.pyl
@@ -63,7 +63,7 @@
"chrome/android/java/strings/android_chrome_strings.grd",
"chrome/android/webapk/strings/android_webapk_strings.grd",
"components/autofill/android/java/strings/autofill_strings.grd",
- "components/web_contents_delegate_android/java/strings/web_contents_delegate_android_strings.grd",
+ "components/embedder_support/android/java/strings/web_contents_delegate_android_strings.grd",
"content/public/android/java/strings/android_content_strings.grd",
"ui/android/java/strings/android_ui_strings.grd",
],
diff --git a/chromium/tools/idl_parser/idl_lexer.py b/chromium/tools/idl_parser/idl_lexer.py
index d44d6c37196..c1446816008 100755
--- a/chromium/tools/idl_parser/idl_lexer.py
+++ b/chromium/tools/idl_parser/idl_lexer.py
@@ -162,7 +162,7 @@ class IDLLexer(object):
# A symbol or keyword.
def t_KEYWORD_OR_SYMBOL(self, t):
- r'_?[A-Za-z][A-Za-z_0-9]*'
+ r'_?[A-Za-z][A-Za-z_0-9-]*'
# All non-keywords are assumed to be symbols
t.type = self.keywords.get(t.value, 'identifier')
diff --git a/chromium/tools/idl_parser/idl_parser.py b/chromium/tools/idl_parser/idl_parser.py
index 3b324fa6ffb..89df17ef2ea 100755
--- a/chromium/tools/idl_parser/idl_parser.py
+++ b/chromium/tools/idl_parser/idl_parser.py
@@ -307,14 +307,22 @@ class IDLParser(object):
p[0] = self.BuildError(p, 'Partial')
def p_PartialDefinition(self, p):
- """PartialDefinition : PartialDictionary
- | PartialInterface
+ """PartialDefinition : INTERFACE PartialInterfaceOrPartialMixin
+ | PartialDictionary
| Namespace"""
+ if len(p) > 2:
+ p[0] = p[2]
+ else:
+ p[0] = p[1]
+
+ def p_PartialInterfaceOrPartialMixin(self, p):
+ """PartialInterfaceOrPartialMixin : PartialInterfaceRest
+ | MixinRest"""
p[0] = p[1]
- def p_PartialInterface(self, p):
- """PartialInterface : INTERFACE identifier '{' InterfaceMembers '}' ';'"""
- p[0] = self.BuildNamed('Interface', p, 2, p[4])
+ def p_PartialInterfaceRest(self, p):
+ """PartialInterfaceRest : identifier '{' InterfaceMembers '}' ';'"""
+ p[0] = self.BuildNamed('Interface', p, 1, p[3])
def p_InterfaceMembers(self, p):
"""InterfaceMembers : ExtendedAttributeList InterfaceMember InterfaceMembers
@@ -344,7 +352,8 @@ class IDLParser(object):
def p_MixinRest(self, p):
"""MixinRest : MIXIN identifier '{' MixinMembers '}' ';'"""
- p[0] = self.BuildNamed('InterfaceMixin', p, 2, p[4])
+ p[0] = self.BuildNamed('Interface', p, 2, p[4])
+ p[0].AddChildren(self.BuildTrue('MIXIN'))
def p_MixinMembers(self, p):
"""MixinMembers : ExtendedAttributeList MixinMember MixinMembers
diff --git a/chromium/tools/idl_parser/test_lexer/values.in b/chromium/tools/idl_parser/test_lexer/values.in
index bc37898166f..88dd8cd0682 100644
--- a/chromium/tools/idl_parser/test_lexer/values.in
+++ b/chromium/tools/idl_parser/test_lexer/values.in
@@ -53,3 +53,4 @@ integer 0x1234567890AbCdEf
integer 0X1234567890aBcDeF
identifier blah
+identifier include-hyphen
diff --git a/chromium/tools/idl_parser/test_parser/interface_web.idl b/chromium/tools/idl_parser/test_parser/interface_web.idl
index d35dfd5b7ce..a2808367795 100644
--- a/chromium/tools/idl_parser/test_parser/interface_web.idl
+++ b/chromium/tools/idl_parser/test_parser/interface_web.idl
@@ -43,18 +43,24 @@ partial interface MyIFacePartial { };
partial interface MyIFaceInherit : Foo {};
/** TREE
- *InterfaceMixin(IFaceMixin)
+ *Interface(IFaceMixin)
+ * MIXIN: True
*/
interface mixin IFaceMixin {};
/** ERROR Unexpected ":" after identifier "IFaceMixinInherit". */
interface mixin IFaceMixinInherit : Foo {};
-/** ERROR Unexpected keyword "mixin" after keyword "interface". */
+/** TREE
+ *Interface(PartialIFaceMixin)
+ * PARTIAL: True
+ * MIXIN: True
+ */
partial interface mixin PartialIFaceMixin {};
/** TREE
- *InterfaceMixin(IFaceMixin)
+ *Interface(IFaceMixin)
+ * MIXIN: True
* Error(Unexpected keyword "static" after "{".)
*/
interface mixin IFaceMixin {
@@ -62,7 +68,8 @@ interface mixin IFaceMixin {
};
/** TREE
- *InterfaceMixin(IFaceMixin)
+ *Interface(IFaceMixin)
+ * MIXIN: True
* Const(pi)
* PrimitiveType(double)
* Value() = "3.14159"
@@ -685,7 +692,7 @@ Foo includes Bar;
* PrimitiveType(void)
*/
interface IFaceWithKeyword {
- // '_' prefix is needed because "includes" is a keyword of Web IDL and our
- // parser cannot handle a keyword as an identifier. (https://crbug.com/820353)
+ // '_' prefix needs to be removed in tokenization.
+ // https://heycam.github.io/webidl/#idl-names
void _includes(DOMString val);
};
diff --git a/chromium/tools/imagediff/BUILD.gn b/chromium/tools/imagediff/BUILD.gn
index 66f539a0c02..cdc204ef0b7 100644
--- a/chromium/tools/imagediff/BUILD.gn
+++ b/chromium/tools/imagediff/BUILD.gn
@@ -17,7 +17,6 @@ if (current_toolchain == host_toolchain) {
deps = [
"//base",
- "//build/config:exe_and_shlib_deps",
"//build/win:default_exe_manifest",
"//third_party/libpng",
"//third_party/zlib",
diff --git a/chromium/tools/include_tracer.py b/chromium/tools/include_tracer.py
index 8f817c34a51..c23f8793922 100755
--- a/chromium/tools/include_tracer.py
+++ b/chromium/tools/include_tracer.py
@@ -9,10 +9,12 @@
Since it ignores defines, it gives just a rough estimation of file size.
Usage:
- tools/include_tracer.py chrome/browser/ui/browser.h
+ tools/include_tracer.py -Iout/Default/gen chrome/browser/ui/browser.h
"""
+import argparse
import os
+import re
import sys
# Created by copying the command line for prerender_browsertest.cc, replacing
@@ -25,98 +27,9 @@ INCLUDE_PATHS = [
'skia/ext',
'testing/gmock/include',
'testing/gtest/include',
- 'third_party/blink/renderer',
- 'third_party/blink/renderer/core',
- 'third_party/blink/renderer/core/accessibility',
- 'third_party/blink/renderer/core/accessibility/chromium',
- 'third_party/blink/renderer/core/bindings',
- 'third_party/blink/renderer/core/bindings/generic',
- 'third_party/blink/renderer/core/bindings/v8',
- 'third_party/blink/renderer/core/bindings/v8/custom',
- 'third_party/blink/renderer/core/bindings/v8/specialization',
- 'third_party/blink/renderer/core/bridge',
- 'third_party/blink/renderer/core/bridge/jni',
- 'third_party/blink/renderer/core/bridge/jni/v8',
- 'third_party/blink/renderer/core/css',
- 'third_party/blink/renderer/core/dom',
- 'third_party/blink/renderer/core/dom/default',
- 'third_party/blink/renderer/core/editing',
- 'third_party/blink/renderer/core/fileapi',
- 'third_party/blink/renderer/core/history',
- 'third_party/blink/renderer/core/html',
- 'third_party/blink/renderer/core/html/canvas',
- 'third_party/blink/renderer/core/html/parser',
- 'third_party/blink/renderer/core/html/shadow',
- 'third_party/blink/renderer/core/inspector',
- 'third_party/blink/renderer/core/loader',
- 'third_party/blink/renderer/core/loader/appcache',
- 'third_party/blink/renderer/core/loader/archive',
- 'third_party/blink/renderer/core/loader/cache',
- 'third_party/blink/renderer/core/loader/icon',
- 'third_party/blink/renderer/core/mathml',
- 'third_party/blink/renderer/core/notifications',
- 'third_party/blink/renderer/core/page',
- 'third_party/blink/renderer/core/page/animation',
- 'third_party/blink/renderer/core/page/chromium',
- 'third_party/blink/renderer/core/platform',
- 'third_party/blink/renderer/core/platform/animation',
- 'third_party/blink/renderer/core/platform/audio',
- 'third_party/blink/renderer/core/platform/audio/chromium',
- 'third_party/blink/renderer/core/platform/audio/mac',
- 'third_party/blink/renderer/core/platform/chromium',
- 'third_party/blink/renderer/core/platform/cocoa',
- 'third_party/blink/renderer/core/platform/graphics',
- 'third_party/blink/renderer/core/platform/graphics/cg',
- 'third_party/blink/renderer/core/platform/graphics/chromium',
- 'third_party/blink/renderer/core/platform/graphics/cocoa',
- 'third_party/blink/renderer/core/platform/graphics/filters',
- 'third_party/blink/renderer/core/platform/graphics/gpu',
- 'third_party/blink/renderer/core/platform/graphics/mac',
- 'third_party/blink/renderer/core/platform/graphics/opentype',
- 'third_party/blink/renderer/core/platform/graphics/skia',
- 'third_party/blink/renderer/core/platform/graphics/transforms',
- 'third_party/blink/renderer/core/platform/image-decoders',
- 'third_party/blink/renderer/core/platform/image-decoders/bmp',
- 'third_party/blink/renderer/core/platform/image-decoders/gif',
- 'third_party/blink/renderer/core/platform/image-decoders/ico',
- 'third_party/blink/renderer/core/platform/image-decoders/jpeg',
- 'third_party/blink/renderer/core/platform/image-decoders/png',
- 'third_party/blink/renderer/core/platform/image-decoders/skia',
- 'third_party/blink/renderer/core/platform/image-decoders/webp',
- 'third_party/blink/renderer/core/platform/image-decoders/xbm',
- 'third_party/blink/renderer/core/platform/image-encoders/skia',
- 'third_party/blink/renderer/core/platform/mac',
- 'third_party/blink/renderer/core/platform/mock',
- 'third_party/blink/renderer/core/platform/network',
- 'third_party/blink/renderer/core/platform/network/chromium',
- 'third_party/blink/renderer/core/platform/sql',
- 'third_party/blink/renderer/core/platform/text',
- 'third_party/blink/renderer/core/platform/text/mac',
- 'third_party/blink/renderer/core/platform/text/transcoder',
- 'third_party/blink/renderer/core/plugins',
- 'third_party/blink/renderer/core/plugins/chromium',
- 'third_party/blink/renderer/core/rendering',
- 'third_party/blink/renderer/core/rendering/style',
- 'third_party/blink/renderer/core/rendering/svg',
- 'third_party/blink/renderer/core/storage',
- 'third_party/blink/renderer/core/storage/chromium',
- 'third_party/blink/renderer/core/svg',
- 'third_party/blink/renderer/core/svg/animation',
- 'third_party/blink/renderer/core/svg/graphics',
- 'third_party/blink/renderer/core/svg/graphics/filters',
- 'third_party/blink/renderer/core/svg/properties',
- 'third_party/blink/renderer/core/webaudio',
- 'third_party/blink/renderer/core/websockets',
- 'third_party/blink/renderer/core/workers',
- 'third_party/blink/renderer/core/xml',
- 'third_party/blink/renderer/public',
- 'third_party/blink/renderer/web',
- 'third_party/blink/renderer/wtf',
'third_party/google_toolbox_for_mac/src',
'third_party/icu/public/common',
'third_party/icu/public/i18n',
- 'third_party/npapi',
- 'third_party/npapi/bindings',
'third_party/protobuf',
'third_party/protobuf/src',
'third_party/skia/gpu/include',
@@ -127,16 +40,10 @@ INCLUDE_PATHS = [
'third_party/skia/include/pdf',
'third_party/skia/include/ports',
'v8/include',
- 'xcodebuild/Debug/include',
- 'xcodebuild/DerivedSources/Debug/chrome',
- 'xcodebuild/DerivedSources/Debug/policy',
- 'xcodebuild/DerivedSources/Debug/protoc_out',
- 'xcodebuild/DerivedSources/Debug/webkit',
- 'xcodebuild/DerivedSources/Debug/webkit/bindings',
]
-def Walk(seen, filename, parent, indent):
+def Walk(include_dirs, seen, filename, parent, indent):
"""Returns the size of |filename| plus the size of all files included by
|filename| and prints the include tree of |filename| to stdout. Every file
is visited at most once.
@@ -165,7 +72,7 @@ def Walk(seen, filename, parent, indent):
# Find file in all include paths.
resolved_filename = filename
- for root in INCLUDE_PATHS + [os.path.dirname(parent)]:
+ for root in INCLUDE_PATHS + [os.path.dirname(parent)] + include_dirs:
if os.path.exists(os.path.join(root, filename)):
resolved_filename = os.path.join(root, filename)
break
@@ -178,21 +85,28 @@ def Walk(seen, filename, parent, indent):
lines = []
for line in lines:
line = line.strip()
- if line.startswith('#include "'):
+ match = re.match(r'#include\s+(\S+).*', line)
+ if match:
+ include = match.group(1)
+ if include.startswith('"'):
+ include = include[1:-1]
total_bytes += Walk(
- seen, line.split('"')[1], resolved_filename, indent + 2)
- elif line.startswith('#include '):
- include = '<' + line.split('<')[1].split('>')[0] + '>'
- total_bytes += Walk(
- seen, include, resolved_filename, indent + 2)
+ include_dirs, seen, include, resolved_filename, indent + 2)
elif line.startswith('import '):
total_bytes += Walk(
- seen, line.split('"')[1], resolved_filename, indent + 2)
+ include_dirs, seen, line.split('"')[1], resolved_filename, indent + 2)
return total_bytes + len("".join(lines))
def main():
- bytes = Walk(set(), sys.argv[1], '', 0)
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-I', action='append', dest='include_dirs')
+ parser.add_argument('source_file')
+ options = parser.parse_args(sys.argv[1:])
+ if not options.include_dirs:
+ options.include_dirs = []
+
+ bytes = Walk(options.include_dirs, set(), options.source_file, '', 0)
print
print float(bytes) / (1 << 20), "megabytes of chrome source"
diff --git a/chromium/tools/ipc_fuzzer/BUILD.gn b/chromium/tools/ipc_fuzzer/BUILD.gn
index ce31589d31e..e33fd6e3d04 100644
--- a/chromium/tools/ipc_fuzzer/BUILD.gn
+++ b/chromium/tools/ipc_fuzzer/BUILD.gn
@@ -2,10 +2,13 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/nacl/config.gni")
import("//tools/ipc_fuzzer/ipc_fuzzer.gni")
config("ipc_fuzzer_config") {
- defines = [ "ENABLE_IPC_FUZZER" ]
+ if (!is_nacl_nonsfi) {
+ defines = [ "ENABLE_IPC_FUZZER" ]
+ }
}
config("ipc_fuzzer_tool_config") {
diff --git a/chromium/tools/ipc_fuzzer/message_replay/BUILD.gn b/chromium/tools/ipc_fuzzer/message_replay/BUILD.gn
index caa50384997..824efe1b4cf 100644
--- a/chromium/tools/ipc_fuzzer/message_replay/BUILD.gn
+++ b/chromium/tools/ipc_fuzzer/message_replay/BUILD.gn
@@ -5,7 +5,7 @@
executable("ipc_fuzzer_replay") {
configs += [ "//tools/ipc_fuzzer:ipc_fuzzer_tool_config" ]
deps = [
- "//mojo/edk",
+ "//mojo/core/embedder",
"//tools/ipc_fuzzer/message_lib:ipc_message_lib",
]
public_deps = [
diff --git a/chromium/tools/ipc_fuzzer/message_replay/DEPS b/chromium/tools/ipc_fuzzer/message_replay/DEPS
index e3f83dc0e83..f69c943f559 100644
--- a/chromium/tools/ipc_fuzzer/message_replay/DEPS
+++ b/chromium/tools/ipc_fuzzer/message_replay/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+chrome/common",
"+content/public/common",
- "+mojo/edk/embedder",
+ "+mojo/core/embedder",
+ "+mojo/public",
"+services/service_manager/embedder",
]
diff --git a/chromium/tools/ipc_fuzzer/message_replay/replay_process.cc b/chromium/tools/ipc_fuzzer/message_replay/replay_process.cc
index d5a3d48703d..8849fb36304 100644
--- a/chromium/tools/ipc_fuzzer/message_replay/replay_process.cc
+++ b/chromium/tools/ipc_fuzzer/message_replay/replay_process.cc
@@ -21,11 +21,12 @@
#include "content/public/common/service_manager_connection.h"
#include "ipc/ipc.mojom.h"
#include "ipc/ipc_channel_mojo.h"
-#include "mojo/edk/embedder/configuration.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/incoming_broker_client_invitation.h"
-#include "mojo/edk/embedder/platform_channel_pair.h"
-#include "mojo/edk/embedder/scoped_ipc_support.h"
+#include "mojo/core/embedder/configuration.h"
+#include "mojo/core/embedder/embedder.h"
+#include "mojo/core/embedder/scoped_ipc_support.h"
+#include "mojo/public/cpp/platform/platform_channel.h"
+#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
+#include "mojo/public/cpp/system/invitation.h"
#include "services/service_manager/embedder/switches.h"
#if defined(OS_POSIX)
@@ -63,27 +64,23 @@ class IPCChannelBootstrapper : public content::ConnectionFilter {
} // namespace
void InitializeMojo() {
- mojo::edk::Configuration config;
+ mojo::core::Configuration config;
config.max_message_num_bytes = 64 * 1024 * 1024;
- mojo::edk::Init(config);
+ mojo::core::Init(config);
}
-std::unique_ptr<mojo::edk::IncomingBrokerClientInvitation>
-InitializeMojoIPCChannel() {
- mojo::edk::ScopedInternalPlatformHandle platform_channel;
+mojo::IncomingInvitation InitializeMojoIPCChannel() {
+ mojo::PlatformChannelEndpoint endpoint;
#if defined(OS_WIN)
- platform_channel =
- mojo::edk::PlatformChannelPair::PassClientHandleFromParentProcess(
- *base::CommandLine::ForCurrentProcess());
+ endpoint = mojo::PlatformChannel::RecoverPassedEndpointFromCommandLine(
+ *base::CommandLine::ForCurrentProcess());
#elif defined(OS_POSIX)
- platform_channel.reset(mojo::edk::InternalPlatformHandle(
- base::GlobalDescriptors::GetInstance()->Get(
- service_manager::kMojoIPCChannel)));
+ endpoint = mojo::PlatformChannelEndpoint(mojo::PlatformHandle(
+ base::ScopedFD(base::GlobalDescriptors::GetInstance()->Get(
+ service_manager::kMojoIPCChannel))));
#endif
- CHECK(platform_channel.is_valid());
- return mojo::edk::IncomingBrokerClientInvitation::Accept(
- mojo::edk::ConnectionParams(mojo::edk::TransportProtocol::kLegacy,
- std::move(platform_channel)));
+ CHECK(endpoint.is_valid());
+ return mojo::IncomingInvitation::Accept(std::move(endpoint));
}
ReplayProcess::ReplayProcess()
@@ -131,19 +128,20 @@ bool ReplayProcess::Initialize(int argc, const char** argv) {
base::GlobalDescriptors::kBaseDescriptor);
#endif
- mojo_ipc_support_.reset(new mojo::edk::ScopedIPCSupport(
+ mojo_ipc_support_.reset(new mojo::core::ScopedIPCSupport(
io_thread_.task_runner(),
- mojo::edk::ScopedIPCSupport::ShutdownPolicy::FAST));
- broker_client_invitation_ = InitializeMojoIPCChannel();
+ mojo::core::ScopedIPCSupport::ShutdownPolicy::FAST));
+ mojo_invitation_ =
+ std::make_unique<mojo::IncomingInvitation>(InitializeMojoIPCChannel());
return true;
}
void ReplayProcess::OpenChannel() {
- DCHECK(broker_client_invitation_);
+ DCHECK(mojo_invitation_);
service_manager_connection_ = content::ServiceManagerConnection::Create(
service_manager::mojom::ServiceRequest(
- broker_client_invitation_->ExtractMessagePipe(
+ mojo_invitation_->ExtractMessagePipe(
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
service_manager::switches::kServiceRequestChannelToken))),
io_thread_.task_runner());
@@ -182,11 +180,10 @@ void ReplayProcess::SendNextMessage() {
}
void ReplayProcess::Run() {
- timer_.reset(new base::Timer(false, true));
- timer_->Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(1),
- base::Bind(&ReplayProcess::SendNextMessage,
- base::Unretained(this)));
+ base::RepeatingTimer timer;
+ timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(1),
+ base::BindRepeating(&ReplayProcess::SendNextMessage,
+ base::Unretained(this)));
base::RunLoop().Run();
}
diff --git a/chromium/tools/ipc_fuzzer/message_replay/replay_process.h b/chromium/tools/ipc_fuzzer/message_replay/replay_process.h
index 485a525923f..29c6914c738 100644
--- a/chromium/tools/ipc_fuzzer/message_replay/replay_process.h
+++ b/chromium/tools/ipc_fuzzer/message_replay/replay_process.h
@@ -24,10 +24,10 @@ class ServiceManagerConnection;
}
namespace mojo {
-namespace edk {
-class IncomingBrokerClientInvitation;
+class IncomingInvitation;
+namespace core {
class ScopedIPCSupport;
-} // namespace edk
+} // namespace core
} // namespace mojo
namespace ipc_fuzzer {
@@ -58,16 +58,14 @@ class ReplayProcess : public IPC::Listener {
private:
void SendNextMessage();
- std::unique_ptr<mojo::edk::ScopedIPCSupport> mojo_ipc_support_;
- std::unique_ptr<mojo::edk::IncomingBrokerClientInvitation>
- broker_client_invitation_;
+ std::unique_ptr<mojo::core::ScopedIPCSupport> mojo_ipc_support_;
+ std::unique_ptr<mojo::IncomingInvitation> mojo_invitation_;
std::unique_ptr<content::ServiceManagerConnection>
service_manager_connection_;
std::unique_ptr<IPC::ChannelProxy> channel_;
base::MessageLoop main_loop_;
base::Thread io_thread_;
base::WaitableEvent shutdown_event_;
- std::unique_ptr<base::Timer> timer_;
MessageVector messages_;
size_t message_index_;
diff --git a/chromium/tools/json_schema_compiler/feature_compiler.py b/chromium/tools/json_schema_compiler/feature_compiler.py
index 243e61ee1e0..fbfcf575a59 100644
--- a/chromium/tools/json_schema_compiler/feature_compiler.py
+++ b/chromium/tools/json_schema_compiler/feature_compiler.py
@@ -25,18 +25,10 @@ HEADER_FILE_TEMPLATE = """
#ifndef %(header_guard)s
#define %(header_guard)s
-#include "extensions/common/features/feature_provider.h"
-
namespace extensions {
+class FeatureProvider;
-class %(provider_class)s : public FeatureProvider {
- public:
- %(provider_class)s();
- ~%(provider_class)s() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(%(provider_class)s);
-};
+void %(method_name)s(FeatureProvider* provider);
} // namespace extensions
@@ -56,16 +48,18 @@ CC_FILE_BEGIN = """
#include "%(header_file_path)s"
#include "extensions/common/features/complex_feature.h"
+#include "extensions/common/features/feature_provider.h"
#include "extensions/common/features/manifest_feature.h"
#include "extensions/common/features/permission_feature.h"
namespace extensions {
+void %(method_name)s(FeatureProvider* provider) {
"""
# The end of the .cc file for the generated FeatureProvider.
CC_FILE_END = """
-%(provider_class)s::~%(provider_class)s() {}
+}
} // namespace extensions
"""
@@ -626,12 +620,12 @@ class FeatureCompiler(object):
"""A compiler to load, parse, and generate C++ code for a number of
features.json files."""
def __init__(self, chrome_root, source_files, feature_type,
- provider_class, out_root, out_base_filename):
+ method_name, out_root, out_base_filename):
# See __main__'s ArgumentParser for documentation on these properties.
self._chrome_root = chrome_root
self._source_files = source_files
self._feature_type = feature_type
- self._provider_class = provider_class
+ self._method_name = method_name
self._out_root = out_root
self._out_base_filename = out_base_filename
@@ -754,39 +748,45 @@ class FeatureCompiler(object):
"""Returns the Code object for the body of the .cc file, which handles the
initialization of all features."""
c = Code()
- c.Append('%s::%s() {' % (self._provider_class, self._provider_class))
c.Sblock()
for k in sorted(self._features.keys()):
c.Sblock('{')
feature = self._features[k]
c.Concat(feature.GetCode(self._feature_type))
- c.Append('AddFeature("%s", feature);' % k)
+ c.Append('provider->AddFeature("%s", feature);' % k)
c.Eblock('}')
- c.Eblock('}')
+ c.Eblock()
return c
def Write(self):
"""Writes the output."""
- header_file_path = self._out_base_filename + '.h'
- cc_file_path = self._out_base_filename + '.cc'
+ header_file = self._out_base_filename + '.h'
+ cc_file = self._out_base_filename + '.cc'
+
+ include_file_root = self._out_root
+ GEN_DIR_PREFIX = 'gen/'
+ if include_file_root.startswith(GEN_DIR_PREFIX):
+ include_file_root = include_file_root[len(GEN_DIR_PREFIX):]
+ header_file_path = '%s/%s' % (include_file_root, header_file)
+ cc_file_path = '%s/%s' % (include_file_root, cc_file)
substitutions = ({
'header_file_path': header_file_path,
'header_guard': (header_file_path.replace('/', '_').
replace('.', '_').upper()),
- 'provider_class': self._provider_class,
+ 'method_name': self._method_name,
'source_files': str(self._source_files),
'year': str(datetime.now().year)
})
if not os.path.exists(self._out_root):
os.makedirs(self._out_root)
# Write the .h file.
- with open(os.path.join(self._out_root, header_file_path), 'w') as f:
+ with open(os.path.join(self._out_root, header_file), 'w') as f:
header_file = Code()
header_file.Append(HEADER_FILE_TEMPLATE)
header_file.Substitute(substitutions)
f.write(header_file.Render().strip())
# Write the .cc file.
- with open(os.path.join(self._out_root, cc_file_path), 'w') as f:
+ with open(os.path.join(self._out_root, cc_file), 'w') as f:
cc_file = Code()
cc_file.Append(CC_FILE_BEGIN)
cc_file.Substitute(substitutions)
@@ -805,8 +805,8 @@ if __name__ == '__main__':
'feature_type', type=str,
help='The name of the class to use in feature generation ' +
'(e.g. APIFeature, PermissionFeature)')
- parser.add_argument('provider_class', type=str,
- help='The name of the class for the feature provider')
+ parser.add_argument('method_name', type=str,
+ help='The name of the method to populate the provider')
parser.add_argument('out_root', type=str,
help='The root directory to generate the C++ files into')
parser.add_argument(
@@ -818,7 +818,7 @@ if __name__ == '__main__':
if args.feature_type not in FEATURE_TYPES:
raise NameError('Unknown feature type: %s' % args.feature_type)
c = FeatureCompiler(args.chrome_root, args.source_files, args.feature_type,
- args.provider_class, args.out_root,
+ args.method_name, args.out_root,
args.out_base_filename)
c.Load()
c.Compile()
diff --git a/chromium/tools/json_schema_compiler/js_externs_generator.py b/chromium/tools/json_schema_compiler/js_externs_generator.py
index d0011e079a2..af7d1908ce5 100644
--- a/chromium/tools/json_schema_compiler/js_externs_generator.py
+++ b/chromium/tools/json_schema_compiler/js_externs_generator.py
@@ -83,11 +83,11 @@ class _Generator(object):
def _AppendEnumJsDoc(self, c, js_type):
""" Given an Enum Type object, generates the Code for the enum's definition.
"""
- (c.Sblock(line='/**', line_prefix=' * ')
- .Append('@enum {string}')
- .Append(self._js_util.GetSeeLink(self._namespace.name, 'type',
- js_type.simple_name))
- .Eblock(' */'))
+ c.Sblock(line='/**', line_prefix=' * ')
+ c.Append('@enum {string}')
+ self._js_util.AppendSeeLink(c, self._namespace.name, 'type',
+ js_type.simple_name)
+ c.Eblock(' */')
c.Append('%s.%s = {' % (self._GetNamespace(), js_type.name))
def get_property_name(e):
@@ -136,8 +136,8 @@ class _Generator(object):
else:
self._AppendTypedef(c, js_type.properties)
- c.Append(self._js_util.GetSeeLink(self._namespace.name, 'type',
- js_type.simple_name))
+ self._js_util.AppendSeeLink(c, self._namespace.name, 'type',
+ js_type.simple_name)
c.Eblock(' */')
var = '%s.%s' % (self._GetNamespace(), js_type.simple_name)
@@ -192,8 +192,7 @@ class _Generator(object):
if (event.description):
c.Comment(event.description, comment_prefix='')
c.Append('@type {!ChromeEvent}')
- c.Append(self._js_util.GetSeeLink(self._namespace.name, 'event',
- event.name))
+ self._js_util.AppendSeeLink(c, self._namespace.name, 'event', event.name)
c.Eblock(' */')
c.Append('%s.%s;' % (self._GetNamespace(), event.name))
c.Append()
diff --git a/chromium/tools/json_schema_compiler/js_externs_generator_test.py b/chromium/tools/json_schema_compiler/js_externs_generator_test.py
index 5036257a8ff..ac8f677acfb 100755
--- a/chromium/tools/json_schema_compiler/js_externs_generator_test.py
+++ b/chromium/tools/json_schema_compiler/js_externs_generator_test.py
@@ -89,7 +89,7 @@ namespace fakeApi {
"""
# The output we expect from our fake idl file.
-expected_output = """// Copyright %s The Chromium Authors. All rights reserved.
+fake_idl_expected = """// Copyright %s The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -221,6 +221,73 @@ chrome.fakeApi.optionalParam = function(callback) {};
*/
chrome.fakeApi.onTrapDetected;""" % datetime.now().year
+# A subset of fake_idl. The key difference is that the namespace is private,
+# which means that @see links shouldn't be generated.
+fake_private_idl = """
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// A totally fake API.
+namespace fakeApiPrivate {
+ enum Greek {
+ ALPHA,
+ BETA,
+ GAMMA,
+ DELTA
+ };
+
+ dictionary Bar {
+ long num;
+ };
+
+ interface Events {
+ // Fired when we realize it's a trap!
+ static void onTrapDetected(Baz baz);
+ };
+};
+"""
+
+fake_private_idl_expected = """// Copyright %s The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file was generated by:
+// tools/json_schema_compiler/compiler.py.
+// NOTE: The format of types has changed. 'FooType' is now
+// 'chrome.fakeApiPrivate.FooType'.
+// Please run the closure compiler before committing changes.
+// See https://chromium.googlesource.com/chromium/src/+/master/docs/closure_compilation.md
+
+/** @fileoverview Externs generated from namespace: fakeApiPrivate */
+
+/**
+ * @const
+ */
+chrome.fakeApiPrivate = {};
+
+/**
+ * @enum {string}
+ */
+chrome.fakeApiPrivate.Greek = {
+ ALPHA: 'ALPHA',
+ BETA: 'BETA',
+ GAMMA: 'GAMMA',
+ DELTA: 'DELTA',
+};
+
+/**
+ * @typedef {{
+ * num: number
+ * }}
+ */
+chrome.fakeApiPrivate.Bar;
+
+/**
+ * Fired when we realize it's a trap!
+ * @type {!ChromeEvent}
+ */
+chrome.fakeApiPrivate.onTrapDetected;""" % datetime.now().year
fake_json = """// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
@@ -296,7 +363,7 @@ fake_json = """// Copyright 2014 The Chromium Authors. All rights reserved.
}
]"""
-json_expected = """// Copyright %s The Chromium Authors. All rights reserved.
+fake_json_expected = """// Copyright %s The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -361,12 +428,18 @@ class JsExternGeneratorTest(unittest.TestCase):
def testBasic(self):
namespace = self._GetNamespace(fake_idl, 'fake_api.idl', True)
- self.assertMultiLineEqual(expected_output,
+ self.assertMultiLineEqual(fake_idl_expected,
+ JsExternsGenerator().Generate(namespace).Render())
+
+ def testPrivate(self):
+ namespace = self._GetNamespace(fake_private_idl, 'fake_api_private.idl',
+ True)
+ self.assertMultiLineEqual(fake_private_idl_expected,
JsExternsGenerator().Generate(namespace).Render())
def testJsonWithInlineObjects(self):
namespace = self._GetNamespace(fake_json, 'fake_api.json', False)
- self.assertMultiLineEqual(json_expected,
+ self.assertMultiLineEqual(fake_json_expected,
JsExternsGenerator().Generate(namespace).Render())
diff --git a/chromium/tools/json_schema_compiler/js_interface_generator.py b/chromium/tools/json_schema_compiler/js_interface_generator.py
index e6c892a8674..b84c717cc08 100644
--- a/chromium/tools/json_schema_compiler/js_interface_generator.py
+++ b/chromium/tools/json_schema_compiler/js_interface_generator.py
@@ -92,8 +92,7 @@ class _Generator(object):
if (event.description):
c.Comment(event.description, comment_prefix='')
c.Append('@type {!ChromeEvent}')
- c.Append(self._js_util.GetSeeLink(self._namespace.name, 'event',
- event.name))
+ self._js_util.AppendSeeLink(c, self._namespace.name, 'event', event.name)
c.Eblock(' */')
c.Append('%s.prototype.%s;' % (self._interface, event.name))
diff --git a/chromium/tools/json_schema_compiler/js_interface_generator_test.py b/chromium/tools/json_schema_compiler/js_interface_generator_test.py
index 90837d7a982..f2d5df58106 100755
--- a/chromium/tools/json_schema_compiler/js_interface_generator_test.py
+++ b/chromium/tools/json_schema_compiler/js_interface_generator_test.py
@@ -72,7 +72,7 @@ namespace fakeApi {
"""
# The output we expect from our fake idl file.
-expected_output = ("""// Copyright %s The Chromium Authors. All rights reserved.
+fake_idl_output = ("""// Copyright %s The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -126,7 +126,7 @@ class JsExternGeneratorTest(unittest.TestCase):
def testBasic(self):
namespace = self._GetNamespace(fake_idl, 'fake_api.idl')
self.assertMultiLineEqual(
- expected_output,
+ fake_idl_output,
JsInterfaceGenerator().Generate(namespace).Render())
diff --git a/chromium/tools/json_schema_compiler/js_util.py b/chromium/tools/json_schema_compiler/js_util.py
index e043f2efbac..285ece1d3b7 100644
--- a/chromium/tools/json_schema_compiler/js_util.py
+++ b/chromium/tools/json_schema_compiler/js_util.py
@@ -97,7 +97,7 @@ class JsUtil(object):
if function.deprecated:
c.Append('@deprecated %s' % function.deprecated)
- c.Append(self.GetSeeLink(namespace_name, 'method', function.name))
+ self.AppendSeeLink(c, namespace_name, 'method', function.name)
c.Eblock(' */')
@@ -174,14 +174,22 @@ class JsUtil(object):
return Code().Append(js_type.property_type.name)
return Code().Append('?') # TODO(tbreisacher): Make this more specific.
- def GetSeeLink(self, namespace_name, object_type, object_name):
- """Returns a @see link for a given API 'object' (type, method, or event).
+ def AppendSeeLink(self, c, namespace_name, object_type, object_name):
+ """Appends a @see link for a given API 'object' (type, method, or event).
"""
+ # TODO(nigeltao): this should actually be gated on if there is
+ # documentation, rather than if it's a private API. Most private APIs
+ # aren't documented, but some are. For example:
+ # - https://developer.chrome.com/apps/developerPrivate exists
+ # - https://developer.chrome.com/apps/screenlockPrivate does not
+ if namespace_name.endswith('Private'):
+ return
+
# NOTE(devlin): This is kind of a hack. Some APIs will be hosted on
# developer.chrome.com/apps/ instead of /extensions/, and some APIs have
# '.'s in them (like app.window), which should resolve to 'app_window'.
# Luckily, the doc server has excellent url resolution, and knows exactly
# what we mean. This saves us from needing any complicated logic here.
- return ('@see https://developer.chrome.com/extensions/%s#%s-%s' %
- (namespace_name, object_type, object_name))
+ c.Append('@see https://developer.chrome.com/extensions/%s#%s-%s' %
+ (namespace_name, object_type, object_name))
diff --git a/chromium/tools/json_schema_compiler/json_features.gni b/chromium/tools/json_schema_compiler/json_features.gni
index c35c677fc73..915a86b7d22 100644
--- a/chromium/tools/json_schema_compiler/json_features.gni
+++ b/chromium/tools/json_schema_compiler/json_features.gni
@@ -6,18 +6,17 @@
# The following variables are required:
# sources: The features.json files to use.
# feature_type: The type of the features to generate, e.g. APIFeature.
-# provider_class: The name of the provider class to generate, e.g.
-# APIFeatureProvider.
+# method_name: The name of the method to generate, e.g. AddChromeAPIFeatures.
# deps/public_deps/visibility: normal meaning
template("json_features") {
assert(defined(invoker.sources),
"\"sources\" must be defined for the $target_name template.")
assert(defined(invoker.feature_type),
"\"feature_type\" must be defined for the $target_name template.")
- assert(defined(invoker.provider_class),
- "\"provider_class\" must be defined for the $target_name template.")
+ assert(defined(invoker.method_name),
+ "\"method_name\" must be defined for the $target_name template.")
feature_type = invoker.feature_type
- provider_class = invoker.provider_class
+ method_name = invoker.method_name
compiler_root = "//tools/json_schema_compiler"
base_filename = target_name
@@ -41,7 +40,7 @@ template("json_features") {
args = [
".",
"$feature_type",
- "$provider_class",
+ "$method_name",
rebase_path(target_gen_dir, root_build_dir),
"$base_filename",
] + rebased
diff --git a/chromium/tools/json_schema_compiler/test/BUILD.gn b/chromium/tools/json_schema_compiler/test/BUILD.gn
index 2fe531e1696..9c6bec748ea 100644
--- a/chromium/tools/json_schema_compiler/test/BUILD.gn
+++ b/chromium/tools/json_schema_compiler/test/BUILD.gn
@@ -44,7 +44,7 @@ json_schema_api("api") {
json_features("features_compiler_test") {
feature_type = "APIFeature"
- provider_class = "CompilerTestFeatureProvider"
+ method_name = "CompilerTestAddFeaturesMethod"
sources = [
"features_test.json",
"features_test2.json",
diff --git a/chromium/tools/luci-go/OWNERS b/chromium/tools/luci-go/OWNERS
index 3bcc77d2384..8b03e48bcd8 100644
--- a/chromium/tools/luci-go/OWNERS
+++ b/chromium/tools/luci-go/OWNERS
@@ -1,5 +1,3 @@
-djd@chromium.org
maruel@chromium.org
tandrii@chromium.org
-tansell@chromium.org
vadimsh@chromium.org
diff --git a/chromium/tools/luci-go/README.md b/chromium/tools/luci-go/README.md
index f53bec17484..5cb0ddf6c62 100644
--- a/chromium/tools/luci-go/README.md
+++ b/chromium/tools/luci-go/README.md
@@ -2,9 +2,4 @@
Contains executable built out of
https://chromium.googlesource.com/infra/luci/luci-go/+/master/client/cmd
-
-The binaries are retrieved from the following builders:
-
-- mac64: http://build.chromium.org/p/chromium.infra/builders/infra-continuous-mac-10.10-64/
-- linux64: http://build.chromium.org/p/chromium.infra/builders/infra-continuous-precise-64/
-- win64: http://build.chromium.org/p/chromium.infra/builders/infra-continuous-win-64/
+Mapped through CIPD.
diff --git a/chromium/tools/luci-go/linux64/isolate.sha1 b/chromium/tools/luci-go/linux64/isolate.sha1
index 5a23e1c0c27..16106572d64 100644
--- a/chromium/tools/luci-go/linux64/isolate.sha1
+++ b/chromium/tools/luci-go/linux64/isolate.sha1
@@ -1 +1 @@
-b1c3c39fe8fe084bd2ec4ed0f03037751a3a8650
+9734e966a14f9e26f86e38a020fcd7584248d285
diff --git a/chromium/tools/luci-go/mac64/isolate.sha1 b/chromium/tools/luci-go/mac64/isolate.sha1
index 72d97848d7e..a61e43abb38 100644
--- a/chromium/tools/luci-go/mac64/isolate.sha1
+++ b/chromium/tools/luci-go/mac64/isolate.sha1
@@ -1 +1 @@
-ffb6a624bd14abdff34618fe97562b34350199f7
+18561de57e944d096521838b4e6cb49e0cc1df23
diff --git a/chromium/tools/luci-go/win64/isolate.exe.sha1 b/chromium/tools/luci-go/win64/isolate.exe.sha1
index d3ab3b3f323..5ac52a0347f 100644
--- a/chromium/tools/luci-go/win64/isolate.exe.sha1
+++ b/chromium/tools/luci-go/win64/isolate.exe.sha1
@@ -1 +1 @@
-bb2a587cbc0a8e5b0ae41be4ffb5ad33b213dcf9
+af227603890ea1d8c082b5caf15e46a6bf060a2e
diff --git a/chromium/tools/mb/mb.py b/chromium/tools/mb/mb.py
index 94bf68ef05a..22c0707c830 100755
--- a/chromium/tools/mb/mb.py
+++ b/chromium/tools/mb/mb.py
@@ -385,9 +385,9 @@ class MetaBuildWrapper(object):
('infra/tools/luci/logdog/butler/${platform}',
'git_revision:e1abc57be62d198b5c2f487bfb2fa2d2eb0e867c'),
('infra/tools/luci/vpython-native/${platform}',
- 'git_revision:e1abc57be62d198b5c2f487bfb2fa2d2eb0e867c'),
+ 'git_revision:b9c4670197dcefd8762d6e509302acd3efc6e303'),
('infra/tools/luci/vpython/${platform}',
- 'git_revision:e1abc57be62d198b5c2f487bfb2fa2d2eb0e867c'),
+ 'git_revision:b9c4670197dcefd8762d6e509302acd3efc6e303'),
]
for pkg, vers in cipd_packages:
cmd.append('--cipd-package=.swarming_module:%s:%s' % (pkg, vers))
@@ -739,13 +739,13 @@ class MetaBuildWrapper(object):
self.FlattenMixins(mixin_vals['mixins'], vals, visited)
return vals
- def RunGNGen(self, vals, compute_grit_inputs_for_analyze=False):
+ def RunGNGen(self, vals, compute_inputs_for_analyze=False):
build_dir = self.args.path
cmd = self.GNCmd('gen', build_dir, '--check')
gn_args = self.GNArgs(vals)
- if compute_grit_inputs_for_analyze:
- gn_args += ' compute_grit_inputs_for_analyze=true'
+ if compute_inputs_for_analyze:
+ gn_args += ' compute_inputs_for_analyze=true'
# Since GN hasn't run yet, the build directory may not even exist.
self.MaybeMakeDirectory(self.ToAbsPath(build_dir))
@@ -920,6 +920,8 @@ class MetaBuildWrapper(object):
subdir, exe = 'linux64', 'gn'
elif self.platform == 'darwin':
subdir, exe = 'mac', 'gn'
+ elif self.platform == 'aix6':
+ subdir, exe = 'aix', 'gn'
else:
subdir, exe = 'win', 'gn.exe'
@@ -935,6 +937,8 @@ class MetaBuildWrapper(object):
if not re.search('target_os.*=.*"chromeos"', gn_args):
raise MBErr('GN_ARGS is missing target_os = "chromeos": (GN_ARGS=%s)' %
gn_args)
+ if vals['gn_args']:
+ gn_args += ' ' + vals['gn_args']
else:
gn_args = vals['gn_args']
@@ -1078,7 +1082,7 @@ class MetaBuildWrapper(object):
def RunGNAnalyze(self, vals):
# Analyze runs before 'gn gen' now, so we need to run gn gen
# in order to ensure that we have a build directory.
- ret = self.RunGNGen(vals, compute_grit_inputs_for_analyze=True)
+ ret = self.RunGNGen(vals, compute_inputs_for_analyze=True)
if ret:
return ret
diff --git a/chromium/tools/mb/mb_config.pyl b/chromium/tools/mb/mb_config.pyl
index 2cab49055a5..334f7489e72 100644
--- a/chromium/tools/mb/mb_config.pyl
+++ b/chromium/tools/mb/mb_config.pyl
@@ -38,14 +38,12 @@
'Android Cronet Builder': 'android_cronet_release_bot_minimal_symbols_arm_no_neon',
'Android Cronet Builder (dbg)': 'android_cronet_debug_static_bot_arm_no_neon',
'Android Cronet Builder Asan': 'android_cronet_release_bot_minimal_symbols_arm_no_neon_clang_asan',
- 'Android Cronet Data Reduction Proxy Builder': 'android_cronet_data_reduction_proxy_release_bot_minimal_symbols_arm_no_neon',
'Android Cronet KitKat Builder': 'android_cronet_release_bot_minimal_symbols_arm_no_neon',
'Android Cronet Lollipop Builder': 'android_cronet_release_bot_minimal_symbols_arm_no_neon',
'Android Cronet Marshmallow 64bit Builder': 'android_cronet_release_bot_minimal_symbols_arm64',
'Android Cronet Marshmallow 64bit Perf': 'android_cronet_release_bot_minimal_symbols_arm64',
'Android Cronet x86 Builder': 'android_cronet_release_bot_minimal_symbols_x86',
'Android Cronet x86 Builder (dbg)': 'android_cronet_debug_static_bot_x86',
- 'Android N5X Swarm Builder': 'android_release_bot_minimal_symbols_arm64',
'Android arm Builder (dbg)': 'android_debug_static_bot',
'Android arm64 Builder (dbg)': 'android_debug_static_bot_arm64',
'Android x64 Builder (dbg)': 'android_debug_static_bot_x64',
@@ -53,8 +51,6 @@
'Cast Android (dbg)': 'android_cast_debug_static_bot',
'Deterministic Android': 'android_without_codecs_release_bot_minimal_symbols',
'Deterministic Android (dbg)': 'android_debug_bot',
- 'KitKat Phone Tester (rel)': 'android_release_bot_minimal_symbols',
- 'Marshmallow Phone Tester (rel)': 'android_release_bot_minimal_symbols_arm64',
'android-kitkat-arm-rel': 'android_release_bot_minimal_symbols',
'android-marshmallow-arm64-rel': 'android_release_bot_minimal_symbols_arm64',
},
@@ -62,11 +58,8 @@
'chromium.android.fyi': {
'Android Cronet Builder (dbg)': 'android_cronet_debug_static_bot_arm_no_neon',
'Android Cronet Builder Asan': 'android_cronet_release_bot_minimal_symbols_arm_no_neon_clang_asan',
- 'Android Cronet Data Reduction Proxy Builder': 'android_cronet_data_reduction_proxy_release_bot_minimal_symbols_arm_no_neon',
'Android Cronet KitKat Builder': 'android_cronet_release_bot_minimal_symbols_arm_no_neon',
'Memory Infra Tester': 'android_release_thumb_bot',
- 'NDK Next MIPS Builder':
- 'android_ndk_next_release_bot_minimal_symbols_mipsel',
'NDK Next arm Builder':
'android_ndk_next_release_bot_minimal_symbols',
'NDK Next arm64 Builder':
@@ -95,9 +88,6 @@
},
'chromium.chromiumos': {
- 'ChromiumOS amd64-generic Compile': 'cros_chrome_sdk',
- 'ChromiumOS daisy Compile': 'cros_chrome_sdk',
- 'Linux ChromiumOS Builder (dbg)': 'chromeos_with_codecs_debug_bot',
'Linux ChromiumOS Full': 'chromeos_with_codecs_release_bot',
'chromeos-amd64-generic-rel': 'cros_chrome_sdk',
@@ -127,10 +117,10 @@
'ToTAndroid64': 'android_clang_tot_release_arm64',
'ToTAndroid x64': 'android_clang_tot_x64',
'ToTLinux': 'clang_tot_linux_full_symbols_shared_release',
- 'ToTLinuxCoverage': 'clang_tot_coverage_minimal_symbols_shared_release',
+ 'ToTLinuxCoverage': 'clang_tot_coverage_minimal_symbols_shared_release_with_libfuzzer',
'ToTLinux (dbg)': 'clang_tot_shared_debug',
'ToTLinuxASan': 'clang_tot_asan_lsan_static_release',
- 'ToTLinuxASanLibfuzzer': 'release_libfuzzer_asan_clang_tot',
+ 'ToTLinuxASanLibfuzzer': 'libfuzzer_asan_clang_tot_release',
'ToTLinuxMSan': 'clang_tot_msan_release',
'ToTLinuxThinLTO': 'clang_tot_release_minimal_symbols_thin_lto_static_use_lld',
'ToTLinuxUBSanVptr': 'clang_tot_edge_ubsan_no_recover_hack_static_release',
@@ -153,25 +143,22 @@
},
'chromium.fyi': {
- 'Afl Upload Linux ASan': 'release_afl_asan',
+ 'Afl Upload Linux ASan': 'afl_asan_release_bot',
'Android Builder (dbg)': 'android_debug_static_bot_vrdata',
'Android Builder (dbg) Goma Canary': 'android_debug_static_bot_vrdata',
- 'Browser Side Navigation Linux': 'release_bot',
'CFI Linux CF': 'cfi_full_cfi_icall_cfi_diag_recover_release_static',
'CFI Linux ToT': 'clang_tot_cfi_full_cfi_icall_cfi_diag_thin_lto_release_static_dcheck_always_on',
'CFI Linux (icall)': 'cfi_full_diag_icall_release_static_dcheck_always_on',
'chromeos-amd64-generic-rel-goma-canary': 'cros_chrome_sdk',
- 'chromeos-amd64-generic-rel-vm-tests': 'cros_chrome_sdk',
+ 'chromeos-amd64-generic-rel-vm-tests': 'cros_chrome_sdk_headless_ozone',
'Linux Builder Goma Canary': 'release_bot',
'Linux x64 Goma Canary (clobber)': 'release_bot',
'Linux x64 Goma Canary LocalOutputCache': 'release_bot',
'mac-views-rel': 'mac_views_browser_release_bot',
- 'Chromium Mac 10.11': 'release_bot',
- 'Chromium Mac 10.11 Force Mac Toolchain': 'release_bot_mac_new_sdk',
'Chromium Mac 10.13': 'release_bot',
'Mac Builder Goma Canary': 'gpu_tests_release_bot',
@@ -180,15 +167,6 @@
'Mac Builder (dbg) Goma Canary (clobber)': 'debug_bot',
'Mac Goma Canary LocalOutputCache': 'release_bot_mac_strip',
- 'Chromium Win 10 GCE Tests': 'release_bot_minimal_symbols',
- 'Chromium Win PGO Builder': {
- '1': 'official_optimize_chrome_pgo_phase_1_x86',
- '2': 'official_optimize_chrome_pgo_phase_2_x86',
- },
- 'Chromium Win x64 PGO Builder': {
- '1': 'official_optimize_chrome_pgo_phase_1',
- '2': 'official_optimize_chrome_pgo_phase_2',
- },
'Chromium Windows Analyze': 'windows_analyze',
'Win7 Builder Goma Canary': 'release_bot_x86_minimal_symbols',
@@ -199,11 +177,9 @@
'Win Goma Canary LocalOutputCache': 'release_bot_x86_minimal_symbols',
'WinMSVC64 Goma Canary': 'win_msvc_release_bot',
- 'EarlGreyiOS': 'ios',
- 'Fuchsia (dbg)': 'debug_bot_fuchsia',
- 'Fuchsia ARM64': 'release_bot_fuchsia_arm64',
- 'Fuchsia x64': 'release_bot_fuchsia',
- 'Fuchsia': 'release_bot_fuchsia',
+ 'fuchsia-fyi-arm64-rel': 'release_bot_fuchsia_arm64',
+ 'fuchsia-fyi-x64-dbg': 'debug_bot_fuchsia',
+ 'fuchsia-fyi-x64-rel': 'release_bot_fuchsia',
'ios-device-goma-canary-clobber': 'ios',
@@ -212,19 +188,12 @@
'Jumbo Linux x64': 'jumbo_large_chunks_release_bot_minimal_symbols',
'Jumbo Mac': 'jumbo_release_bot_minimal_symbols',
'Jumbo Win x64': 'jumbo_release_bot_minimal_symbols',
- 'MD Top Chrome ChromeOS material-hybrid': 'chromeos_with_codecs_debug_bot',
- 'MD Top Chrome ChromeOS non-material': 'chromeos_with_codecs_debug_bot',
- 'MD Top Chrome Win material': 'debug_bot_minimal_symbols',
- 'MD Top Chrome Linux material': 'debug_bot',
- 'Libfuzzer Upload Linux ASan': 'release_libfuzzer_asan',
- 'Libfuzzer Upload Linux ASan Debug': 'debug_libfuzzer_asan',
- 'Libfuzzer Upload Linux MSan': 'release_libfuzzer_msan',
- 'Libfuzzer Upload Linux UBSan': 'release_libfuzzer_ubsan',
- 'Libfuzzer Upload Mac ASan': 'release_libfuzzer_mac_asan',
+ 'Libfuzzer Upload Linux ASan': 'libfuzzer_asan_release_bot',
+ 'Libfuzzer Upload Linux ASan Debug': 'libfuzzer_asan_debug_bot',
+ 'Libfuzzer Upload Linux MSan': 'libfuzzer_msan_release_bot',
+ 'Libfuzzer Upload Linux UBSan': 'libfuzzer_ubsan_release_bot',
+ 'Libfuzzer Upload Mac ASan': 'libfuzzer_mac_asan_release_bot',
'Linux ARM': 'release_bot_arm',
- 'Linux ARM (dbg)': 'debug_bot_arm',
- 'Linux ARM64': 'release_bot_arm64',
- 'Linux ARM64 (dbg)': 'debug_bot_arm64',
'Linux Clang Analyzer': 'linux_chromium_analysis',
'Linux remote_run Builder': 'release_bot',
'Linux remote_run Tester': 'release_bot',
@@ -239,18 +208,12 @@
'Mojo Android': 'android_release_bot_minimal_symbols_arm64',
'Mojo Linux': 'release_trybot',
'Mojo Windows': 'release_bot_x86_minimal_symbols',
- 'Out of Process Profiling Android': 'android_release_bot_minimal_symbols',
- 'Out of Process Profiling Linux': 'release_bot',
- 'Out of Process Profiling Mac': 'release_bot',
- 'Out of Process Profiling Windows': 'release_bot',
'Site Isolation Android': 'android_release_bot_minimal_symbols_arm64',
- 'Site Isolation Linux': 'release_trybot',
- 'Site Isolation Win': 'release_trybot_x86',
'VR Linux': 'vr_release_bot',
'Win 10 Fast Ring': 'release_trybot',
'Windows deterministic': 'release_bot_x86_minimal_symbols',
'Windows Clang deterministic': 'clang_release_bot_minimal_symbols_x86',
- 'Windows Clang Analyzer': 'windows_chromium_analysis',
+ 'win-annotator-rel': 'release_bot',
},
'chromium.goma': {
@@ -287,9 +250,13 @@
'Android FYI Release (Nexus 9)': 'android_release_trybot_arm64',
'Android FYI Release (NVIDIA Shield TV)': 'android_release_trybot_arm64',
'Android FYI 32 Vk Release (Nexus 5X)': 'gpu_tests_android_vulkan_release_trybot',
+ 'Android FYI 32 Vk Release (Pixel 2)': 'gpu_tests_android_vulkan_release_trybot',
'Android FYI 64 Vk Release (Nexus 5X)': 'gpu_tests_android_vulkan_release_trybot_arm64',
+ 'Android FYI 64 Vk Release (Pixel 2)': 'gpu_tests_android_vulkan_release_trybot_arm64',
'Android FYI 32 dEQP Vk Release (Nexus 5X)': 'deqp_android_vulkan_release_trybot',
+ 'Android FYI 32 dEQP Vk Release (Pixel 2)': 'deqp_android_vulkan_release_trybot',
'Android FYI 64 dEQP Vk Release (Nexus 5X)': 'deqp_android_vulkan_release_trybot_arm64',
+ 'Android FYI 64 dEQP Vk Release (Pixel 2)': 'deqp_android_vulkan_release_trybot_arm64',
'GPU FYI Linux Builder': 'gpu_fyi_tests_release_trybot',
'GPU FYI Linux Ozone Builder': 'gpu_fyi_tests_ozone_linux_system_gbm_libdrm_release_trybot',
'GPU FYI Linux Builder (dbg)': 'gpu_fyi_tests_debug_trybot',
@@ -403,8 +370,8 @@
'Linux Compile Perf FYI': 'official_goma_perf',
'Android Builder Perf FYI': 'official_goma_minimal_symbols_android',
'Android arm64 Builder Perf FYI': 'official_goma_minimal_symbols_android_arm64',
- 'Android CFI Builder Perf FYI': 'official_goma_minimal_symbols_android_cfi',
- 'Android CFI arm64 Builder Perf FYI': 'official_goma_minimal_symbols_android_cfi_arm64',
+ 'Android CFI Builder Perf FYI': 'official_goma_minimal_symbols_android_thin_lto',
+ 'Android CFI arm64 Builder Perf FYI': 'official_goma_minimal_symbols_android_thin_lto_arm64',
'Battor Agent Linux': 'release_bot',
'Battor Agent Mac': 'release_bot',
'Battor Agent Win': 'release_bot',
@@ -440,7 +407,7 @@
'client.v8.fyi': {
'Android Builder': 'official_goma_minimal_symbols_android',
'Android V8 FYI Release (Nexus 5X)': 'gpu_tests_android_release_trybot_arm64',
- 'Linux ASAN Builder': 'asan_lsan_release_bot',
+ 'Linux ASAN Builder': 'asan_lsan_release_trybot',
'Linux Debug Builder': 'debug_bot',
'Linux V8 FYI Release (NVIDIA)': 'gpu_tests_release_trybot',
'Linux Release - concurrent marking (NVIDIA)': 'gpu_tests_release_trybot_cm',
@@ -460,18 +427,11 @@
'chromium.webkit': {
'Android Builder': 'android_release_bot_minimal_symbols',
'WebKit Linux Trusty ASAN': 'asan_lsan_release_bot',
- 'WebKit Linux Trusty (dbg)': 'debug_bot',
'WebKit Linux Trusty Leak': 'release_bot',
'WebKit Linux Trusty MSAN': 'msan_release_bot',
- 'WebKit Linux Trusty': 'release_bot',
- 'WebKit Mac Builder (dbg)': 'debug_bot',
'WebKit Mac Builder': 'release_bot',
- 'WebKit Mac10.12 (retina)': 'release_bot',
- 'WebKit Mac10.12': 'release_bot',
- 'WebKit Win Builder (dbg)': 'debug_bot_x86_minimal_symbols',
+ 'WebKit Mac10.13 (retina)': 'release_bot',
'WebKit Win Builder': 'release_bot_x86_minimal_symbols',
- 'WebKit Win x64 Builder (dbg)': 'debug_bot_minimal_symbols',
- 'WebKit Win x64 Builder': 'release_bot_minimal_symbols',
},
'chromium.webrtc': {
@@ -521,18 +481,21 @@
# release trybots must *not* enable dchecks, because that could
# cause them to produce different baselines than the release
# waterfall bots, and run_web_tests.py can't handle that (by design).
- 'linux_trusty_blink_compile_dbg': 'debug_trybot',
- 'linux_trusty_blink_compile_rel': 'release_bot_minimal_symbols',
- 'linux_trusty_blink_dbg': 'debug_trybot',
+ 'linux-blink-rel': 'release_bot_minimal_symbols',
+ 'mac10.10-blink-rel': 'release_bot_minimal_symbols',
+ 'mac10.11-blink-rel': 'release_bot_minimal_symbols',
+ 'mac10.12-blink-rel': 'release_bot_minimal_symbols',
+ 'mac10.13-blink-rel': 'release_bot_minimal_symbols',
+ 'mac10.13_retina-blink-rel': 'release_bot_minimal_symbols',
+ 'win7-blink-rel': 'release_bot_x86_minimal_symbols',
+ 'win10-blink-rel': 'release_bot_x86_minimal_symbols',
+ # TODO(dpranke): Delete all the old names once things have been updated.
'linux_trusty_blink_rel': 'release_bot_minimal_symbols',
'mac10.10_blink_rel': 'release_bot_minimal_symbols',
'mac10.11_blink_rel': 'release_bot_minimal_symbols',
- 'mac10.12_retina_blink_rel': 'release_bot_minimal_symbols',
'mac10.12_blink_rel': 'release_bot_minimal_symbols',
'mac10.13_blink_rel': 'release_bot_minimal_symbols',
- 'win7_blink_compile_dbg': 'debug_trybot_x86_minimal_symbols',
- 'win7_blink_compile_rel': 'release_bot_x86_minimal_symbols',
- 'win7_blink_dbg': 'debug_trybot_x86_minimal_symbols',
+ 'mac10.13_retina_blink_rel': 'release_bot_minimal_symbols',
'win7_blink_rel': 'release_bot_x86_minimal_symbols',
'win10_blink_rel': 'release_bot_x86_minimal_symbols',
},
@@ -558,19 +521,21 @@
'android_mojo': 'android_release_trybot_arm64',
'android_n5x_swarming_dbg': 'android_debug_trybot_arm64',
- 'android_n5x_swarming_rel': 'android_release_trybot_arm64_no_symbols',
'android_optional_gpu_tests_rel': 'gpu_tests_android_release_trybot_arm64',
- 'android_unswarmed_n5_rel': 'android_release_trybot',
- 'android_unswarmed_n5x_rel': 'android_release_trybot_arm64',
+ 'android_unswarmed_pixel_aosp': 'android_debug_trybot_arm64',
'cast_shell_android': 'android_cast_debug_static_bot_compile_only',
+ 'gpu-manual-try-android-p-pixel-2-32': 'gpu_tests_android_vulkan_release_trybot',
'linux_android_dbg_ng': 'android_debug_trybot',
- 'linux_android_rel_ng': 'android_release_trybot',
},
# TODO(crbug/786044): Remove non-compile debug configs when migrated.
'tryserver.chromium.angle': {
'android_angle_rel_ng': 'gpu_tests_android_release_trybot_arm64',
+ 'android_angle_vk32_rel_ng': 'gpu_tests_android_vulkan_release_trybot',
+ 'android_angle_vk64_rel_ng': 'gpu_tests_android_vulkan_release_trybot_arm64',
'android_angle_deqp_rel_ng': 'deqp_android_release_trybot_arm64',
+ 'android_angle_vk32_deqp_rel_ng': 'deqp_android_vulkan_release_trybot',
+ 'android_angle_vk64_deqp_rel_ng': 'deqp_android_vulkan_release_trybot_arm64',
'linux_angle_ozone_rel_ng': 'gpu_fyi_tests_ozone_linux_system_gbm_libdrm_release_trybot',
'linux_angle_dbg_ng': 'gpu_fyi_tests_debug_trybot',
'linux_angle_deqp_rel_ng': 'deqp_release_trybot',
@@ -600,6 +565,7 @@
'closure_compilation': 'closure_compilation',
'fuchsia_arm64': 'release_trybot_fuchsia_arm64',
'fuchsia_arm64_cast_audio': 'release_trybot_fuchsia_arm64_cast_audio',
+ 'fuchsia-fyi-x64-dbg': 'debug_trybot_fuchsia',
'fuchsia_x64': 'release_trybot_fuchsia',
'fuchsia_x64_cast_audio': 'release_trybot_fuchsia_cast_audio',
'layout_test_leak_detection': 'release_trybot',
@@ -607,6 +573,8 @@
'linux-blink-gen-property-trees': 'release_trybot',
'linux-blink-heap-incremental-marking': 'debug_trybot_enable_blink_heap_incremental_marking',
'linux-blink-heap-verification-try': 'release_trybot_enable_blink_heap_verification',
+ 'linux-dcheck-off-rel': 'release_trybot_dcheck_off',
+ 'linux-goma-rbe-staging-rel': 'gpu_tests_release_trybot_no_symbols',
'linux-gcc-rel': 'release_bot_x86_minimal_symbols_no_clang_cxx11',
'linux-jumbo-rel': 'jumbo_release_bot_minimal_symbols',
'linux-ozone-rel': 'ozone_linux_release_trybot',
@@ -614,7 +582,6 @@
'linux_arm': 'release_trybot_arm',
'linux_chromium_archive_rel_ng': 'release_bot',
'linux_chromium_asan_rel_ng': 'asan_lsan_release_trybot',
- 'linux_chromium_browser_side_navigation_rel': 'release_trybot',
'linux_chromium_cfi_rel_ng': 'cfi_full_cfi_icall_cfi_diag_thin_lto_release_static_dcheck_always_on_goma',
'linux_chromium_chromeos_asan_rel_ng': 'asan_lsan_chromeos_release_trybot',
'linux_chromium_chromeos_msan_rel_ng': 'chromeos_msan_release_bot',
@@ -635,6 +602,7 @@
'linux_chromium_rel_ng': 'gpu_tests_release_trybot_no_symbols',
'linux_chromium_tsan_rel_ng': 'tsan_disable_nacl_release_trybot',
+ 'linux_chromium_ubsan_rel_ng': 'ubsan_vptr_release_trybot',
'linux_layout_tests_layout_ng': 'release_trybot',
'linux_layout_tests_root_layer_scrolls': 'release_trybot',
'linux_layout_tests_slimming_paint_v2': 'release_trybot',
@@ -643,7 +611,6 @@
'linux_nacl_sdk': 'release_bot',
'linux_nacl_sdk_build': 'release_bot',
'linux_optional_gpu_tests_rel': 'gpu_fyi_tests_release_trybot',
- 'linux_site_isolation': 'release_trybot',
'linux_upload_clang': 'release_bot',
'linux_vr': 'vr_release_trybot',
},
@@ -687,8 +654,10 @@
'gpu_manual_try_win7_nvidia_rel': 'gpu_fyi_tests_release_trybot_x86',
'win7_chromium_rel_ng': 'gpu_tests_release_trybot_x86_minimal_symbols',
'win7_chromium_rel_loc_exp': 'gpu_tests_release_trybot_x86_minimal_symbols',
+ 'win10_chromium_x64_dbg_ng': 'debug_trybot',
'win10_chromium_x64_rel_ng': 'release_trybot',
'win10_chromium_x64_rel_ng_exp': 'release_trybot',
+ 'win-annotator-rel': 'release_trybot',
'win-jumbo-rel': 'jumbo_release_bot_minimal_symbols',
'win_chromium_gn_upload': 'release_bot_x86_minimal_symbols',
'win_x64_archive': 'release_trybot',
@@ -701,14 +670,6 @@
'win_nacl_sdk': 'release_bot_x86_minimal_symbols',
'win_nacl_sdk_build': 'release_bot_x86_minimal_symbols',
'win_optional_gpu_tests_rel': 'gpu_fyi_tests_release_trybot_x86',
- 'win_pgo': {
- '1': 'official_optimize_chrome_pgo_phase_1_x86',
- '2': 'official_optimize_chrome_pgo_phase_2_x86',
- },
- 'win_pgo_x64': {
- '1': 'official_optimize_chrome_pgo_phase_1',
- '2': 'official_optimize_chrome_pgo_phase_2',
- },
'win_upload_clang': 'release_bot',
'win_chrome_official': 'official_goma_x86',
},
@@ -737,6 +698,10 @@
# is not necessarily so (i.e., we might have mac, win, and linux
# bots all using the 'release_bot' config).
'configs': {
+ 'afl_asan_release_bot': [
+ 'afl', 'asan', 'release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
+ ],
+
'android_binary_size': [
'android', 'chrome_with_codecs', 'goma', 'minimal_symbols', 'official_optimize',
],
@@ -785,11 +750,6 @@
'dcheck_always_on',
],
- 'android_cronet_data_reduction_proxy_release_bot_minimal_symbols_arm_no_neon': [
- 'android', 'cronet', 'release_bot', 'minimal_symbols', 'arm_no_neon',
- 'strip_debug_info',
- ],
-
'android_cronet_debug_static_bot_arm64': [
'android', 'cronet', 'debug_static_bot', 'arm64',
],
@@ -802,11 +762,6 @@
'android', 'cronet', 'debug_static_bot', 'x86',
],
- 'android_cronet_data_reduction_proxy_release_bot_minimal_symbols_arm_no_neon': [
- 'android', 'cronet', 'release_bot', 'minimal_symbols', 'arm_no_neon',
- 'strip_debug_info',
- ],
-
'android_cronet_debug_static_bot_arm64': [
'android', 'cronet', 'debug_static_bot', 'arm64',
],
@@ -903,10 +858,6 @@
'android', 'ndk_next', 'release_bot', 'minimal_symbols', 'arm64', 'strip_debug_info',
],
- 'android_ndk_next_release_bot_minimal_symbols_mipsel': [
- 'android', 'ndk_next', 'release_bot', 'minimal_symbols', 'mipsel', 'strip_debug_info',
- ],
-
'android_ndk_next_release_bot_minimal_symbols_x64': [
'android', 'ndk_next', 'release_bot', 'minimal_symbols', 'x64', 'strip_debug_info',
],
@@ -955,15 +906,15 @@
],
'asan_clang_edge_fuzzer_static_v8_heap_x86_full_symbols_release': [
- 'asan', 'clang_tot', 'edge', 'fuzzer', 'static', 'v8_heap', 'full_symbols', 'release', 'x86',
+ 'asan', 'clang_tot', 'edge', 'fuzzer', 'static', 'v8_heap', 'full_symbols', 'release', 'x64',
],
'asan_clang_shared_v8_heap_x86_full_symbols_release': [
- 'asan', 'clang_tot', 'shared', 'v8_heap', 'full_symbols', 'release', 'x86',
+ 'asan', 'clang_tot', 'shared', 'v8_heap', 'full_symbols', 'release', 'x64',
],
'asan_clang_fuzzer_static_v8_heap_x86_full_symbols_release': [
- 'asan', 'clang_tot', 'fuzzer', 'static', 'v8_heap', 'full_symbols', 'release', 'x86',
+ 'asan', 'clang_tot', 'fuzzer', 'static', 'v8_heap', 'full_symbols', 'release', 'x64',
],
'asan_dcheck_disable_nacl_release_bot': [
@@ -1081,7 +1032,7 @@
],
'chromeos_with_codecs_release_trybot': [
- 'chromeos_with_codecs', 'release_trybot', 'use_vaapi',
+ 'chromeos_with_codecs', 'release_trybot', 'use_vaapi', 'no_symbols',
],
'clang_release_bot_minimal_symbols_x86': [
@@ -1146,6 +1097,10 @@
'clang_tot', 'minimal_symbols', 'shared', 'release',
],
+ 'clang_tot_coverage_minimal_symbols_shared_release_with_libfuzzer': [
+ 'clang_tot', 'use_clang_coverage', 'minimal_symbols', 'shared', 'release', 'libfuzzer',
+ ],
+
'clang_tot_coverage_minimal_symbols_shared_release': [
'clang_tot', 'use_clang_coverage', 'minimal_symbols', 'shared', 'release',
],
@@ -1210,16 +1165,12 @@
'cros_chrome_sdk',
],
- 'debug_bot': [
- 'debug_bot',
- ],
-
- 'debug_bot_arm': [
- 'debug_bot', 'arm',
+ 'cros_chrome_sdk_headless_ozone': [
+ 'cros_chrome_sdk', 'ozone_platform_headless',
],
- 'debug_bot_arm64': [
- 'debug_bot', 'arm64',
+ 'debug_bot': [
+ 'debug_bot',
],
'debug_bot_enable_blink_heap_incremental_marking': [
@@ -1248,14 +1199,18 @@
'debug_bot', 'x86', 'minimal_symbols', 'no_com_init_hooks', 'chrome_with_codecs'
],
- 'debug_libfuzzer_asan': [
- 'debug', 'libfuzzer', 'asan', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl',
+ 'libfuzzer_asan_debug_bot': [
+ 'libfuzzer', 'asan', 'debug_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
],
'debug_trybot': [
'debug_trybot',
],
+ 'debug_trybot_fuchsia': [
+ 'debug_trybot', 'fuchsia',
+ ],
+
'debug_trybot_x86': [
'debug_trybot', 'x86',
],
@@ -1383,11 +1338,31 @@
'jumbo_non_goma_chunks', 'release_bot', 'minimal_symbols'
],
- 'linux_chromium_analysis': [
- 'analysis'
+ 'libfuzzer_asan_debug_bot': [
+ 'libfuzzer', 'asan', 'debug_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
+ ],
+ 'libfuzzer_asan_release_bot': [
+ 'libfuzzer', 'asan', 'release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
+ ],
+
+
+ 'libfuzzer_asan_clang_tot_release': [
+ 'libfuzzer', 'asan', 'clang_tot', 'release', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl',
+ ],
+
+ 'libfuzzer_mac_asan_release_bot': [
+ 'libfuzzer', 'asan', 'release_bot', 'chrome_with_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
+ ],
+
+ 'libfuzzer_msan_release_bot': [
+ 'libfuzzer', 'msan', 'release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
+ ],
+
+ 'libfuzzer_ubsan_release_bot': [
+ 'libfuzzer', 'ubsan_security', 'release_bot', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
],
- 'windows_chromium_analysis': [
+ 'linux_chromium_analysis': [
'analysis'
],
@@ -1431,34 +1406,18 @@
'official', 'goma', 'minimal_symbols', 'android', 'arm64',
],
- 'official_goma_minimal_symbols_android_cfi': [
- 'official', 'goma', 'minimal_symbols', 'android', 'cfi',
+ 'official_goma_minimal_symbols_android_thin_lto': [
+ 'official', 'goma', 'minimal_symbols', 'android', 'thin_lto',
],
- 'official_goma_minimal_symbols_android_cfi_arm64': [
- 'official', 'goma', 'minimal_symbols', 'android', 'cfi', 'arm64',
+ 'official_goma_minimal_symbols_android_thin_lto_arm64': [
+ 'official', 'goma', 'minimal_symbols', 'android', 'thin_lto', 'arm64',
],
'official_goma_x86': [
'official', 'goma', 'x86',
],
- 'official_optimize_chrome_pgo_phase_1': [
- 'official_optimize', 'chrome_pgo_phase_1',
- ],
-
- 'official_optimize_chrome_pgo_phase_1_x86': [
- 'official_optimize', 'chrome_pgo_phase_1', 'x86',
- ],
-
- 'official_optimize_chrome_pgo_phase_2': [
- 'official_optimize', 'chrome_pgo_phase_2',
- ],
-
- 'official_optimize_chrome_pgo_phase_2_x86': [
- 'official_optimize', 'chrome_pgo_phase_2', 'x86',
- ],
-
'ozone_linux_release_bot': [
'ozone_linux', 'release_bot',
],
@@ -1472,10 +1431,6 @@
'error',
],
- 'release_afl_asan': [
- 'release', 'afl', 'asan', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
- ],
-
'release_bot': [
'release_bot',
],
@@ -1484,10 +1439,6 @@
'release_bot', 'arm',
],
- 'release_bot_arm64': [
- 'release_bot', 'arm64',
- ],
-
'release_bot_chrome_with_codecs': [
'release_bot', 'chrome_with_codecs',
],
@@ -1512,10 +1463,6 @@
'release_bot', 'fuchsia', 'arm64', 'cast', 'cast_audio', 'no_symbols',
],
- 'release_bot_mac_new_sdk': [
- 'release_bot', 'mac_new_sdk',
- ],
-
'release_bot_mac_strip': [
'release_bot', 'mac_strip',
],
@@ -1546,30 +1493,14 @@
'release_bot', 'x86', 'minimal_symbols', 'no_com_init_hooks', 'chrome_with_codecs'
],
- 'release_libfuzzer_asan': [
- 'release', 'libfuzzer', 'asan', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
- ],
-
- 'release_libfuzzer_asan_clang_tot': [
- 'clang_tot', 'release', 'libfuzzer', 'asan', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl',
- ],
-
- 'release_libfuzzer_mac_asan': [
- 'release', 'libfuzzer', 'asan', 'chrome_with_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
- ],
-
- 'release_libfuzzer_msan': [
- 'release', 'libfuzzer', 'msan', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
- ],
-
- 'release_libfuzzer_ubsan': [
- 'release', 'libfuzzer', 'ubsan_security', 'chromeos_codecs', 'pdf_xfa', 'disable_nacl', 'optimize_for_fuzzing',
- ],
-
'release_trybot': [
'release_trybot',
],
+ 'release_trybot_dcheck_off': [
+ 'release_trybot', 'dcheck_off',
+ ],
+
'release_trybot_minimal_symbols': [
'release_trybot', 'minimal_symbols',
],
@@ -1634,6 +1565,10 @@
'ubsan_vptr', 'ubsan_no_recover_hack', 'release_bot',
],
+ 'ubsan_vptr_release_trybot': [
+ 'ubsan_vptr', 'ubsan_no_recover_hack', 'release_trybot',
+ ],
+
'v8_future_debug_bot': [
'v8_future', 'debug_bot',
],
@@ -1749,14 +1684,6 @@
'gn_args': 'use_cfi_recover=true',
},
- 'chrome_pgo_phase_1': {
- 'gn_args': 'chrome_pgo_phase=1 is_clang=false',
- },
-
- 'chrome_pgo_phase_2': {
- 'gn_args': 'chrome_pgo_phase=2 is_clang=false',
- },
-
'chrome_with_codecs': {
'mixins': ['ffmpeg_branding_chrome', 'proprietary_codecs'],
},
@@ -1822,6 +1749,10 @@
'gn_args': 'dcheck_always_on=true',
},
+ 'dcheck_off': {
+ 'gn_args': 'dcheck_always_on=false',
+ },
+
'debug': {
'gn_args': 'is_debug=true',
},
@@ -1910,10 +1841,6 @@
'mixins': ['chrome_with_codecs'],
},
- 'mac_new_sdk': {
- 'gn_args': 'mac_sdk_min="10.12"',
- },
-
'headless': {
'args_file': '//build/args/headless.gn',
},
@@ -1965,10 +1892,6 @@
'gn_args': 'symbol_level=1',
},
- 'mipsel': {
- 'gn_args': 'target_cpu="mipsel"',
- },
-
'msan': {
'gn_args': 'is_msan=true msan_track_origins=2 use_prebuilt_instrumented_libraries=true',
},
@@ -2023,6 +1946,10 @@
'use_xkbcommon=true use_ozone=true'),
},
+ 'ozone_platform_headless': {
+ 'gn_args': 'ozone_platform_headless=true',
+ },
+
'fuchsia': {
'gn_args': 'target_os="fuchsia"',
},
diff --git a/chromium/tools/metrics/actions/README.md b/chromium/tools/metrics/actions/README.md
index 6b0a82c0988..71614931dd7 100644
--- a/chromium/tools/metrics/actions/README.md
+++ b/chromium/tools/metrics/actions/README.md
@@ -13,6 +13,9 @@ enable different analyses. They're complementary.
## Coding (Emitting to User Actions)
+Generally you'll want to call `base::RecordAction()`, which is defined in
+[https://cs.chromium.org/chromium/src/base/metrics/user_metrics.h](user_metrics.h).
+
### Emit at a High-Level, not Deep in the Implementation
Prefer to emit at the highest level reasonable, closest to the code that handles
@@ -116,6 +119,12 @@ different interpretations of the data and make no sense.
## Documenting User Actions
+Document user actions in [actions.xml](./actions.xml). There is also a
+[google-internal version of the file](http://go/chrome-user-actions-internal)
+for the rare case when the user action is confidential (added only to Chrome
+code, not Chromium code; or, an accurate description about how to interpret the
+user action would reveal information about Google's plans).
+
### Add User Actions and Documentation in the Same Changelist
If possible, please add the actions.xml description in the same changelist in
@@ -155,13 +164,16 @@ actions.xml allows you to annotate an action as `not_user_triggered="true"`. Th
feature should be used rarely. If you think you want to annotate your action
thusly, please re-review the best practices above.
-### Deleting User Action Entries
+## Deleting User Action Entries
Do not delete actions from actions.xml. Instead, mark unused user actions as
obsolete, annotating them with the associated date or milestone in the obsolete
tag entry. If your user action is being replaced by a new version, we suggest
noting that in the previous user action's description.
+A changelist that marks a user action as obsolete should be reviewed by all
+current owners.
+
Deleting user action entries would be bad if someone accidentally reused your
old user action name and which therefore corrupts new data with whatever old
data is still coming in. It's also useful to keep obsolete user action
diff --git a/chromium/tools/metrics/actions/actions.xml b/chromium/tools/metrics/actions/actions.xml
index 57f246d2b15..c65c22f4c75 100644
--- a/chromium/tools/metrics/actions/actions.xml
+++ b/chromium/tools/metrics/actions/actions.xml
@@ -1545,7 +1545,8 @@ should be able to be added at any place in this file.
<description>The infobar was created and shown.</description>
</action>
-<action name="Android.DownloadManager.CheckForExternallyRemovedItems">
+<action name="Android.DownloadManager.CheckForExternallyRemovedItems"
+ not_user_triggered="true">
<owner>dtrainor@chromium.org</owner>
<owner>twellington@chromium.org</owner>
<description>
@@ -1788,22 +1789,25 @@ should be able to be added at any place in this file.
</action>
<action name="Android.InstantApps.BannerDismissed">
- <owner>mariakhomenko@chromium.org</owner>
- <description>Promo banner for an instant app has been dismissed.</description>
+ <owner>thildebr@chromium.org</owner>
+ <description>
+ Infobar banner for an instant app has been dismissed by the user.
+ </description>
</action>
<action name="Android.InstantApps.BannerDismissedAppIsDefault">
<owner>thildebr@chromium.org</owner>
<description>
- A promo banner shown when opening the instant app is default has been
- dismissed.
+ Infobar banner shown when opening the instant app is default has been
+ dismissed. Infobar is shown for a default app when the user arrives on the
+ page via intra-site navigation.
</description>
</action>
<action name="Android.InstantApps.BannerOpen">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
<description>
- User clicked &quot;Open App&quot; button on the instant apps banner.
+ User clicked &quot;Open App&quot; button on the instant apps infobar.
</description>
</action>
@@ -1817,21 +1821,25 @@ should be able to be added at any place in this file.
</action>
<action name="Android.InstantApps.BannerShown" not_user_triggered="true">
- <owner>mariakhomenko@chromium.org</owner>
- <description>Promo banner for an instant app has been displayed.</description>
+ <owner>thildebr@chromium.org</owner>
+ <description>
+ Infobar advertising an instant app has been displayed.
+ </description>
</action>
<action name="Android.InstantApps.BannerShownAppIsDefault"
not_user_triggered="true">
<owner>thildebr@chromium.org</owner>
<description>
- Promo banner for an instant app has been displayed when opening the app is
- default.
+ Infobar for an instant app has been displayed when opening the app is
+ default. Infobar is shown for a default app when the user arrives on the
+ page via intra-site navigation.
</description>
</action>
<action name="Android.InstantApps.InstantAppsEligiblePageLoaded"
not_user_triggered="true">
+ <obsolete>Deleted as of June 8, 2018</obsolete>
<owner>mariakhomenko@chromium.org</owner>
<description>
A page finished loading in Chrome that could have been loaded in an Instant
@@ -1840,22 +1848,24 @@ should be able to be added at any place in this file.
</action>
<action name="Android.InstantApps.LaunchedByDefault" not_user_triggered="true">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
<description>
- An instant app was launched without any user prompting.
+ An instant app was launched without any user prompting during a navigation
+ within Chrome. This happens when the user has previously chosen to use the
+ Instant App by opening it through the infobar UI.
</description>
</action>
<action name="Android.InstantApps.LaunchedFromWebsiteSettingsPopup">
- <owner>mariakhomenko@chromium.org</owner>
<owner>tedchoc@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
<description>
An instant app was launched from the page info popup.
</description>
</action>
<action name="Android.InstantApps.OpenInstantAppButtonShown">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
<description>
Recorded when the user opened PageInfo dialog and saw a button to launch an
Instant App there.
@@ -1938,7 +1948,7 @@ should be able to be added at any place in this file.
</action>
<action name="Android.PhoneIntent">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>mpearson@chromium.org</owner>
<description>
A user clicked on a telephone number link in Chrome content.
</description>
@@ -3500,6 +3510,11 @@ should be able to be added at any place in this file.
<description>Please enter the description of this user action.</description>
</action>
+<action name="BrowserServices.TwaOpened">
+ <owner>peconn@chromium.org</owner>
+ <description>Recorded when a user opens a TWA.</description>
+</action>
+
<action name="Cancel">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<description>Please enter the description of this user action.</description>
@@ -3941,16 +3956,19 @@ should be able to be added at any place in this file.
</action>
<action name="ConflictBadge">
+ <obsolete>Deprecated as of 6/2018.</obsolete>
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<description>Please enter the description of this user action.</description>
</action>
<action name="ConflictingModuleNotificationDismissed">
+ <obsolete>Deprecated as of 6/2018.</obsolete>
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<description>Please enter the description of this user action.</description>
</action>
<action name="ConflictingModuleNotificationShown">
+ <obsolete>Deprecated as of 6/2018.</obsolete>
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<description>Please enter the description of this user action.</description>
</action>
@@ -4207,6 +4225,15 @@ should be able to be added at any place in this file.
</description>
</action>
+<action name="ContextualSuggestions.ContextMenu">
+ <owner>huayinz@chromium.org</owner>
+ <owner>twellington@chromium.com</owner>
+ <description>
+ Android: User used the context menu on a suggested item on the contextual
+ suggestions surface.
+ </description>
+</action>
+
<action name="ContextualSuggestions.Preference.Disabled">
<owner>huayinz@chromium.org</owner>
<owner>twellington@chromium.org</owner>
@@ -5113,6 +5140,7 @@ should be able to be added at any place in this file.
</action>
<action name="FileBrowser.ClickBreadcrumbs">
+ <owner>sashab@chromium.org</owner>
<owner>joelhockey@chromium.org</owner>
<description>
User clicked the breadcrumbs in order to return to a parent directory.
@@ -5120,31 +5148,43 @@ should be able to be added at any place in this file.
</action>
<action name="FileBrowser.CreateNewFolder">
- <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
- <description>Please enter the description of this user action.</description>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
+ <description>User created a new folder in the file manager app.</description>
</action>
<action name="FileBrowser.PhotoEditor.Edit">
- <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
- <description>Please enter the description of this user action.</description>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
+ <description>
+ User saved a photo over itself for the first time (i.e. edited the photo) in
+ the gallery app.
+ </description>
</action>
<action name="FileBrowser.PhotoEditor.View">
- <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
- <description>Please enter the description of this user action.</description>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
+ <description>
+ User loaded an image into an editing session in the gallery app.
+ </description>
</action>
<action name="FileBrowser.SelectSearch">
<owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<description>
- Chrome OS Files App: When the user focused the search field at the top of
- the file manager app.
+ User focused the search field at the top of the file manager app.
</description>
</action>
<action name="FileBrowser.SuggestApps.ShowDialog">
- <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
- <description>Please enter the description of this user action.</description>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
+ <description>
+ The embedded Chrome Web Store dialog was shown with suggested apps to open
+ the file in the file manager app.
+ </description>
</action>
<action name="FilterURLTermiate_About" not_user_triggered="true">
@@ -5778,951 +5818,51 @@ should be able to be added at any place in this file.
</action>
<action name="InProductHelp.Dismissed">
+ <owner>dtrainor@chromium.org</owner>
<owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
<description>The user dismissed the in-product help.</description>
</action>
<action name="InProductHelp.NotifyEvent.IPH">
- <owner>dtrainor@@chromium.org</owner>
+ <owner>dtrainor@chromium.org</owner>
<owner>nyquist@chromium.org</owner>
<description>The user triggered an event in in-product help.</description>
</action>
<action name="InProductHelp.NotifyUsedEvent.IPH">
- <owner>dtrainor@@chromium.org</owner>
+ <owner>dtrainor@chromium.org</owner>
<owner>nyquist@chromium.org</owner>
<description>The user triggered a used event in in-product help.</description>
</action>
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_BadgedReadingList">
- <owner>edchin@chromium.org</owner>
- <owner>gchatz@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether in-product help
- should be shown to the user.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_Bookmark">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether in-product help
- should be shown to the user.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_ChromeHomeExpand">
- <owner>twellington@chromium.org</owner>
- <owner>mdjones@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether the Chrome Home
- cold start in-product help should be shown to the user. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_ChromeHomeMenuHeader">
- <obsolete>Unused as of 03/2018</obsolete>
- <owner>twellington@chromium.org</owner>
- <owner>mdjones@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether the Chrome Home
- menu header in-product help should be shown to the user. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_ChromeHomePullToRefresh">
- <owner>twellington@chromium.org</owner>
- <owner>mdjones@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether the Chrome Home
- in-product help that is shown after a pull-to-refresh should be shown to the
- user. See //components/feature_engagement/README.md#Configuring-UMA for
- details.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_ContextualSearch">
- <obsolete>
- Replaced with
- InProductHelp.ShouldTriggerHelpUI.IPH_ContextualSearchWebSearch.
- </obsolete>
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether the Contextual
- Search in-product help should be shown to the user. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_ContextualSearchOptIn">
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether the in-product
- help related to opting-in for Contextual Search should be shown to the user.
- See //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_ContextualSearchPanel">
- <obsolete>
- Replaced with
- InProductHelp.ShouldTriggerHelpUI.IPH_ContextualSearchPromotePanelOpen.
- </obsolete>
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether the in-product
- help related to opening the Contextual Search panel should be shown to the
- user. See //components/feature_engagement/README.md#Configuring-UMA for
- details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUI.IPH_ContextualSearchPromotePanelOpen">
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether the in-product
- help related to opening the Contextual Search panel should be shown to the
- user. See //components/feature_engagement/README.md#Configuring-UMA for
- details.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_ContextualSearchPromoteTap">
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether the in-product
- help related to activation by tap for Contextual Search should be shown to
- the user. See //components/feature_engagement/README.md#Configuring-UMA for
- details.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_ContextualSearchTap">
- <obsolete>
- Replaced with
- InProductHelp.ShouldTriggerHelpUI.IPH_ContextualSearchPromoteTap.
- </obsolete>
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether the in-product
- help related to activation by tap for Contextual Search should be shown to
- the user. See //components/feature_engagement/README.md#Configuring-UMA for
- details.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_ContextualSearchWebSearch">
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether the Contextual
- Search in-product help should be shown to the user. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_ContextualSuggestions">
- <owner>twellington@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether the contextual
- suggestions in-product help should be shown to the user. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_DataSaverDetail">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether in-product help
- should be shown to the user.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_DataSaverPreview">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether in-product help
- should be shown to the user.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_DownloadHome">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether in-product help
- should be shown to the user.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_DownloadPage">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether in-product help
- should be shown to the user.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_DownloadPageScreenshot">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether in-product help
- should be shown to the user.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_HomePageButton">
- <owner>danielpark@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether in-product help
- should be shown to the user.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_IncognitoWindow">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether in-product help
- should be shown to the user.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_MediaDownload">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether in-product help
- should be shown to the user.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_NewIncognitoTabTip">
- <owner>edchin@chromium.org</owner>
- <owner>gchatz@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether in-product help
- should be shown to the user.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_NewTab">
+<action name="InProductHelp.ShouldTriggerHelpUI.IPH">
+ <owner>dtrainor@chromium.org</owner>
<owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether in-product help
- should be shown to the user.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_NewTabPageButton">
- <owner>danielpark@chromium.org</owner>
- <description>
- The feature engagement tracker tried to determine whether in-product help
- should be shown to the user.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUI.IPH_NewTabTip">
- <owner>edchin@chromium.org</owner>
- <owner>gchatz@chromium.org</owner>
<description>
The feature engagement tracker tried to determine whether in-product help
should be shown to the user.
</description>
</action>
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_BadgedReadingList">
- <owner>edchin@chromium.org</owner>
- <owner>gchatz@chromium.org</owner>
- <description>
- A user action that could have triggered In-Product Help did not.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_Bookmark">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action that could have triggered In-Product Help did not.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ChromeHomeExpand">
- <owner>twellington@chromium.org</owner>
- <owner>mdjones@chromium.org</owner>
- <description>
- A user action that could have triggered the Chrome Home cold start
- in-product help did not. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ChromeHomeMenuHeader">
- <obsolete>Unused as of 03/2018</obsolete>
- <owner>twellington@chromium.org</owner>
- <owner>mdjones@chromium.org</owner>
- <description>
- A user action that could have triggered the Chrome Home menu header
- in-product help did not. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ChromeHomePullToRefresh">
- <owner>twellington@chromium.org</owner>
- <owner>mdjones@chromium.org</owner>
- <description>
- A pull-to-refresh that could have triggered the Chrome Home in-product help
- did not. See //components/feature_engagement/README.md#Configuring-UMA for
- details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ContextualSearch">
- <obsolete>
- Replaced with
- InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ContextualSearchWebSearch.
- </obsolete>
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action that could have triggered the Contextual Search in-product
- help did not. See //components/feature_engagement/README.md#Configuring-UMA
- for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ContextualSearchOptIn">
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action that could have triggered the in-product help related to
- opting-in for Contextual Search did not. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ContextualSearchPanel">
- <obsolete>
- Replaced with
- InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ContextualSearchPromotePanelOpen.
- </obsolete>
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action that could have triggered the in-product help related to
- opening the Contextual Search panel did not. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ContextualSearchPromotePanelOpen">
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action that could have triggered the in-product help related to
- opening the Contextual Search panel did not. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ContextualSearchPromoteTap">
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action that could have triggered the in-product help related to
- activation by tap did not. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ContextualSearchTap">
- <obsolete>
- Replaced with
- InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ContextualSearchPromoteTap.
- </obsolete>
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action that could have triggered the in-product help related to
- activation by tap did not. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ContextualSearchWebSearch">
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action that could have triggered the Contextual Search in-product
- help did not. See //components/feature_engagement/README.md#Configuring-UMA
- for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_ContextualSuggestions">
- <owner>twellington@chromium.org</owner>
- <description>
- A user action that could have triggered the contextual suggestions
- in-product help did not. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_DataSaverDetail">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action that could have triggered In-Product Help did not.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_DataSaverPreview">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action that could have triggered In-Product Help did not.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_DownloadHome">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action that could have triggered In-Product Help did not.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_DownloadPage">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action that could have triggered In-Product Help did not.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_DownloadPageScreenshot">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action that could have triggered In-Product Help did not.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_HomePageButton">
- <owner>danielpark@chromium.org</owner>
- <description>
- A user action that could have triggered In-Product Help did not.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_IncognitoWindow">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action that could have triggered In-Product Help did not.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_MediaDownload">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action that could have triggered In-Product Help did not.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_NewIncognitoTabTip">
- <owner>edchin@chromium.org</owner>
- <owner>gchatz@chromium.org</owner>
- <description>
- A user action that could have triggered In-Product Help did not.
- </description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_NewTab">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action that could have triggered In-Product Help did not.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_NewTabPageButton">
- <owner>danielpark@chromium.org</owner>
- <description>
- A user action that could have triggered In-Product Help did not.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH_NewTabTip">
- <owner>edchin@chromium.org</owner>
- <owner>gchatz@chromium.org</owner>
- <description>
- A user action that could have triggered In-Product Help did not.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_BadgedReadingList">
- <owner>edchin@chromium.org</owner>
- <owner>gchatz@chromium.org</owner>
- <description>A user action triggered In-Product Help.</description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_Bookmark">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>A user action triggered In-Product Help.</description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ChromeHomeExpand">
- <owner>twellington@chromium.org</owner>
- <owner>mdjones@chromium.org</owner>
- <description>
- A user action triggered the Chrome Home cold start in-product help. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ChromeHomeMenuHeader">
- <obsolete>Unused as of 03/2018</obsolete>
- <owner>twellington@chromium.org</owner>
- <owner>mdjones@chromium.org</owner>
- <description>
- A user action triggered the Chrome Home menu header in-product help. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ChromeHomePullToRefresh">
- <owner>twellington@chromium.org</owner>
- <owner>mdjones@chromium.org</owner>
- <description>
- A pull-to-refresh triggered the Chrome Home in-product help. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ContextualSearch">
- <obsolete>
- Replaced with
- InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ContextualSearchWebSearch.
- </obsolete>
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action triggered the Contextual Search in-product help. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ContextualSearchOptIn">
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action triggered the in-product help related to opting-in for
- Contextual Search. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ContextualSearchPanel">
- <obsolete>
- Replaced with
- InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ContextualSearchPromotePanelOpen.
- </obsolete>
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action triggered the in-product help related to opening the
- Contextual Search panel. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ContextualSearchPromotePanelOpen">
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action triggered the in-product help related to opening the
- Contextual Search panel. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ContextualSearchPromoteTap">
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action triggered the in-product help related to activation by tap.
- See //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ContextualSearchTap">
- <obsolete>
- Replaced with
- InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ContextualSearchPromoteTap.
- </obsolete>
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action triggered the in-product help related to activation by tap.
- See //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ContextualSearchWebSearch">
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action triggered the Contextual Search in-product help. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_ContextualSuggestions">
- <owner>donnd@chromium.org</owner>
- <owner>mahmoudi@chromium.org</owner>
- <owner>twellington@chromium.org</owner>
- <description>
- A user action triggered the contextual suggestions in-product help. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_DataSaverDetail">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>A user action triggered In-Product Help.</description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_DataSaverPreview">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>A user action triggered In-Product Help.</description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_DownloadHome">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>A user action triggered In-Product Help.</description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_DownloadPage">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>A user action triggered In-Product Help.</description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_DownloadPageScreenshot">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>A user action triggered In-Product Help.</description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_HomePageButton">
- <owner>danielpark@chromium.org</owner>
- <description>A user action triggered In-Product Help.</description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_IncognitoWindow">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>A user action triggered In-Product Help.</description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_MediaDownload">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>A user action triggered In-Product Help.</description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_NewIncognitoTabTip">
- <owner>edchin@chromium.org</owner>
- <owner>gchatz@chromium.org</owner>
- <description>A user action triggered In-Product Help.</description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_NewTab">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>A user action triggered In-Product Help.</description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_NewTabPageButton">
- <owner>danielpark@chromium.org</owner>
- <description>A user action triggered In-Product Help.</description>
-</action>
-
-<action name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH_NewTabTip">
- <owner>edchin@chromium.org</owner>
- <owner>gchatz@chromium.org</owner>
- <description>A user action triggered In-Product Help.</description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_BadgedReadingList">
- <owner>edchin@chromium.org</owner>
- <owner>gchatz@chromium.org</owner>
- <description>
- A user action would have triggered In-Product Help, but the feature was
- configured for tracking only.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_Bookmark">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action would have triggered In-Product Help, but the feature was
- configured for tracking only.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_ChromeHomeExpand">
- <owner>twellington@chromium.org</owner>
- <owner>mdjones@chromium.org</owner>
- <description>
- A user action would have triggered the Chrome Home cold start in-product
- help, but the feature was configured for tracking only. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_ChromeHomeMenuHeader">
- <obsolete>Unused as of 03/2018</obsolete>
- <owner>twellington@chromium.org</owner>
- <owner>mdjones@chromium.org</owner>
- <description>
- A user action would have triggered the Chrome Home menu header in-product
- help, but the feature was configured for tracking only. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_ChromeHomePullToRefresh">
- <owner>twellington@chromium.org</owner>
- <owner>mdjones@chromium.org</owner>
- <description>
- A pull-to-refresh would have triggered the Chrome Home in-product help, but
- the feature was configured for tracking only. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_ContextualSuggestions">
- <owner>twellington@chromium.org</owner>
- <owner>mdjones@chromium.org</owner>
- <description>
- A user action would have triggered the contextual suggestions in-product
- help, but the feature was configured for tracking only. See
- //components/feature_engagement/README.md#Configuring-UMA for details.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_DataSaverDetail">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action would have triggered In-Product Help, but the feature was
- configured for tracking only.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_DataSaverPreview">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action would have triggered In-Product Help, but the feature was
- configured for tracking only.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_DownloadHome">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action would have triggered In-Product Help, but the feature was
- configured for tracking only.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_DownloadPage">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action would have triggered In-Product Help, but the feature was
- configured for tracking only.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_DownloadPageScreenshot">
- <owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action would have triggered In-Product Help, but the feature was
- configured for tracking only.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_HomePageButton">
- <owner>danielpark@chromium.org</owner>
- <description>
- A user action would have triggered In-Product Help, but the feature was
- configured for tracking only.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_IncognitoWindow">
+<action name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH">
+ <owner>dtrainor@chromium.org</owner>
<owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
<description>
- A user action would have triggered In-Product Help, but the feature was
- configured for tracking only.
+ A user action that could have triggered in-product help did not.
</description>
</action>
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_MediaDownload">
+<action name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH">
+ <owner>dtrainor@chromium.org</owner>
<owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
- <description>
- A user action would have triggered In-Product Help, but the feature was
- configured for tracking only.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_NewIncognitoTabTip">
- <owner>edchin@chromium.org</owner>
- <owner>gchatz@chromium.org</owner>
- <description>
- A user action would have triggered In-Product Help, but the feature was
- configured for tracking only.
- </description>
+ <description>A user action triggered in-product help.</description>
</action>
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_NewTab">
+<action name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH">
+ <owner>dtrainor@chromium.org</owner>
<owner>nyquist@chromium.org</owner>
- <owner>xingliu@chromium.org</owner>
<description>
- A user action would have triggered In-Product Help, but the feature was
- configured for tracking only.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_NewTabPageButton">
- <owner>danielpark@chromium.org</owner>
- <description>
- A user action would have triggered In-Product Help, but the feature was
- configured for tracking only.
- </description>
-</action>
-
-<action
- name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH_NewTabTip">
- <owner>edchin@chromium.org</owner>
- <owner>gchatz@chromium.org</owner>
- <description>
- A user action would have triggered In-Product Help, but the feature was
+ A user action would have triggered in-product help, but the feature was
configured for tracking only.
</description>
</action>
@@ -11104,6 +10244,24 @@ should be able to be added at any place in this file.
<description>Please enter the description of this user action.</description>
</action>
+<action name="MediaContextMenu_EnterPictureInPicture">
+ <owner>apacible@chromium.org</owner>
+ <owner>media-dev@chromium.org</owner>
+ <description>
+ User clicked on the contextual menu of a video player to enter
+ Picture-in-Picture mode.
+ </description>
+</action>
+
+<action name="MediaContextMenu_ExitPictureInPicture">
+ <owner>apacible@chromium.org</owner>
+ <owner>media-dev@chromium.org</owner>
+ <description>
+ User clicked on the contextual menu of a video player to exit
+ Picture-in-Picture mode.
+ </description>
+</action>
+
<action name="MediaContextMenu_Loop">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<description>Please enter the description of this user action.</description>
@@ -11553,7 +10711,7 @@ should be able to be added at any place in this file.
</action>
<action name="MobileExternalNavigationDispatched">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
<description>
Records when the system started a VIEW intent on a navigation click. This
happens when there is another application in the system that's not a browser
@@ -11563,7 +10721,7 @@ should be able to be added at any place in this file.
</action>
<action name="MobileExternalNavigationReceived">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
<description>
Records when a user was given a choice between using Chrome and an installed
app and chose Chrome.
@@ -12173,6 +11331,14 @@ should be able to be added at any place in this file.
<description>Please enter the description of this user action.</description>
</action>
+<action name="MobilePopupMenuSwipeToSelect">
+ <owner>gambard@chromium.org</owner>
+ <description>
+ The user selected an option in the Popup Menu without lifting the finger
+ from the LongPress action.
+ </description>
+</action>
+
<action name="MobilePreviewPageBack">
<obsolete>Deprecated as of 7/2015</obsolete>
<owner>ksimbili@chromium.org</owner>
@@ -12268,7 +11434,6 @@ should be able to be added at any place in this file.
</action>
<action name="MobileReceivedExternalIntent">
- <owner>mariakhomenko@chromium.org</owner>
<owner>tedchoc@chromium.org</owner>
<description>
A VIEW intent was received by the tabbed mode activity. This will combine
@@ -12280,7 +11445,6 @@ should be able to be added at any place in this file.
</action>
<action name="MobileReceivedExternalIntent.App">
- <owner>mariakhomenko@chromium.org</owner>
<owner>tedchoc@chromium.org</owner>
<description>
A VIEW intent was received by the tabbed mode activity from an external
@@ -12289,7 +11453,6 @@ should be able to be added at any place in this file.
</action>
<action name="MobileReceivedExternalIntent.Chrome">
- <owner>mariakhomenko@chromium.org</owner>
<owner>tedchoc@chromium.org</owner>
<description>
A VIEW intent was received by the tabbed mode activity from Chrome. This is
@@ -12336,6 +11499,42 @@ should be able to be added at any place in this file.
</description>
</action>
+<action name="MobileShareActionBookmarkThisPage">
+ <owner>gambard@chromium.org</owner>
+ <description>
+ The user pressed &quot;Bookmark&quot; from the share action menu.
+ </description>
+</action>
+
+<action name="MobileShareActionFindInPage">
+ <owner>gambard@chromium.org</owner>
+ <description>
+ The user pressed &quot;Find In Page&quot; from the share action menu.
+ </description>
+</action>
+
+<action name="MobileShareActionReadLater">
+ <owner>gambard@chromium.org</owner>
+ <description>
+ The user pressed &quot;Read Later&quot; from the share action menu.
+ </description>
+</action>
+
+<action name="MobileShareActionRequestDesktop">
+ <owner>gambard@chromium.org</owner>
+ <description>
+ The user pressed &quot;Request Desktop Site&quot; from the share action
+ menu.
+ </description>
+</action>
+
+<action name="MobileShareActionRequestMobile">
+ <owner>gambard@chromium.org</owner>
+ <description>
+ The user pressed &quot;Request Mobile Site&quot; from the share action menu.
+ </description>
+</action>
+
<action name="MobileShortcutAllBookmarks">
<obsolete>Deprecated as of 5/2015</obsolete>
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
@@ -12439,7 +11638,6 @@ should be able to be added at any place in this file.
</action>
<action name="MobileTabbedModeViewIntentFromApp">
- <owner>mariakhomenko@chromium.org</owner>
<owner>tedchoc@chromium.org</owner>
<description>
A VIEW intent was received by the tabbed mode activity from an external
@@ -12448,7 +11646,6 @@ should be able to be added at any place in this file.
</action>
<action name="MobileTabbedModeViewIntentFromChrome">
- <owner>mariakhomenko@chromium.org</owner>
<owner>tedchoc@chromium.org</owner>
<description>
A VIEW intent was received by the tabbed mode activity from Chrome.
@@ -12493,6 +11690,11 @@ should be able to be added at any place in this file.
<description>Please enter the description of this user action.</description>
</action>
+<action name="MobileTabStripShowTabGridMenu">
+ <owner>justincohen@chromium.org</owner>
+ <description>User long-pressed on the tab strip tab grid button.</description>
+</action>
+
<action name="MobileTabSwitched">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<description>Please enter the description of this user action.</description>
@@ -12521,6 +11723,14 @@ should be able to be added at any place in this file.
<description>Please enter the description of this user action.</description>
</action>
+<action name="MobileToolbarOmniboxAcceleratorTap">
+ <owner>mdjones@chromium.org</owner>
+ <owner>amaralp@chromium.org</owner>
+ <description>
+ User tapped the omnibox accelerator button in the bottom toolbar.
+ </description>
+</action>
+
<action name="MobileToolbarOmniboxShortcut">
<owner>gambard@chromium.org</owner>
<description>
@@ -12940,6 +12150,7 @@ should be able to be added at any place in this file.
</action>
<action name="Net.URLRequest_StartJob_InvalidReferrer">
+ <obsolete>Deprecated 6/2018.</obsolete>
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<description>Please enter the description of this user action.</description>
</action>
@@ -16061,6 +15272,84 @@ should be able to be added at any place in this file.
<description>Please enter the description of this user action.</description>
</action>
+<action name="ProfileChooser_AddressesClicked">
+ <owner>vasilii@chromium.org</owner>
+ <owner>ewald@chromium.org</owner>
+ <description>
+ User clicked 'Addresses' in the profile chooser menu.
+ </description>
+</action>
+
+<action name="ProfileChooser_CloseAllClicked">
+ <owner>vasilii@chromium.org</owner>
+ <owner>ewald@chromium.org</owner>
+ <description>
+ User clicked 'Close All Windows' in the profile chooser menu.
+ </description>
+</action>
+
+<action name="ProfileChooser_GuestClicked">
+ <owner>vasilii@chromium.org</owner>
+ <owner>ewald@chromium.org</owner>
+ <description>
+ User opened a guest session from the profile chooser menu.
+ </description>
+</action>
+
+<action name="ProfileChooser_ManageClicked">
+ <owner>vasilii@chromium.org</owner>
+ <owner>ewald@chromium.org</owner>
+ <description>
+ User clicked 'Manage people' in the profile chooser menu.
+ </description>
+</action>
+
+<action name="ProfileChooser_PasswordsClicked">
+ <owner>vasilii@chromium.org</owner>
+ <owner>ewald@chromium.org</owner>
+ <description>
+ User clicked 'Passwords' in the profile chooser menu.
+ </description>
+</action>
+
+<action name="ProfileChooser_PaymentsClicked">
+ <owner>vasilii@chromium.org</owner>
+ <owner>ewald@chromium.org</owner>
+ <description>
+ User clicked 'Payments' in the profile chooser menu.
+ </description>
+</action>
+
+<action name="ProfileChooser_ProfileClicked">
+ <owner>vasilii@chromium.org</owner>
+ <owner>ewald@chromium.org</owner>
+ <description>
+ User clicked a profile to switch in the profile chooser menu.
+ </description>
+</action>
+
+<action name="ProfileChooser_Show">
+ <owner>vasilii@chromium.org</owner>
+ <owner>ewald@chromium.org</owner>
+ <description>The user opened the profile chooser menu.</description>
+</action>
+
+<action name="ProfileChooser_SignInAgainClicked">
+ <owner>vasilii@chromium.org</owner>
+ <owner>ewald@chromium.org</owner>
+ <description>
+ User clicked 'Sign in again' in the profile chooser menu.
+ </description>
+</action>
+
+<action name="ProfileChooser_SignInAgainDisplayed">
+ <owner>vasilii@chromium.org</owner>
+ <owner>ewald@chromium.org</owner>
+ <description>
+ The profile chooser opened with 'Sign in again' button.
+ </description>
+</action>
+
<action name="Redo">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<description>Please enter the description of this user action.</description>
@@ -16165,6 +15454,14 @@ should be able to be added at any place in this file.
<description>Please enter the description of this user action.</description>
</action>
+<action name="RendererForegroundMainFrameOOM">
+ <owner>ssid@chromium.org</owner>
+ <owner>boliu@chromium.org</owner>
+ <description>
+ Recorded when a foreground main frame renderer OOM is observed.
+ </description>
+</action>
+
<action name="ReportBug">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<description>Please enter the description of this user action.</description>
@@ -16895,8 +16192,11 @@ should be able to be added at any place in this file.
</action>
<action name="ShowFileBrowserFullTab">
- <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
- <description>Please enter the description of this user action.</description>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
+ <description>
+ The user opened the file manager to a specific file or folder.
+ </description>
</action>
<action name="ShowHelpTab">
@@ -17593,6 +16893,8 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNewAccount_FromAvatarBubbleSignin">
+ <obsolete>Deprecated 08/2018</obsolete>
+ <owner>bsazonov@chromium.org</owner>
<owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
@@ -17602,6 +16904,8 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNewAccount_FromBookmarkBubble">
+ <obsolete>Deprecated 08/2018</obsolete>
+ <owner>bsazonov@chromium.org</owner>
<owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
@@ -17611,7 +16915,10 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNewAccount_FromBookmarkManager">
+ <obsolete>Deprecated 08/2018</obsolete>
+ <owner>bsazonov@chromium.org</owner>
<owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER, with a new
@@ -17620,6 +16927,8 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNewAccount_FromExtensionInstallBubble">
+ <obsolete>Deprecated 08/2018</obsolete>
+ <owner>bsazonov@chromium.org</owner>
<owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
@@ -17629,7 +16938,9 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNewAccount_FromNTPContentSuggestions">
+ <obsolete>Deprecated 08/2018</obsolete>
<owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_NTP_CONTENT_SUGGESTIONS, with a
@@ -17638,6 +16949,8 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNewAccount_FromPasswordBubble">
+ <obsolete>Deprecated 08/2018</obsolete>
+ <owner>bsazonov@chromium.org</owner>
<owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
@@ -17647,7 +16960,10 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNewAccount_FromRecentTabs">
+ <obsolete>Deprecated 08/2018</obsolete>
+ <owner>bsazonov@chromium.org</owner>
<owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS, with a new account.
@@ -17655,7 +16971,10 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNewAccount_FromSettings">
+ <obsolete>Deprecated 08/2018</obsolete>
+ <owner>bsazonov@chromium.org</owner>
<owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS, with a new account.
@@ -17663,14 +16982,303 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNewAccount_FromTabSwitcher">
+ <obsolete>Deprecated 08/2018</obsolete>
+ <owner>bsazonov@chromium.org</owner>
<owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER, with a new account.
</description>
</action>
+<action name="Signin_SigninNewAccountExistingAccount_FromAvatarBubbleSignin">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN, with a new
+ account, while Chrome already has other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountExistingAccount_FromBookmarkBubble">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE, with a new
+ account, while Chrome already has other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountExistingAccount_FromBookmarkManager">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER, with a new
+ account, while Chrome already has other accounts.
+ </description>
+</action>
+
+<action
+ name="Signin_SigninNewAccountExistingAccount_FromExtensionInstallBubble">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE, with a
+ new account, while Chrome already has other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountExistingAccount_FromNTPContentSuggestions">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_NTP_CONTENT_SUGGESTIONS, with a
+ new account, while Chrome already has other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountExistingAccount_FromPasswordBubble">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE, with a new
+ account, while Chrome already has other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountExistingAccount_FromRecentTabs">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS, with a new account,
+ while Chrome already has other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountExistingAccount_FromSettings">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS, with a new account,
+ while Chrome already has other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountExistingAccount_FromTabSwitcher">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER, with a new account,
+ while Chrome already has other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountNoExistingAccount_FromAvatarBubbleSignin">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN, with a new
+ account, while Chrome does not have other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountNoExistingAccount_FromBookmarkBubble">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE, with a new
+ account, while Chrome does not have other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountNoExistingAccount_FromBookmarkManager">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER, with a new
+ account, while Chrome does not have other accounts.
+ </description>
+</action>
+
+<action
+ name="Signin_SigninNewAccountNoExistingAccount_FromExtensionInstallBubble">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE, with a
+ new account, while Chrome does not have other accounts.
+ </description>
+</action>
+
+<action
+ name="Signin_SigninNewAccountNoExistingAccount_FromNTPContentSuggestions">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_NTP_CONTENT_SUGGESTIONS, with a
+ new account, while Chrome does not have other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountNoExistingAccount_FromPasswordBubble">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE, with a new
+ account, while Chrome does not have other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountNoExistingAccount_FromRecentTabs">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS, with a new account,
+ while Chrome does not have other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountNoExistingAccount_FromSettings">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS, with a new account,
+ while Chrome does not have other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountNoExistingAccount_FromTabSwitcher">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER, with a new account,
+ while Chrome does not have other accounts.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountPreDice_FromAvatarBubbleSignin">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_AVATAR_BUBBLE_SIGN_IN, with a new
+ account, on desktop pre-Dice.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountPreDice_FromBookmarkBubble">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_BUBBLE, with a new
+ account, on desktop pre-Dice.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountPreDice_FromBookmarkManager">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER, with a new
+ account, on desktop pre-Dice.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountPreDice_FromExtensionInstallBubble">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_EXTENSION_INSTALL_BUBBLE, with a
+ new account, on desktop pre-Dice.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountPreDice_FromNTPContentSuggestions">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_NTP_CONTENT_SUGGESTIONS, with a
+ new account, on desktop pre-Dice.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountPreDice_FromPasswordBubble">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_PASSWORD_BUBBLE, with a new
+ account, on desktop pre-Dice.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountPreDice_FromRecentTabs">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS, with a new account,
+ on desktop pre-Dice.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountPreDice_FromSettings">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS, with a new account, on
+ desktop pre-Dice.
+ </description>
+</action>
+
+<action name="Signin_SigninNewAccountPreDice_FromTabSwitcher">
+ <owner>bsazonov@chromium.org</owner>
+ <owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <description>
+ Recorded on sign in start from access point
+ signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER, with a new account,
+ on desktop pre-Dice.
+ </description>
+</action>
+
<action name="Signin_SigninNotDefault_FromAvatarBubbleSignin">
+ <owner>bsazonov@chromium.org</owner>
<owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
@@ -17680,6 +17288,7 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNotDefault_FromBookmarkBubble">
+ <owner>bsazonov@chromium.org</owner>
<owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
@@ -17689,7 +17298,9 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNotDefault_FromBookmarkManager">
+ <owner>bsazonov@chromium.org</owner>
<owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER, using another
@@ -17698,6 +17309,7 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNotDefault_FromExtensionInstallBubble">
+ <owner>bsazonov@chromium.org</owner>
<owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
@@ -17708,6 +17320,7 @@ should be able to be added at any place in this file.
<action name="Signin_SigninNotDefault_FromNTPContentSuggestions">
<owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_NTP_CONTENT_SUGGESTIONS, using
@@ -17716,6 +17329,7 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNotDefault_FromPasswordBubble">
+ <owner>bsazonov@chromium.org</owner>
<owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
@@ -17725,7 +17339,9 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNotDefault_FromRecentTabs">
+ <owner>bsazonov@chromium.org</owner>
<owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS, using another account
@@ -17734,7 +17350,9 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNotDefault_FromSettings">
+ <owner>bsazonov@chromium.org</owner>
<owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS, using another account
@@ -17743,7 +17361,9 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninNotDefault_FromTabSwitcher">
+ <owner>bsazonov@chromium.org</owner>
<owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER, using another
@@ -17762,6 +17382,7 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninWithDefault_FromAvatarBubbleSignin">
+ <owner>bsazonov@chromium.org</owner>
<owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
@@ -17771,6 +17392,7 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninWithDefault_FromBookmarkBubble">
+ <owner>bsazonov@chromium.org</owner>
<owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
@@ -17780,7 +17402,9 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninWithDefault_FromBookmarkManager">
+ <owner>bsazonov@chromium.org</owner>
<owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_BOOKMARK_MANAGER, using the
@@ -17789,6 +17413,7 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninWithDefault_FromExtensionInstallBubble">
+ <owner>bsazonov@chromium.org</owner>
<owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
@@ -17799,6 +17424,7 @@ should be able to be added at any place in this file.
<action name="Signin_SigninWithDefault_FromNTPContentSuggestions">
<owner>bsazonov@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_NTP_CONTENT_SUGGESTIONS, using the
@@ -17807,6 +17433,7 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninWithDefault_FromPasswordBubble">
+ <owner>bsazonov@chromium.org</owner>
<owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
@@ -17816,7 +17443,9 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninWithDefault_FromRecentTabs">
+ <owner>bsazonov@chromium.org</owner>
<owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_RECENT_TABS, using the default
@@ -17825,7 +17454,9 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninWithDefault_FromSettings">
+ <owner>bsazonov@chromium.org</owner>
<owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS, using the default
@@ -17834,7 +17465,9 @@ should be able to be added at any place in this file.
</action>
<action name="Signin_SigninWithDefault_FromTabSwitcher">
+ <owner>bsazonov@chromium.org</owner>
<owner>jlebel@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
<description>
Recorded on sign in start from access point
signin_metrics::AccessPoint::ACCESS_POINT_TAB_SWITCHER, using the default
@@ -18870,62 +18503,12 @@ should be able to be added at any place in this file.
<description>User opened a content suggestion.</description>
</action>
-<action name="Suggestions.ContextMenu.DownloadItem">
- <owner>mvanouwerkerk@chromium.org</owner>
- <owner>galinap@google.com</owner>
- <description>
- Android: User used the context menu to download a suggested item.
- </description>
-</action>
-
-<action name="Suggestions.ContextMenu.LearnMore">
- <owner>mvanouwerkerk@chromium.org</owner>
- <owner>peconn@chromium.org</owner>
- <description>
- Android: User used the context menu to follow the learn more link to product
- help.
- </description>
-</action>
-
-<action name="Suggestions.ContextMenu.OpenItemInIncognitoTab">
+<action name="Suggestions.ContextMenu">
<owner>mvanouwerkerk@chromium.org</owner>
<owner>galinap@google.com</owner>
<description>
- Android: User used the context menu to open a suggested item in an incognito
- tab.
- </description>
-</action>
-
-<action name="Suggestions.ContextMenu.OpenItemInNewTab">
- <owner>mvanouwerkerk@chromium.org</owner>
- <owner>galinap@google.com</owner>
- <description>
- Android: User used the context menu to open a suggested item in a new tab.
- </description>
-</action>
-
-<action name="Suggestions.ContextMenu.OpenItemInNewWindow">
- <owner>mvanouwerkerk@chromium.org</owner>
- <owner>galinap@google.com</owner>
- <description>
- Android: User used the context menu to open a suggested item in a new
- window.
- </description>
-</action>
-
-<action name="Suggestions.ContextMenu.RemoveItem">
- <owner>mvanouwerkerk@chromium.org</owner>
- <owner>galinap@google.com</owner>
- <description>
- Android: User used the context menu to remove a suggested item.
- </description>
-</action>
-
-<action name="Suggestions.ContextMenu.Shown">
- <owner>mvanouwerkerk@chromium.org</owner>
- <owner>galinap@google.com</owner>
- <description>
- Android: User opened the context menu on a suggested item.
+ Android: User used the context menu to download a suggested item on the new
+ tab page.
</description>
</action>
@@ -20334,6 +19917,7 @@ should be able to be added at any place in this file.
<action-suffix separator="_" ordering="suffix">
<suffix name="BadgedReadingList" label="For BadgedReadingList feature."/>
<suffix name="Bookmark" label="For Bookmark feature."/>
+ <suffix name="BottomToolbarTip" label="For BottomToolbarTip feature."/>
<suffix name="ChromeHomeExpand" label="For ChromeHomeExpand feature."/>
<suffix name="ChromeHomeMenuHeader"
label="For ChromeHomeMenuHeader feature."/>
@@ -20346,11 +19930,17 @@ should be able to be added at any place in this file.
label="For ContextualSearchPanel feature."/>
<suffix name="ContextualSearchPromotePanelOpen"
label="For ContextualSearchPromotePanelOpen feature."/>
+ <suffix name="ContextualSearchPromotePanelOpen"
+ label="For ContextualSearchPromotePanelOpen feature."/>
+ <suffix name="ContextualSearchPromoteTap"
+ label="For ContextualSearchPromoteTap feature."/>
<suffix name="ContextualSearchPromoteTap"
label="For ContextualSearchPromoteTap feature."/>
<suffix name="ContextualSearchTap" label="For ContextualSearchTap feature."/>
<suffix name="ContextualSearchWebSearch"
label="For ContextualSearchWebSearch feature."/>
+ <suffix name="ContextualSearchWebSearch"
+ label="For ContextualSearchWebSearch feature."/>
<suffix name="ContextualSuggestions"
label="For ContextualSuggestions feature."/>
<suffix name="DataSaverDetail" label="For DataSaverDetail feature."/>
@@ -20361,6 +19951,7 @@ should be able to be added at any place in this file.
label="For DownloadPageScreenshot feature."/>
<suffix name="HomePageButton" label="For HomePageButton feature."/>
<suffix name="IncognitoWindow" label="For IncognitoWindow feature."/>
+ <suffix name="LongPressToolbarTip" label="For LongPressToolbar feature."/>
<suffix name="MediaDownload" label="For MediaDownload feature."/>
<suffix name="NewIncognitoTabTip" label="For NewIncognitoTabTip feature."/>
<suffix name="NewTab" label="For NewTab feature."/>
@@ -20368,6 +19959,27 @@ should be able to be added at any place in this file.
<suffix name="NewTabTip" label="For NewTabTip feature."/>
<affected-action name="InProductHelp.NotifyEvent.IPH"/>
<affected-action name="InProductHelp.NotifyUsedEvent.IPH"/>
+ <affected-action name="InProductHelp.ShouldTriggerHelpUI.IPH"/>
+ <affected-action
+ name="InProductHelp.ShouldTriggerHelpUIResult.NotTriggered.IPH"/>
+ <affected-action
+ name="InProductHelp.ShouldTriggerHelpUIResult.Triggered.IPH"/>
+ <affected-action
+ name="InProductHelp.ShouldTriggerHelpUIResult.WouldHaveTriggered.IPH"/>
+</action-suffix>
+
+<action-suffix separator="." ordering="suffix">
+ <suffix name="DownloadItem" label="Download a suggested item."/>
+ <suffix name="LearnMore" label="Open the learn more link for product help."/>
+ <suffix name="OpenItemInIncognitoTab"
+ label="Open a suggested item in an incognito tab."/>
+ <suffix name="OpenItemInNewTab" label="Open a suggested item in a new tab."/>
+ <suffix name="OpenItemInNewWindow"
+ label="Open a suggested item in a new window."/>
+ <suffix name="RemoveItem" label="Remove a suggested item."/>
+ <suffix name="Shown" label="Context menu is opened."/>
+ <affected-action name="ContextualSuggestions.ContextMenu"/>
+ <affected-action name="Suggestions.ContextMenu"/>
</action-suffix>
</actions>
diff --git a/chromium/tools/metrics/histograms/README.md b/chromium/tools/metrics/histograms/README.md
index 669cc21e061..c11f4328f1f 100644
--- a/chromium/tools/metrics/histograms/README.md
+++ b/chromium/tools/metrics/histograms/README.md
@@ -8,8 +8,17 @@ range and/or the range is not possible to specify a priori).
[TOC]
+## Naming Your Histogram
+
+Histogram names should be in the form Group.Name or Group.Subgroup.Name,
+etc., where each group organizes related histograms.
+
## Coding (Emitting to Histograms)
+Generally you'll be best served by using one of the macros in
+[https://cs.chromium.org/chromium/src/base/metrics/histogram_macros.h](histogram_macros.h)
+if possible.
+
### Don't Use the Same Histogram Logging Call in Multiple Places
These logging macros and functions have long names and sometimes include extra
@@ -189,6 +198,39 @@ good reason (and consider whether [sparse histograms](#When-To-Use-Sparse-
Histograms) might work better for you in that case--they do not pre- allocate
their buckets).
+### Percentage or Ratio Histograms
+
+You can easily emit a percentage histogram using the
+UMA_HISTOGRAM_PERCENTAGE macro provided in
+[histogram_macros.h](https://cs.chromium.org/chromium/src/base/metrics/histogram_macros.h).
+You can also easily emit any ratio as a linear histogram (for equally
+sized buckets).
+
+For such histograms, you should think carefully about _when_ the values are
+emitted. Normally, you should emit values periodically at a set time interval,
+such as every 5 minutes. Conversely, we strongly discourage emitting values
+based on event triggers. For example, we do not recommend recording a ratio
+at the end of a video playback.
+
+Why? You typically cannot make decisions based on histograms whose values are
+recorded in response to an event, because such metrics can conflate heavy usage
+with light usage. It's easier to reason about metrics that route around this
+source of bias.
+
+Many developers have been bitten by this. For example, it was previously common
+to emit an actions-per-minute ratio whenever Chrome was backgrounded.
+Precisely, these metrics computed the number of uses of a particular action
+during a Chrome session, divided by length of time Chrome had been open.
+Sometimes, the recorded rate was based on a short interaction with Chrome – a
+few seconds or a minute. Other times, the recorded rate was based on a long
+interaction, tens of minutes or hours. These two situations are
+indistinguishable in the UMA logs – the recorded values can be identical.
+
+This inability to distinguish these two qualitatively different settings make
+such histograms effectively uninterpretable and not actionable. Emitting at a
+regular interval avoids the issue. Each value will represent the same amount of
+time (e.g., one minute of video playback).
+
### Local Histograms
Histograms can be added via [Local macros](https://codesearch.chromium.org/chromium/src/base/metrics/histogram_macros_local.h).
@@ -222,7 +264,7 @@ The code to record it becomes dead code, and should be removed from the
codebase along with marking the histogram definition as obsolete. However, if
histogram would remain useful, the expiration should be extended accordingly
before it becomes expired. If histogram you care about already expired, see
-[Expired Histogram Whitelist](###Expired histogram whitelist).
+[Expired Histogram Whitelist](#Expired-histogram-whitelist).
For all the new histograms the use of expiry attribute will be strongly
encouraged and enforced by Chrome metrics team through reviews.
@@ -266,8 +308,12 @@ emitted to when you expect and not emitted to at other times. Also check that
the values emitted to are correct. Finally, for count histograms, make sure
that buckets capture enough precision for your needs over the range.
+Pro tip: You can filter the set of histograms shown on `chrome://histograms` by
+specifying a prefix. For example, `chrome://histograms/Extensions.Load` will
+show only histograms whose names match the pattern "Extensions.Load*".
+
In addition to testing interactively, you can have unit tests examine the
-values emitted to histograms. See [histogram_tester.h](https://cs.chromium.org/chromium/src/base/test/histogram_tester.h)
+values emitted to histograms. See [histogram_tester.h](https://cs.chromium.org/chromium/src/base/test/metrics/histogram_tester.h)
for details.
## Interpreting the Resulting Data
@@ -296,6 +342,12 @@ about is good! But see the note below on [Deleting Histogram Entries](#Deleting
## Documenting Histograms
+Document histograms in [histograms.xml](./histograms.xml). There is also a
+[google-internal version of the file](http://go/chrome-histograms-internal) for
+the rare case when the histogram is confidential (added only to Chrome code,
+not Chromium code; or, an accurate description about how to interpret the
+histogram would reveal information about Google's plans).
+
### Add Histogram and Documentation in the Same Changelist
If possible, please add the [histograms.xml](./histograms.xml) description in
@@ -340,6 +392,9 @@ unused histograms as obsolete, annotating them with the associated date or
milestone in the obsolete tag entry. If your histogram is being replaced by a
new version, we suggest noting that in the previous histogram's description.
+A changelist that marks a histogram as obsolete should be reviewed by all
+current owners.
+
Deleting histogram entries would be bad if someone to accidentally reused your
old histogram name and thereby corrupts new data with whatever old data is still
coming in. It's also useful to keep obsolete histogram descriptions in
@@ -358,6 +413,9 @@ suffixes, annotate the element with the attribute `base="true"`. This instructs
tools not to treat the partial base name as a distinct histogram. Note that
suffixes can be applied recursively.
+You can also declare ownership of `<histogram_suffixes>`. If there's no owner
+specified, the generated histograms will inherit owners from the parents.
+
### Enum labels
_All_ histograms, including boolean and sparse histograms, may have enum labels
diff --git a/chromium/tools/metrics/histograms/enums.xml b/chromium/tools/metrics/histograms/enums.xml
index 32fec1fc3b7..02713f3fae2 100644
--- a/chromium/tools/metrics/histograms/enums.xml
+++ b/chromium/tools/metrics/histograms/enums.xml
@@ -360,6 +360,30 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="157" label="UMA_API_UNSELECT_ROW">unselectRow</int>
</enum>
+<enum name="AccessoryAction">
+ <int value="0" label="Automatic password generation selected"/>
+ <int value="1" label="'Manage all passwords' link selected"/>
+</enum>
+
+<enum name="AccessoryBarContents">
+ <int value="0" label="Without contents (should never be logged)"/>
+ <int value="1" label="With any content (should always be logged)"/>
+ <int value="2" label="With Tabs"/>
+ <int value="3" label="With Actions"/>
+ <int value="4" label="With Autofill Suggestions"/>
+</enum>
+
+<enum name="AccessorySheetTrigger">
+ <int value="0" label="Sheet was closed (user-triggered or automatic)"/>
+ <int value="1" label="User closed an accessory sheet"/>
+ <int value="2" label="User opened an accessory sheet"/>
+</enum>
+
+<enum name="AccessorySuggestionType">
+ <int value="0" label="USERNAME"/>
+ <int value="1" label="PASSWORD"/>
+</enum>
+
<enum name="AccessPasswordInSettingsEvent">
<int value="0" label="Viewed"/>
<int value="1" label="Copied"/>
@@ -410,6 +434,17 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="4" label="Better Ads Standard"/>
</enum>
+<enum name="ActiveDirectoryDomainJoinType">
+ <summary>
+ This list corresponds to the ways device could be joined to the Active
+ Directory domain.
+ </summary>
+ <int value="0" label="Joined without streamline configuration"/>
+ <int value="1"
+ label="Had streamline configuration set but did not unlock it"/>
+ <int value="2" label="Joined using streamline configuration"/>
+</enum>
+
<enum name="ActiveWindowShowType">
<int value="0" label="No Active Window"/>
<int value="1" label="Other"/>
@@ -564,6 +599,17 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="4" label="Not QUIC, destination different from origin"/>
</enum>
+<enum name="Android.ChildProcessBindingStateCombination">
+ <int value="0" label="No waived no moderate no strong"/>
+ <int value="1" label="No waived no moderate has strong"/>
+ <int value="2" label="No waived has moderate no strong"/>
+ <int value="3" label="No waived has moderate has strong"/>
+ <int value="4" label="Has waived no moderate no strong"/>
+ <int value="5" label="Has waived no moderate has strong"/>
+ <int value="6" label="Has waived has moderate no strong"/>
+ <int value="7" label="Has waived has moderate has strong"/>
+</enum>
+
<enum name="Android.DownloadManager.List.View.Actions">
<int value="0" label="OPEN"/>
<int value="1" label="RESUME"/>
@@ -984,6 +1030,19 @@ uploading your change for review. These are checked by presubmit scripts.
</int>
<int value="7" label="All GPU process crashes"/>
<int value="8" label="All renderer process crashes"/>
+ <int value="9"
+ label="Visible main frame renderer foreground intentional kill"/>
+ <int value="10"
+ label="Visible renderer foreground normal termination without minidump"/>
+ <int value="11"
+ label="Invisible renderer in foreground app with strong binding killed"/>
+ <int value="12"
+ label="Invisible renderer in foreground app with strong binding oom"/>
+ <int value="13"
+ label="Invisible renderer in foreground app with moderate binding
+ killed"/>
+ <int value="14"
+ label="Invisible renderer in foreground app with moderate binding oom"/>
</enum>
<enum name="AndroidResourceExtractionStatus">
@@ -1138,7 +1197,8 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="29" label="Service worker not offline capable"/>
<int value="30" label="Waiting for manifest to be fetched"/>
<int value="31" label="Waiting for installability check"/>
- <int value="32" label="No gesture associated with call to prompt"/>
+ <int value="32"
+ label="No gesture associated with call to prompt (removed Aug 2018)"/>
<int value="33" label="Waiting for native data"/>
<int value="34" label="App install dialog shown"/>
</enum>
@@ -1288,6 +1348,14 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="17" label="Window Exit Presentation Mode"/>
</enum>
+<enum name="AppListAppMovingType">
+ <int value="0" label="MOVE_INTO_FOLDER"/>
+ <int value="1" label="MOVE_OUT_OF_FOLDER"/>
+ <int value="2" label="MOVE_INTO_ANOTHER_FOLDER"/>
+ <int value="3" label="REORDER_IN_FOLDER"/>
+ <int value="4" label="REORDER_IN_TOP_LEVEL"/>
+</enum>
+
<enum name="AppListDoodleAction">
<obsolete>
App list doesn't support doodles anymore.
@@ -1481,6 +1549,16 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="3" label="Crashed"/>
</enum>
+<enum name="ArcEnableState">
+ <int value="0" label="Enabled not managed"/>
+ <int value="1" label="Disabled not managed"/>
+ <int value="2" label="Managed on"/>
+ <int value="3" label="Managed on but disabled"/>
+ <int value="4" label="Managed off"/>
+ <int value="5" label="Not allowed but enabled"/>
+ <int value="6" label="Not allowed"/>
+</enum>
+
<enum name="ArcIntentHandlerAction">
<summary>Defines Arc intent handler actions</summary>
<int value="0" label="Error"/>
@@ -1589,6 +1667,37 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="21" label="Already provisioned"/>
</enum>
+<enum name="ArcSupervisionTransitionResult">
+ <summary>
+ Defines Arc supervision transition success and failure reasons
+ </summary>
+ <int value="0" label="CloudDPC supervision was disabled successfully."/>
+ <int value="1" label="CloudDPC supervision was already disabled."/>
+ <int value="2" label="CloudDPC supervision was enabled successfully."/>
+ <int value="3" label="CloudDPC supervision was already enabled."/>
+ <int value="4" label="Invalid state returned from Chrome."/>
+ <int value="5"
+ label="Failed to disable CloudDPC due to an unspecified error."/>
+ <int value="6"
+ label="Failed to enable CloudDPC due to an unspecified error."/>
+</enum>
+
+<enum name="ArcUserInteraction">
+ <summary>Defines Arc User Interactions</summary>
+ <int value="0" label="Action not user initiated"/>
+ <int value="1" label="App started from launcher"/>
+ <int value="2" label="App started from launcher context menu"/>
+ <int value="3" label="App started from launcher search"/>
+ <int value="4" label="App started from launcher search context menu"/>
+ <int value="5" label="App started from launcher suggested apps"/>
+ <int value="6" label="App started from launcher suggested apps context menu"/>
+ <int value="7" label="App started from shelf"/>
+ <int value="8" label="App started from shelf context menu"/>
+ <int value="9" label="App started from settings"/>
+ <int value="10" label="Interaction with notification"/>
+ <int value="11" label="Interaction with app window"/>
+</enum>
+
<enum name="ArcVideoDecodeAcceleratorResult">
<summary>Defines ArcVideoDecodeAccelerator initialization status</summary>
<int value="0" label="SUCCESS"/>
@@ -1599,6 +1708,37 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="5" label="INSUFFICIENT_RESOURCES"/>
</enum>
+<enum name="AshGestureActionType">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="Omnibox pinch (deprecated, see crbug.com/826476)"/>
+ <int value="2" label="Omnibox scroll (deprecated, see crbug.com/826476)"/>
+ <int value="3" label="Tabstrip pinch (deprecated, see crbug.com/826476)"/>
+ <int value="4" label="Tabstrip scroll (deprecated, see crbug.com/826476)"/>
+ <int value="5" label="Bezel scroll"/>
+ <int value="6" label="Desktop scroll"/>
+ <int value="7" label="Desktop pinch"/>
+ <int value="8" label="Webpage pinch"/>
+ <int value="9" label="Webpage scroll"/>
+ <int value="10" label="Webpage tap"/>
+ <int value="11" label="Tabstrip tap (deprecated, see crbug.com/826476)"/>
+ <int value="12" label="Bezel down"/>
+ <int value="13"
+ label="Tab switched tap (deprecated, see Event.Touch.GestureType)"/>
+ <int value="14"
+ label="Active tab tap (deprecated, see Event.Touch.GestureType)"/>
+ <int value="15"
+ label="Tab close button tap (deprecated, see Event.Touch.GestureType)"/>
+ <int value="16"
+ label="New tab button tap (deprecated, see Event.Touch.GestureType)"/>
+ <int value="17"
+ label="Top edge of browser window tap (deprecated, see
+ Event.Touch.GestureType)"/>
+ <int value="18" label="Window size button tap"/>
+ <int value="19"
+ label="Area surrounding tabstrip tap (deprecated, see crbug.com/826476)"/>
+ <int value="20" label="Window resized double tap"/>
+</enum>
+
<enum name="AshNightLightDisplayCrtcCtmSupportType">
<summary>
Defines the possible displays' color transform matrix support types
@@ -1779,6 +1919,12 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="12" label="Other error (file missing)"/>
</enum>
+<enum name="AudioCaptureDeviceError">
+ <int value="0" label="No error"/>
+ <int value="1" label="Error during stream creation"/>
+ <int value="2" label="Error during active capture"/>
+</enum>
+
<enum name="AudioCaptureStartupResult">
<int value="0" label="OK"/>
<int value="1" label="Failed to create stream"/>
@@ -1935,6 +2081,12 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="4" label="Document destroyed"/>
</enum>
+<enum name="AudioRenderDeviceError">
+ <int value="0" label="No error"/>
+ <int value="1" label="Error during stream creation"/>
+ <int value="2" label="Error during active rendering"/>
+</enum>
+
<enum name="AudioRendererEvents">
<int value="0" label="Initialized"/>
<int value="1" label="Runtime error"/>
@@ -2165,6 +2317,7 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="9" label="Name not found on card or address profiles"/>
<int value="10" label="Card and/or addresses had conflicting names"/>
<int value="11" label="Get upload details RPC failed"/>
+ <int value="12" label="User requested to provide cardholder name"/>
</enum>
<enum name="AutofillCreditCardInfoBar">
@@ -2562,6 +2715,18 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="7" label="Previous button pressed (once)"/>
</enum>
+<enum name="AutofillLocalCardMigrationBubbleOffer">
+ <int value="0" label="Show requested"/>
+ <int value="1" label="Shown"/>
+</enum>
+
+<enum name="AutofillLocalCardMigrationBubbleUserInteraction">
+ <int value="0" label="User explicitly accepted bubble"/>
+ <int value="1" label="User explicitly denied bubble"/>
+ <int value="2" label="User navigated away from page while bubble showing"/>
+ <int value="3" label="User navigated away from page while bubble hidden"/>
+</enum>
+
<enum name="AutofillMacAddressBook">
<int value="0" label="Showed popup entry"/>
<int value="1" label="Selected popup entry"/>
@@ -2923,6 +3088,7 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="11" label="Offline content notification task"/>
<int value="12" label="WebAPK update task"/>
<int value="13" label="Download resumption task"/>
+ <int value="14" label="Feed refresh task"/>
</enum>
<enum name="BackgroundTracingState">
@@ -3141,9 +3307,11 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="171" label="RFH_BASE_URL_FOR_DATA_URL_SPECIFIED"/>
<int value="172" label="RFPH_ILLEGAL_UPLOAD_PARAMS"/>
<int value="173" label="OBSOLETE_SWDH_PROVIDER_CREATED_ILLEGAL_TYPE"/>
- <int value="174" label="SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_NOT_WINDOW"/>
- <int value="175" label="SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_SERVICE_WORKER"/>
- <int value="176" label="SWDH_PROVIDER_CREATED_DUPLICATE_ID"/>
+ <int value="174"
+ label="OBSOLETE_SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_NOT_WINDOW"/>
+ <int value="175"
+ label="OBSOLETE_SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_SERVICE_WORKER"/>
+ <int value="176" label="OBSOLETE_SWDH_PROVIDER_CREATED_DUPLICATE_ID"/>
<int value="177" label="OBSOLETE_SWDH_PROVIDER_CREATED_BAD_ID"/>
<int value="178" label="RFH_KEEP_ALIVE_HANDLE_REQUESTED_INCORRECTLY"/>
<int value="179" label="BFSI_INVALID_UNIQUE_ID"/>
@@ -3221,6 +3389,11 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="8"
label="CPMD_BAD_ORIGIN_SAVE_GENERATION_FIELD_DETECTED_BY_CLASSIFIER"/>
<int value="9" label="CPMD_BAD_ORIGIN_SHOW_FALLBACK_FOR_SAVING"/>
+ <int value="10" label="CPMD_BAD_ORIGIN_AUTOMATIC_GENERATION_STATUS_CHANGED"/>
+ <int value="11"
+ label="CPMD_BAD_ORIGIN_SHOW_MANUAL_PASSWORD_GENERATION_POPUP"/>
+ <int value="12" label="CPMD_BAD_ORIGIN_SHOW_PASSWORD_EDITING_POPUP"/>
+ <int value="13" label="CPMD_BAD_ORIGIN_GENERATION_AVAILABLE_FOR_FORM"/>
</enum>
<enum name="BadSyncDataReason">
@@ -3301,6 +3474,17 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="5" label="Blacklist disabled."/>
</enum>
+<enum name="BloatedRendererHandlingInBrowser">
+ <int value="0" label="Reloaded the bloated tab"/>
+ <int value="1" label="Cannot reload the bloated tab"/>
+ <int value="2" label="Cannot shutdown the renderer process"/>
+</enum>
+
+<enum name="BloatedRendererHandlingInResourceCoordinator">
+ <int value="0" label="Forwarded handling to the browser process"/>
+ <int value="1" label="Ignored due to multiple pages in the renderer process"/>
+</enum>
+
<enum name="BlobBrokenReason">
<int value="0" label="Unknown"/>
<int value="1" label="There is not enough memory to store this blob"/>
@@ -3338,6 +3522,13 @@ uploading your change for review. These are checked by presubmit scripts.
frozen."/>
</enum>
+<enum name="BlockStatusForClient3DAPIs">
+ <summary>The reason WebGL / Pepper3D were blocked, or not.</summary>
+ <int value="0" label="BLOCK_STATUS_NOT_BLOCKED"/>
+ <int value="1" label="BLOCK_STATUS_SPECIFIC_DOMAIN_BLOCKED"/>
+ <int value="2" label="BLOCK_STATUS_ALL_DOMAINS_BLOCKED"/>
+</enum>
+
<enum name="BluetoothAvailability">
<int value="0" label="Unexpected error"/>
<int value="1" label="Not available"/>
@@ -3923,6 +4114,11 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="1" label="Lacks Form Manager"/>
</enum>
+<enum name="BooleanFound">
+ <int value="0" label="Not found"/>
+ <int value="1" label="Found"/>
+</enum>
+
<enum name="BooleanFrameAsOverlay">
<int value="0" label="Frame was not allow_overlay"/>
<int value="1" label="Frame was allow_overlay"/>
@@ -4058,6 +4254,11 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="1" label="Incognito"/>
</enum>
+<enum name="BooleanInfinity">
+ <int value="0" label="Not Infinity"/>
+ <int value="1" label="Infinity"/>
+</enum>
+
<enum name="BooleanInForeground">
<int value="0" label="Background"/>
<int value="1" label="Foreground"/>
@@ -4073,6 +4274,11 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="1" label="Invalid"/>
</enum>
+<enum name="BooleanIsGenerationTriggeredManually">
+ <int value="0" label="Password generation was triggered automatically"/>
+ <int value="1" label="A user triggered password generation"/>
+</enum>
+
<enum name="BooleanIsLastSharedAppInfoRetrieved">
<int value="0" label="Not retrieved"/>
<int value="1" label="Retrieved"/>
@@ -4616,6 +4822,14 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="5" label="App provided items"/>
</enum>
+<enum name="BrowserGestureActionType">
+ <int value="0" label="Tab switched tap"/>
+ <int value="1" label="Active tab tap"/>
+ <int value="2" label="Tab close button tap"/>
+ <int value="3" label="New tab button tap"/>
+ <int value="4" label="Top edge of browser window tap"/>
+</enum>
+
<enum name="BrowserServicesVerificationResult">
<summary>Result of Trusted Web Activity verification attempt.</summary>
<int value="0" label="Online Success"/>
@@ -5035,6 +5249,11 @@ histogram as enum -->
<int value="3" label="Primary Error, Secondary Valid"/>
<int value="4" label="Both Valid, Different Details"/>
<int value="5" label="Both Error, Different Details"/>
+ <int value="6" label="Ignored Mac Undesired Revocation Checking"/>
+ <int value="7" label="Ignored Multiple EV Policies and One Matches Root"/>
+ <int value="8"
+ label="Ignored Differing Path After Reverifying With Trial Chain"/>
+ <int value="9" label="Ignored Locally Trusted Leaf Cert"/>
</enum>
<enum name="ChannelLayout">
@@ -5166,6 +5385,13 @@ histogram as enum -->
<int value="2" label="Periodic"/>
</enum>
+<enum name="ChromeOSMessageCenterScrollActionReason">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="By mouse wheel"/>
+ <int value="2" label="By touch"/>
+ <int value="3" label="By arrow key"/>
+</enum>
+
<enum name="ChromeOSPlatformVerificationExpiryStatus">
<summary>
Possible results of a platform verification expiry check. See
@@ -6458,6 +6684,8 @@ Called by update_net_error_codes.py.-->
<int value="-202" label="CERT_AUTHORITY_INVALID"/>
<int value="-201" label="CERT_DATE_INVALID"/>
<int value="-200" label="CERT_COMMON_NAME_INVALID"/>
+ <int value="-179" label="WRONG_VERSION_ON_EARLY_DATA"/>
+ <int value="-178" label="EARLY_DATA_REJECTED"/>
<int value="-177" label="SSL_CLIENT_AUTH_NO_COMMON_ALGORITHMS"/>
<int value="-176" label="NO_BUFFER_SPACE"/>
<int value="-175" label="SSL_VERSION_INTERFERENCE"/>
@@ -6654,6 +6882,12 @@ Called by update_net_error_codes.py.-->
<int value="2" label="Will use composited scrolling"/>
</enum>
+<enum name="CompositorFrameSinkSubmitResult">
+ <int value="0" label="Accepted"/>
+ <int value="1" label="CopyOutputResults not allowed"/>
+ <int value="2" label="Surface Invariants Violation"/>
+</enum>
+
<enum name="CompositorScrollResult">
<int value="0" label="ScrollOnMainThread"/>
<int value="1" label="ScrollStarted"/>
@@ -6952,6 +7186,7 @@ Called by update_net_error_codes.py.-->
<int value="12" label="MIDI_SYSEX"/>
<int value="13" label="SOUND"/>
<int value="14" label="FRAMEBUST"/>
+ <int value="16" label="SENSORS"/>
</enum>
<enum name="ContentSettingMixedScriptAction">
@@ -6981,6 +7216,11 @@ Called by update_net_error_codes.py.-->
<int value="6" label="Clicked 'Always show on mobile'"/>
</enum>
+<enum name="ContentSettings.EphemeralFlashPermission">
+ <int value="0" label="The First time permission is granted to a host."/>
+ <int value="1" label="Subsequant grants to a host."/>
+</enum>
+
<enum name="ContentSettingScheme">
<int value="0" label="(wildcard)"/>
<int value="1" label="(other)"/>
@@ -7506,6 +7746,7 @@ Called by update_net_error_codes.py.-->
<int value="12" label="Suggestion clicked"/>
<int value="13" label="UI dismissed without open"/>
<int value="14" label="UI dismissed after open"/>
+ <int value="15" label="UI button shown"/>
</enum>
<enum name="CookieCommitProblem">
@@ -7805,6 +8046,7 @@ Called by update_net_error_codes.py.-->
<int value="29" label="RESULT_CODE_SXS_MIGRATION_FAILED_NOT_USED"/>
<int value="30" label="RESULT_CODE_ACTION_DISALLOWED_BY_POLICY"/>
<int value="31" label="RESULT_CODE_INVALID_SANDBOX_STATE"/>
+ <int value="32" label="RESULT_CODE_CLOUD_POLICY_ENROLLMENT_FAILED"/>
<int value="131" label="SIGQUIT"/>
<int value="132" label="SIGILL"/>
<int value="133" label="SIGTRAP"/>
@@ -8138,6 +8380,11 @@ Called by update_net_error_codes.py.-->
<int value="8" label="Auto sign-in"/>
</enum>
+<enum name="CreditCardUploadDisallowedNetwork">
+ <int value="0" label="Elo card"/>
+ <int value="1" label="JCB card"/>
+</enum>
+
<enum name="CrosBeamformingDeviceState">
<int value="0" label="Default enabled"/>
<int value="1" label="User enabled"/>
@@ -8153,6 +8400,11 @@ Called by update_net_error_codes.py.-->
<int value="4" label="COMPATIBILITY_CHECK_FAILED"/>
</enum>
+<enum name="CrosDictationToggleDictationMethod">
+ <int value="0" label="Search+D"/>
+ <int value="1" label="Click onscreen button"/>
+</enum>
+
<enum name="CrosDisksArchiveType">
<int value="0" label="Unknown"/>
<int value="1" label="ZIP"/>
@@ -8338,6 +8590,11 @@ Called by update_net_error_codes.py.-->
<int value="7" label="Error Starting Container"/>
</enum>
+<enum name="CrostiniUISurface">
+ <int value="0" label="Settings"/>
+ <int value="1" label="App List"/>
+</enum>
+
<enum name="CrostiniUninstallResult">
<int value="0" label="User Cancelled"/>
<int value="1" label="Error"/>
@@ -8651,6 +8908,22 @@ Called by update_net_error_codes.py.-->
<int value="3" label="Connected to service with KeepAlive connection"/>
</enum>
+<enum name="CustomTabsDynamicModuleLoadResult">
+ <int value="0" label="Loaded new instance successfully"/>
+ <int value="1" label="Used cached instance"/>
+ <int value="2" label="Not loaded because the feature is disabled"/>
+ <int value="3" label="Not loaded because the package is not Google-signed"/>
+ <int value="4"
+ label="Not loaded because the package name could not be found"/>
+ <int value="5"
+ label="Not loaded because the entry point class could not be found"/>
+ <int value="6"
+ label="Not loaded because the entry point class could not be
+ instantiated"/>
+ <int value="7"
+ label="Loaded but the host and module versions are incompatible"/>
+</enum>
+
<enum name="CustomTabsParallelRequestStatusOnStart">
<int value="0" label="No Parallel Request was requested"/>
<int value="1" label="Parallel request successfully started"/>
@@ -8716,6 +8989,24 @@ Called by update_net_error_codes.py.-->
<int value="14" label="D3D11CreateDevice returned DXGI_ERROR_DEVICE_HUNG"/>
</enum>
+<enum name="D3D11VideoNotSupportedReason">
+ <int value="0" label="kVideoIsSupported">
+ Video is not disqualified from potential playback.
+ </int>
+ <int value="1" label="kInsufficientD3D11FeatureLevel">
+ D3D11 is not 11.1 or later.
+ </int>
+ <int value="2" label="kProfileNotSupported">
+ A supported video codec is using the an unsupported profile.
+ </int>
+ <int value="3" label="kZeroCopyNv12Required">
+ The GPU is not configured to allow zero copy for nv12.
+ </int>
+ <int value="4" label="kZeroCopyVideoRequired">
+ The GPU is not configured to allow zero copy for videos.
+ </int>
+</enum>
+
<enum name="D3D12FeatureLevel">
<int value="0" label="D3D_FEATURE_LEVEL_UNKNOWN"/>
<int value="1" label="D3D_FEATURE_LEVEL_12_0"/>
@@ -9112,6 +9403,9 @@ Called by update_net_error_codes.py.-->
</enum>
<enum name="DataUsageReportSubmissionResult">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<int value="0" label="Successful"/>
<int value="1" label="Failed"/>
<int value="2" label="Timed out"/>
@@ -9119,6 +9413,9 @@ Called by update_net_error_codes.py.-->
</enum>
<enum name="DataUsageTrackingSessionEndReason">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<int value="0" label="Omnibox search navigation"/>
<int value="1" label="Omnibox navigation"/>
<int value="2" label="Bookmark navigation"/>
@@ -9126,6 +9423,9 @@ Called by update_net_error_codes.py.-->
</enum>
<enum name="DataUsageTrackingSessionStartReason">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<int value="0" label="Package regex match in Custom Tab"/>
<int value="1" label="Omnibox search navigation"/>
<int value="2" label="Omnibox navigation"/>
@@ -9135,6 +9435,9 @@ Called by update_net_error_codes.py.-->
</enum>
<enum name="DataUsageUIAction">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<int value="0" label="Data use tracking started snackbar shown"/>
<int value="1"
label="Data use tracking started snackbar 'More' link clicked"/>
@@ -9826,6 +10129,9 @@ Called by update_net_error_codes.py.-->
</enum>
<enum name="DidNavigateToAd">
+ <obsolete>
+ Removed July 2018.
+ </obsolete>
<int value="0" label="Navigated to Non-Ad"/>
<int value="1" label="Navigated to Ad"/>
</enum>
@@ -10432,6 +10738,7 @@ Called by update_net_error_codes.py.-->
<int value="5" label="CANCEL"/>
<int value="6" label="OUT_OF_RETRIES"/>
<int value="7" label="OUT_OF_RESUMPTIONS"/>
+ <int value="8" label="UPLOAD_TIMEOUT"/>
</enum>
<enum name="Download.Service.EntryEvent">
@@ -10662,6 +10969,7 @@ Called by update_net_error_codes.py.-->
<int value="9" label="ClearAll"/>
<int value="10" label="OpenFolder"/>
<int value="11" label="Resume"/>
+ <int value="12" label="RetryDownload"/>
</enum>
<enum name="DownloadedFileAction">
@@ -11082,6 +11390,15 @@ Called by update_net_error_codes.py.-->
<int value="306" label="shtml"/>
<int value="307" label="shtm"/>
<int value="308" label="sht"/>
+ <int value="309" label="slk"/>
+ <int value="310" label="applescript"/>
+ <int value="311" label="scpt"/>
+ <int value="312" label="scptd"/>
+ <int value="313" label="seplugin"/>
+ <int value="314" label="osas"/>
+ <int value="315" label="osax"/>
+ <int value="316" label="settingcontent-ms"/>
+ <int value="317" label="oxt"/>
</enum>
<enum name="DownloadItem.DangerType">
@@ -11251,6 +11568,15 @@ Called by update_net_error_codes.py.-->
<int value="1" label="Touch"/>
</enum>
+<enum name="DrawResult">
+ <int value="0" label="Invalid"/>
+ <int value="1" label="Success"/>
+ <int value="2" label="Abort: checkerboard animation"/>
+ <int value="3" label="Abort: missing high res"/>
+ <int value="4" label="Abort: cannot draw"/>
+ <int value="5" label="Abort: draining pipeline"/>
+</enum>
+
<enum name="DriveApiErrorCode">
<!-- Generated from google_apis/drive/drive_api_error_codes.h -->
@@ -11623,10 +11949,12 @@ Called by update_net_error_codes.py.-->
<int value="3" label="SENT_START_WORKER"/>
<int value="4" label="SCRIPT_DOWNLOADING"/>
<int value="5" label="SCRIPT_LOADED"/>
- <int value="6" label="SCRIPT_EVALUATED"/>
+ <int value="6" label="SCRIPT_EVALUATED (obsolete)"/>
<int value="7" label="THREAD_STARTED"/>
<int value="8" label="SCRIPT_READ_STARTED"/>
<int value="9" label="SCRIPT_READ_FINISHED"/>
+ <int value="10" label="SCRIPT_STREAMING"/>
+ <int value="11" label="SCRIPT_EVALUATION"/>
</enum>
<enum name="EmmcLifeUsed">
@@ -13558,7 +13886,7 @@ Called by update_net_error_codes.py.-->
<int value="441" label="ChromeCleanupEnabled"/>
<int value="442" label="ChromeCleanupReportingEnabled"/>
<int value="443" label="DeveloperToolsAvailability"/>
- <int value="444" label="AllowedLocales"/>
+ <int value="444" label="AllowedUILocales"/>
<int value="445" label="IsolateOriginsAndroid"/>
<int value="446" label="SitePerProcessAndroid"/>
<int value="447" label="ArcAppInstallEventLoggingEnabled"/>
@@ -13566,6 +13894,16 @@ Called by update_net_error_codes.py.-->
<int value="449" label="ArcBackupRestoreServiceEnabled"/>
<int value="450" label="ArcGoogleLocationServicesEnabled"/>
<int value="451" label="EnableSyncConsent"/>
+ <int value="452" label="ContextualSuggestionsEnabled"/>
+ <int value="453" label="DeviceAutoUpdateTimeRestrictions"/>
+ <int value="454" label="PromotionalTabsEnabled"/>
+ <int value="455" label="SafeSitesFilterBehavior"/>
+ <int value="456" label="AllowedInputMethods"/>
+ <int value="457" label="OverrideSecurityRestrictionsOnInsecureOrigin"/>
+ <int value="458" label="DeviceUpdateStagingPercentOfFleetPerWeek"/>
+ <int value="459" label="AutofillAddressEnabled"/>
+ <int value="460" label="TabLifecyclesEnabled"/>
+ <int value="461" label="UrlKeyedAnonymizedDataCollectionEnabled"/>
</enum>
<enum name="EnterprisePolicyInvalidations">
@@ -14492,6 +14830,7 @@ Called by update_net_error_codes.py.-->
<int value="421"
label="ACCESSIBILITY_PRIVATE_ON_SELECT_TO_SPEAK_STATE_CHANGE_REQUESTED"/>
<int value="422" label="INPUT_METHOD_PRIVATE_ON_FOCUS"/>
+ <int value="423" label="SYSTEM_POWER_SOURCE_ONPOWERCHANGED"/>
</enum>
<enum name="ExtensionFileWriteResult">
@@ -15776,9 +16115,9 @@ Called by update_net_error_codes.py.-->
<int value="1228" label="QUICKUNLOCKPRIVATE_GETAUTHTOKEN"/>
<int value="1229" label="QUICKUNLOCKPRIVATE_SETLOCKSCREENENABLED"/>
<int value="1230" label="LANGUAGESETTINGSPRIVATE_RETRYDOWNLOADDICTIONARY"/>
- <int value="1231" label="DECLARATIVENETREQUEST_ADDWHITELISTEDPAGES"/>
- <int value="1232" label="DECLARATIVENETREQUEST_REMOVEWHITELISTEDPAGES"/>
- <int value="1233" label="DECLARATIVENETREQUEST_GETWHITELISTEDPAGES"/>
+ <int value="1231" label="DECLARATIVENETREQUEST_ADDALLOWEDPAGES"/>
+ <int value="1232" label="DECLARATIVENETREQUEST_REMOVEALLOWEDPAGES"/>
+ <int value="1233" label="DECLARATIVENETREQUEST_GETALLOWEDPAGES"/>
<int value="1234" label="DEVELOPERPRIVATE_INSTALLDROPPEDFILE"/>
<int value="1235" label="AUTOMATIONINTERNAL_ENABLEFRAME"/>
<int value="1236" label="AUTOMATIONINTERNAL_QUERYSELECTOR"/>
@@ -15803,6 +16142,14 @@ Called by update_net_error_codes.py.-->
<int value="1254" label="DEVELOPERPRIVATE_REMOVEHOSTPERMISSION"/>
<int value="1255" label="MEDIAPERCEPTIONPRIVATE_SETCOMPONENTPROCESSSTATE"/>
<int value="1256" label="USERSPRIVATE_GETCURRENTUSER"/>
+ <int value="1257" label="WALLPAPERPRIVATE_GETSURPRISEMEIMAGE"/>
+ <int value="1258" label="VIRTUALKEYBOARDPRIVATE_SETOCCLUDEDBOUNDS"/>
+ <int value="1259" label="SYSTEM_POWER_SOURCE_GETPOWERSOURCEINFO"/>
+ <int value="1260" label="SYSTEM_POWER_SOURCE_REQUESTSTATUSUPDATE"/>
+ <int value="1261" label="INPUTMETHODPRIVATE_GETSURROUNDINGTEXT"/>
+ <int value="1262" label="USERSPRIVATE_GETLOGINSTATUS"/>
+ <int value="1263" label="FILEMANAGERPRIVATEINTERNAL_INSTALLLINUXPACKAGE"/>
+ <int value="1264" label="VIRTUALKEYBOARDPRIVATE_SETHITTESTBOUNDS"/>
</enum>
<enum name="ExtensionIconState">
@@ -15892,6 +16239,13 @@ Called by update_net_error_codes.py.-->
<int value="10" label="EXTERNAL_COMPONENT"/>
</enum>
+<enum name="ExtensionMessagingIncludeChannelIdBehavior">
+ <int value="0" label="Not requested"/>
+ <int value="1" label="Requested but denied"/>
+ <int value="2" label="Requested but not found"/>
+ <int value="3" label="Requested and included"/>
+</enum>
+
<enum name="ExtensionNotificationType">
<int value="0" label="NOTIFICATION_TYPE_SIMPLE"/>
<int value="1" label="NOTIFICATION_TYPE_BASE_FORMAT"/>
@@ -16238,6 +16592,8 @@ Called by update_net_error_codes.py.-->
<int value="209" label="kWebrtcLoggingPrivateAudioDebug"/>
<int value="210" label="kEnterpriseReportingPrivate"/>
<int value="211" label="kCecPrivate"/>
+ <int value="212" label="kSafeBrowsingPrivate"/>
+ <int value="213" label="kFileSystemRequestDownloads"/>
</enum>
<enum name="ExtensionServiceVerifyAllSuccess">
@@ -18726,7 +19082,7 @@ Called by update_net_error_codes.py.-->
<int value="2144" label="WebkitBoxLineClampDoesSomething"/>
<int value="2145" label="FeaturePolicyAllowAttributeDeprecatedSyntax"/>
<int value="2146" label="SuppressHistoryEntryWithoutUserGesture"/>
- <int value="2147" label="ImageInputTypeFormDataWithNonEmptyValue"/>
+ <int value="2147" label="OBSOLETE_ImageInputTypeFormDataWithNonEmptyValue"/>
<int value="2148" label="WebAudioDezipperGainNodeGain"/>
<int value="2149" label="WebAudioDezipperStereoPannerNodePan"/>
<int value="2150" label="WebAudioDezipperDelayNodeDelayTime"/>
@@ -19054,6 +19410,9 @@ Called by update_net_error_codes.py.-->
<int value="2462" label="ShapeOutsidePaddingBoxDifferentFromMarginBox"/>
<int value="2463" label="CSSContainLayoutPositionedDescendants"/>
<int value="2464" label="HTMLFrameSetElementAnonymousNamedGetter"/>
+ <int value="2465" label="CanvasConvertToBlob"/>
+ <int value="2466" label="PolymerV1Detected"/>
+ <int value="2467" label="PolymerV2Detected"/>
<int value="2468" label="PerformanceEventTimingBuffer"/>
<int value="2469" label="PerformanceEventTimingConstructor"/>
<int value="2470" label="ReverseIterateDOMStorage"/>
@@ -19076,9 +19435,35 @@ Called by update_net_error_codes.py.-->
<int value="2485" label="LegacySymantecCertInSubresource"/>
<int value="2486" label="LegacySymantecCertInSubframeMainResource"/>
<int value="2487" label="EventTimingExplicitlyRequested"/>
+ <int value="2488" label="CSSEnvironmentVariable"/>
+ <int value="2489" label="CSSEnvironmentVariable_SafeAreaInsetTop"/>
+ <int value="2490" label="CSSEnvironmentVariable_SafeAreaInsetLeft"/>
+ <int value="2491" label="CSSEnvironmentVariable_SafeAreaInsetBottom"/>
+ <int value="2492" label="CSSEnvironmentVariable_SafeAreaInsetRight"/>
+ <int value="2493" label="MediaControlsDisplayCutoutGesture"/>
<int value="2494" label="DocumentOpenTwoArgs"/>
<int value="2495" label="DocumentOpenTwoArgsWithReplace"/>
<int value="2496" label="DocumentOpenThreeArgs"/>
+ <int value="2497" label="V8FunctionTokenOffsetTooLongForToString"/>
+ <int value="2498" label="ServiceWorkerImportScriptNotInstalled"/>
+ <int value="2499" label="NestedDedicatedWorker"/>
+ <int value="2500" label="ClientHintsMetaAcceptCHLifetime"/>
+ <int value="2501" label="DOMNodeRemovedEventDelayed"/>
+ <int value="2502" label="DOMNodeRemovedEventHandlerAccessDetachingNode"/>
+ <int value="2503" label="DOMNodeRemovedEventListenedAtNonTarget"/>
+ <int value="2504" label="DOMNodeRemovedFromDocumentEventDelayed"/>
+ <int value="2505"
+ label="DOMNodeRemovedFromDocumentEventHandlerAccessDetachingNode"/>
+ <int value="2506" label="DOMNodeRemovedFromDocumentEventListenedAtNonTarget"/>
+ <int value="2507" label="CSSFillAvailableLogicalWidth"/>
+ <int value="2508" label="CSSFillAvailableLogicalHeight"/>
+ <int value="2509" label="PopupOpenWhileFileChooserOpened"/>
+ <int value="2510" label="CookieStoreAPI"/>
+ <int value="2511" label="FeaturePolicyJSAPI"/>
+ <int value="2512" label="V8RTCPeerConnection_GetTransceivers_Method"/>
+ <int value="2513" label="V8RTCPeerConnection_AddTransceiver_Method"/>
+ <int value="2514" label="V8RTCRtpTransceiver_Direction_AttributeGetter"/>
+ <int value="2515" label="V8RTCRtpTransceiver_Direction_AttributeSetter"/>
</enum>
<enum name="FeedbackSource">
@@ -19972,6 +20357,8 @@ Called by update_net_error_codes.py.-->
<int value="7" label="Toggle use mobile data for sync (off)"/>
<int value="8" label="Toggle Show Google Docs files (on)"/>
<int value="9" label="Toggle Show Google Docs files (off)"/>
+ <int value="10" label="Toggle show hidden Android folders (on)"/>
+ <int value="11" label="Toggle show hidden Android folders (off)"/>
</enum>
<enum name="FileManagerQuickViewWayToOpen">
@@ -20006,6 +20393,7 @@ Called by update_net_error_codes.py.-->
<int value="2" label="Chrome App"/>
<int value="3" label="Drive App"/>
<int value="4" label="ARC App"/>
+ <int value="5" label="Crostini App"/>
</enum>
<enum name="FileManagerVolumeType">
@@ -20075,6 +20463,22 @@ Called by update_net_error_codes.py.-->
<int value="14" label="Async DeleteFile Failed"/>
</enum>
+<enum name="FileReaderLoaderFailureType">
+ <int value="0" label="Mojo pipe creation failed"/>
+ <int value="1" label="Data incomplete after synchronous reading"/>
+ <int value="2" label="OnComplete never called after synchronous reading"/>
+ <int value="3" label="The blob's total size too large for FileReaderLoader"/>
+ <int value="4" label="Failed to create the ArrayBufferBuilder"/>
+ <int value="5" label="Failed to append to the ArrayBufferBuilder"/>
+ <int value="6"
+ label="Backend read error, see Storage.Blob.FileReaderLoader.ReadError"/>
+ <int value="7" label="The size read does not match the size reported"/>
+ <int value="8"
+ label="The data pipe is not readable and there are bytes left to read"/>
+ <int value="9" label="The data pipe closed early"/>
+ <int value="10" label="Data pipe reading failed with an unexpected error"/>
+</enum>
+
<enum name="FileReaderSyncWorkerType">
<int value="0" label="Other"/>
<int value="1" label="Dedicated Worker"/>
@@ -21567,7 +21971,7 @@ Called by update_net_error_codes.py.-->
</enum>
<enum name="GCMRegistrationRequestStatus">
- <int value="0" label="Success (this is not logged currently)"/>
+ <int value="0" label="Success"/>
<int value="1" label="Invalid parameters"/>
<int value="2" label="Invalid sender"/>
<int value="3" label="Authentication failed"/>
@@ -21627,6 +22031,10 @@ Called by update_net_error_codes.py.-->
<int value="3" label="Forced GC for testing"/>
<int value="4" label="Memory pressure GC"/>
<int value="5" label="Page navigation GC"/>
+ <int value="6" label="Thread termination GC"/>
+ <int value="7" label="Testing GC"/>
+ <int value="8" label="Incremental idle GC"/>
+ <int value="9" label="Incremental v8 follow-up GC"/>
</enum>
<enum name="GDataAuthResult">
@@ -21769,30 +22177,6 @@ Called by update_net_error_codes.py.-->
<int value="3" label="Timeout"/>
</enum>
-<enum name="GestureActionType">
- <int value="0" label="Unknown"/>
- <int value="1" label="Omnibox pinch"/>
- <int value="2" label="Omnibox scroll"/>
- <int value="3" label="Tabstrip pinch"/>
- <int value="4" label="Tabstrip scroll"/>
- <int value="5" label="Bezel scroll"/>
- <int value="6" label="Desktop scroll"/>
- <int value="7" label="Desktop pinch"/>
- <int value="8" label="Webpage pinch"/>
- <int value="9" label="Webpage scroll"/>
- <int value="10" label="Webpage tap"/>
- <int value="11" label="Tabstrip tap"/>
- <int value="12" label="Bezel down"/>
- <int value="13" label="Tab switched tap"/>
- <int value="14" label="Active tab tap"/>
- <int value="15" label="Tab close button tap"/>
- <int value="16" label="New tab button tap"/>
- <int value="17" label="Top edge of window tap"/>
- <int value="18" label="Window size button tap"/>
- <int value="19" label="Area surrounding tabstrip tap"/>
- <int value="20" label="Window resized double tap"/>
-</enum>
-
<enum name="GestureMergeState">
<int value="0" label="Neither token had a gesture"/>
<int value="1" label="Only the old token had a gesture"/>
@@ -21955,6 +22339,11 @@ Called by update_net_error_codes.py.-->
<int value="17" label="SIGN_IN_FAILED"/>
<int value="18" label="SERVICE_UPDATING"/>
<int value="1500" label="DRIVE_EXTERNAL_STORAGE_REQUIRED"/>
+ <int value="12000" label="SAFE_BROWSING_UNSUPPORTED_THREAT_TYPES"/>
+ <int value="12001" label="SAFE_BROWSING_MISSING_API_KEY"/>
+ <int value="12002" label="SAFE_BROWSING_API_NOT_AVAILABLE"/>
+ <int value="12006" label="UNSUPPORTED_SDK_VERSION"/>
+ <int value="12009" label="SAFE_BROWSING_API_NOT_INITIALIZED"/>
</enum>
<enum name="GooglePlayServicesErrorHandlerAction">
@@ -22804,15 +23193,15 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<enum name="GPUProcessLifetimeEvent">
<summary>
Lifetime events of the GPU Process, as defined in
- chrome/browser/gpu_process_host.cc. DiedFourth should never happen as it is
- beyond the threshold number of launches enforced in
- chrome/browser/gpu_process_host.cc.
+ content/browser/gpu/gpu_process_host.cc.
</summary>
<int value="0" label="Launched"/>
- <int value="1" label="DiedFirst"/>
- <int value="2" label="DiedSecond"/>
- <int value="3" label="DiedThird"/>
- <int value="4" label="DiedFourth"/>
+ <int value="1" label="Died first time"/>
+ <int value="2" label="Died second time"/>
+ <int value="3" label="Died third time"/>
+ <int value="4" label="Died fourth time"/>
+ <int value="5" label="Died fifth time"/>
+ <int value="6" label="Died sixth time"/>
</enum>
<enum name="GPUProcessType">
@@ -22913,6 +23302,18 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<int value="3" label="Checked dont launch"/>
</enum>
+<enum name="HeavyPageCappingInfoBarInteraction">
+ <int value="0" label="InfoBar shown">
+ The user was shown the capping heavy pages InfoBar.
+ </int>
+ <int value="1" label="Paused">
+ The user clicked the InfoBar button pausing subresource loading.
+ </int>
+ <int value="2" label="Resumed">
+ The user clicked the InfoBar again resuming subresource loading.
+ </int>
+</enum>
+
<enum name="HIDContinueScenarioType">
<summary>Possible detected devices combination on leaving dialog</summary>
<int value="0" label="Pointing device only detected."/>
@@ -22999,6 +23400,8 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
label="PasswordManager.Android.PasswordCredentialEntry.Username"/>
<int value="1753226325"
label="DataUse.MessageSize.AllServices.Downstream.Foreground.Cellular"/>
+ <int value="1857977303"
+ label="TaskQueueSelector.TaskServicedPerSelectorLogic"/>
<int value="1864392953" label="AsyncDNS.HostsNotifyInterval"/>
<int value="1977321258"
label="DataUse.MessageSize.AllServices.Downstream.Background.Cellular"/>
@@ -23434,6 +23837,8 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<enum name="HttpResponseCode">
<int value="100" label="100: Continue"/>
<int value="101" label="101: Switching Protocols"/>
+ <int value="102" label="102: Processing"/>
+ <int value="103" label="103: Early Hints"/>
<int value="200" label="200: OK"/>
<int value="201" label="201: Created"/>
<int value="202" label="202: Accepted"/>
@@ -24102,6 +24507,9 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<int value="79" label="NEAR_OOM_INFOBAR_ANDROID"/>
<int value="80" label="INSTALLABLE_AMBIENT_BADGE_INFOBAR_DELEGATE"/>
<int value="81" label="PAGE_LOAD_CAPPING_INFOBAR_DELEGATE"/>
+ <int value="83" label="AR_CORE_UPGRADE_ANDROID"/>
+ <int value="84" label="BLOATED_RENDERER_INFOBAR_DELEGATE"/>
+ <int value="85" label="SUPERVISED_USERS_DEPRECATED_INFOBAR_DELEGATE"/>
</enum>
<enum name="InfoBarResponse">
@@ -24118,6 +24526,12 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<int value="3" label="3G"/>
</enum>
+<enum name="InitiatorAccess">
+ <int value="0" label="Initiator absent"/>
+ <int value="1" label="No access"/>
+ <int value="2" label="Has access"/>
+</enum>
+
<enum name="InjectedAdType">
<int value="0" label="Invalid"/>
<int value="1" label="IFrame"/>
@@ -24296,25 +24710,36 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<enum name="InputMethodID2">
<int value="-2082426075" label="xkb:cz:qwerty:cze">Czech QWERTY keyboard</int>
<int value="-2039513744" label="xkb:ru::rus">Russian keyboard</int>
+ <int value="-2030885731" label="vkd_fa">Persian keyboard</int>
<int value="-2004968165" label="xkb:gb:dvorak:eng">UK Dvorak keyboard</int>
<int value="-2004834194" label="xkb:ca:multix:fra">
Canadian Multilingual keyboard
</int>
<int value="-1992142310" label="xkb:dk::dan">Danish keyboard</int>
- <int value="-1972379678" label="vkd_deva_phone">
- Devanagari keyboard (Phonetic)
+ <int value="-1989523479" label="pa-t-i0-und">Punjabi transliteration</int>
+ <int value="-1972379678" label="vkd_deva_phone_old">
+ Devanagari keyboard (Phonetic) (obsolete)
+ </int>
+ <int value="-1957398030" label="ta-t-i0-und_old">
+ Tamil transliteration (obsolete)
</int>
- <int value="-1957398030" label="ta-t-i0-und">Tamil transliteration</int>
<int value="-1955862460" label="xkb:ro::rum">Romanian keyboard</int>
+ <int value="-1953637256" label="xkb:us:workman-intl:eng">
+ US Workman International Keyboard
+ </int>
<int value="-1951732875" label="xkb:be::nld">Belgian keyboard</int>
- <int value="-1931838225" label="zh-hant-t-i0-cangjie-1987-x-m0-simplified">
- Quick input method
+ <int value="-1931838225"
+ label="zh-hant-t-i0-cangjie-1987-x-m0-simplified_old">
+ Quick input method (obsolete)
</int>
- <int value="-1899483055" label="vkd_my">Myanmar keyboard</int>
+ <int value="-1899483055" label="vkd_my_old">Myanmar keyboard (obsolete)</int>
<int value="-1856842164" label="xkb:ge::geo">Georgian keyboard</int>
- <int value="-1856063724" label="vkd_km">Khmer keyboard</int>
- <int value="-1749961581" label="vkd_ta_inscript">
- Tamil keyboard (InScript)
+ <int value="-1856063724" label="vkd_km_old">Khmer keyboard (obsolete)</int>
+ <int value="-1793755122" label="zh-hant-t-i0-cangjie-1987-x-m0-simplified">
+ Quick input method
+ </int>
+ <int value="-1749961581" label="vkd_ta_inscript_old">
+ Tamil keyboard (InScript) (obsolete)
</int>
<int value="-1710145174" label="xkb:am:phonetic:arm">
Armenian Phonetic keyboard
@@ -24323,31 +24748,55 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<int value="-1668610460" label="xkb:us:dvp:eng">
US Programmer Dvorak keyboard
</int>
- <int value="-1667829653" label="zh-hant-t-i0-cangjie-1987">
- Cangjie input method
+ <int value="-1667829653" label="zh-hant-t-i0-cangjie-1987_old">
+ Cangjie input method (obsolete)
</int>
- <int value="-1591721678" label="vkd_ne_inscript">
- Nepali keyboard (InScript)
+ <int value="-1622129313" label="sr-t-i0-und">Serbian transliteration</int>
+ <int value="-1616253108" label="ta-t-i0-und">Tamil transliteration</int>
+ <int value="-1608984043" label="vkd_my_myansan">Myanmar Myansan keyboard</int>
+ <int value="-1591721678" label="vkd_ne_inscript_old">
+ Nepali keyboard (InScript) (obsolete)
</int>
+ <int value="-1520893793" label="vkd_te_phone">Telugu keyboard (Phonetic)</int>
<int value="-1474243589" label="xkb:it::ita">Italian keyboard</int>
+ <int value="-1466408010" label="hi-t-i0-und">Hindi transliteration</int>
<int value="-1408581676" label="xkb:gb:extd:eng">UK keyboard</int>
<int value="-1402880636" label="xkb:se::swe">Swedish keyboard</int>
- <int value="-1396156987" label="vkd_ru_phone_aatseel">
+ <int value="-1396156987" label="vkd_ru_phone_aatseel_old">
+ Russian Phonetic (AATSEEL) keyboard (obsolete)
+ </int>
+ <int value="-1386518472" label="vkd_ru_phone_aatseel">
Russian Phonetic (AATSEEL) keyboard
</int>
+ <int value="-1362493117" label="zh-hant-t-i0-dayi-1988">
+ Dayi input method
+ </int>
+ <int value="-1356599825" label="bn-t-i0-und">Bengali transliteration</int>
+ <int value="-1346114248" label="vkd_vi_vni">Vietnamese keyboard (VNI)</int>
<int value="-1338032348" label="xkb:de:neo:ger">German NEO 2 keyboard</int>
- <int value="-1288127107" label="vkd_vi_telex">
- Vietnamese keyboard (Telex)
+ <int value="-1288127107" label="vkd_vi_telex_old">
+ Vietnamese keyboard (Telex) (obsolete)
+ </int>
+ <int value="-1263201701" label="hi-t-i0-und_old">
+ Hindi transliteration (obsolete)
+ </int>
+ <int value="-1242404917" label="sr-t-i0-und_old">
+ Serbian transliteration (obsolete)
</int>
- <int value="-1263201701" label="hi-t-i0-und">Hindi transliteration</int>
- <int value="-1242404917" label="sr-t-i0-und">Serbian transliteration</int>
<int value="-1148371254" label="xkb:us:intl:por">
US International keyboard
</int>
- <int value="-1105197074" label="vkd_ar">Arabic keyboard</int>
- <int value="-1096071752" label="vkd_fa">Persian keyboard</int>
- <int value="-1065120196" label="vkd_th">Thai keyboard (Kedmanee)</int>
+ <int value="-1105197074" label="vkd_ar_old">Arabic keyboard (obsolete)</int>
+ <int value="-1096071752" label="vkd_fa_old">Persian keyboard (obsolete)</int>
+ <int value="-1093390778" label="vkd_ml_phone">
+ Malayalam keyboard (Phonetic)
+ </int>
+ <int value="-1084450354" label="gu-t-i0-und">Gujarati transliteration</int>
+ <int value="-1065120196" label="vkd_th_old">
+ Thai keyboard (Kedmanee) (obsolete)
+ </int>
<int value="-1053378431" label="xkb:tr::tur">Turkish keyboard</int>
+ <int value="-1044696009" label="ar-t-i0-und">Arabic transliteration</int>
<int value="-1032532014" label="xkb:bg:phonetic:bul">
Bulgarian Phonetic keyboard
</int>
@@ -24355,137 +24804,296 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
Canadian English keyboard
</int>
<int value="-1021036210" label="xkb:us::ind">US keyboard</int>
- <int value="-1018545698" label="vkd_ckb_en">
- Sorani Kurdish English-based keyboard
+ <int value="-1018545698" label="vkd_ckb_en_old">
+ Sorani Kurdish English-based keyboard (obsolete)
</int>
+ <int value="-1011117789" label="vkd_ta_itrans">Tamil keyboard (itrans)</int>
<int value="-994915284" label="xkb:ch:fr:fra">Swiss French keyboard</int>
<int value="-955047705" label="xkb:sk::slo">Slovakian keyboard</int>
<int value="-942739805" label="xkb:tr:f:tur">Turkish-F keyboard</int>
<int value="-923332388" label="xkb:ua::ukr">Ukrainian keyboard</int>
- <int value="-917118451" label="vkd_vi_tcvn">Vietnamese keyboard (TCVN)</int>
- <int value="-848378885" label="vkd_ethi">Ethiopic keyboard</int>
+ <int value="-917118451" label="vkd_vi_tcvn_old">
+ Vietnamese keyboard (TCVN) (obsolete)
+ </int>
+ <int value="-848378885" label="vkd_ethi_old">
+ Ethiopic keyboard (obsolete)
+ </int>
<int value="-827208209" label="xkb:hu::hun">Hungarian keyboard</int>
- <int value="-797137387" label="ml-t-i0-und">Malayalam transliteration</int>
- <int value="-676861102" label="vkd_vi_viqr">Vietnamese keyboard (VIQR)</int>
+ <int value="-797137387" label="ml-t-i0-und_old">
+ Malayalam transliteration (obsolete)
+ </int>
+ <int value="-769279084" label="xkb:us:intl_pc:eng">
+ US International (PC) keyboard
+ </int>
+ <int value="-694112343" label="vkd_ne_phone">Nepali keyboard (Phonetic)</int>
+ <int value="-676861102" label="vkd_vi_viqr_old">
+ Vietnamese keyboard (VIQR) (obsolete)
+ </int>
<int value="-666585286" label="xkb:bg::bul">Bulgarian keyboard</int>
<int value="-650362029" label="xkb:ie::ga">Irish keyboard</int>
- <int value="-639620912" label="te-t-i0-und">Telugu transliteration</int>
- <int value="-622670909" label="zh-hant-t-i0-dayi-1988">Dayi input method</int>
+ <int value="-639620912" label="te-t-i0-und_old">
+ Telugu transliteration (obsolete)
+ </int>
+ <int value="-622670909" label="zh-hant-t-i0-dayi-1988_old">
+ Dayi input method (obsolete)
+ </int>
+ <int value="-607101895" label="zh-t-i0-pinyin">Pinyin input method</int>
<int value="-547772150" label="xkb:ro:std:rum">
Romanian standard keyboard
</int>
+ <int value="-545936253" label="zh-hant-t-i0-array-1992">
+ Array input method
+ </int>
+ <int value="-537214862" label="xkb:us:intl_pc:eng">
+ US International (PC) keyboard
+ </int>
<int value="-535089160" label="xkb:us::msa">US keyboard</int>
- <int value="-519506383" label="he-t-i0-und">Hebrew transliteration</int>
+ <int value="-519506383" label="he-t-i0-und_old">
+ Hebrew transliteration (obsolete)
+ </int>
<int value="-512360986" label="xkb:us:altgr-intl:eng">
US Extended keyboard
</int>
- <int value="-498028381" label="sa-t-i0-und">Sanskrit transliteration</int>
+ <int value="-498028381" label="sa-t-i0-und_old">
+ Sanskrit transliteration (obsolete)
+ </int>
<int value="-496003957" label="xkb:de::ger">German keyboard</int>
- <int value="-439432295" label="vkd_ru_phone_yazhert">
- Russian Phonetic (YaZHert) keyboard
+ <int value="-489436211" label="xkb:us:intl_pc:nld">
+ US International (PC) keyboard
+ </int>
+ <int value="-456651526" label="kn-t-i0-und">Kannada transliteration</int>
+ <int value="-439432295" label="vkd_ru_phone_yazhert_old">
+ Russian Phonetic (YaZHert) keyboard (obsolete)
+ </int>
+ <int value="-428164685" label="ml-t-i0-und_old">
+ Malayalam transliteration (obsolete)
</int>
- <int value="-378677550" label="vkd_bn_phone">Bengali keyboard (Phonetic)</int>
+ <int value="-383640577" label="or-t-i0-und">Oriya transliteration</int>
+ <int value="-378677550" label="vkd_bn_phone_old">
+ Bengali keyboard (Phonetic) (obsolete)
+ </int>
+ <int value="-366323598" label="fa-t-i0-und">Persian transliteration</int>
<int value="-352571373" label="xkb:rs::srp">Serbian keyboard</int>
+ <int value="-329596558" label="te-t-i0-und">Telugu transliteration</int>
<int value="-299716106" label="xkb:si::slv">Slovenian keyboard</int>
<int value="-292687390" label="xkb:fi::fin">Finnish keyboard</int>
- <int value="-280690349" label="vkd_vi_vni">Vietnamese keyboard (VNI)</int>
+ <int value="-280690349" label="vkd_vi_vni_old">
+ Vietnamese keyboard (VNI) (obsolete)
+ </int>
<int value="-263932473" label="xkb:ch::ger">Swiss keyboard</int>
- <int value="-231610124" label="ne-t-i0-und">Nepali transliteration</int>
- <int value="-225482038" label="vkd_si">Sinhala keyboard</int>
- <int value="-219542410" label="ko-t-i0-und">Korean input method</int>
+ <int value="-244167850" label="nacl_mozc_jp">
+ Google Japanese Input (for Japanese keyboard)
+ </int>
+ <int value="-231610124" label="ne-t-i0-und_old">
+ Nepali transliteration (obsolete)
+ </int>
+ <int value="-225482038" label="vkd_si_old">Sinhala keyboard (obsolete)</int>
+ <int value="-219542410" label="ko-t-i0-und_old">
+ Korean input method (obsolete)
+ </int>
<int value="-202781885" label="xkb:us:intl:eng">
US International keyboard
</int>
- <int value="-193738949" label="gu-t-i0-und">Gujarati transliteration</int>
- <int value="-147742988" label="mr-t-i0-und">Marathi transliteration</int>
- <int value="-83634292" label="vkd_my_myansan">Myanmar Myansan keyboard</int>
+ <int value="-193738949" label="gu-t-i0-und_old">
+ Gujarati transliteration (obsolete)
+ </int>
+ <int value="-176093583" label="vkd_bn_phone">Bengali keyboard (Phonetic)</int>
+ <int value="-147742988" label="mr-t-i0-und_old">
+ Marathi transliteration (obsolete)
+ </int>
+ <int value="-119597715" label="mr-t-i0-und">Marathi transliteration</int>
+ <int value="-83634292" label="vkd_my_myansan_old">
+ Myanmar Myansan keyboard (obsolete)
+ </int>
<int value="-70827301" label="xkb:be::fra">Belgian keyboard</int>
- <int value="-69316526" label="fa-t-i0-und">Persian transliteration</int>
+ <int value="-69316526" label="fa-t-i0-und_old">
+ Persian transliteration (obsolete)
+ </int>
<int value="2215666" label="xkb:jp::jpn">Japanese keyboard</int>
+ <int value="23642603" label="yue-hant-t-i0-und">Cantonese input method</int>
<int value="28549849" label="xkb:pt::por">Portuguese keyboard</int>
<int value="60054916" label="xkb:fo::fao">Faroese keyboard</int>
+ <int value="68243712" label="vkd_si">Sinhala keyboard</int>
<int value="87135772" label="xkb:fr::fra">French keyboard</int>
- <int value="150803493" label="vkd_ta_phone">Tamil keyboard (Phonetic)</int>
+ <int value="132261074" label="ti-t-i0-und">Tigrinya transliteration</int>
+ <int value="150803493" label="vkd_ta_phone_old">
+ Tamil keyboard (Phonetic) (obsolete)
+ </int>
<int value="193122406" label="xkb:gr::gre">Greek keyboard</int>
<int value="197116831" label="xkb:es::spa">Spanish keyboard</int>
- <int value="214846098" label="zh-t-i0-wubi-1986">Wubi input method</int>
+ <int value="214846098" label="zh-t-i0-wubi-1986_old">
+ Wubi input method (obsolete)
+ </int>
+ <int value="233227876" label="vkd_km">Khmer keyboard</int>
<int value="319509360" label="xkb:be::ger">Belgian keyboard</int>
+ <int value="374544129" label="vkd_th_pattajoti">
+ Thai keyboard (Pattachote)
+ </int>
<int value="382485416" label="xkb:lv:apostrophe:lav">Latvian keyboard</int>
- <int value="398887705" label="ti-t-i0-und">Tigrinya transliteration</int>
- <int value="400837283" label="yue-hant-t-i0-und">Cantonese input method</int>
- <int value="414827905" label="vkd_ta_typewriter">
- Tamil keyboard (Typewriter)
+ <int value="398887705" label="ti-t-i0-und_old">
+ Tigrinya transliteration (obsolete)
+ </int>
+ <int value="400837283" label="yue-hant-t-i0-und_old">
+ Cantonese input method (obsolete)
+ </int>
+ <int value="414827905" label="vkd_ta_typewriter_old">
+ Tamil keyboard (Typewriter) (obsolete)
+ </int>
+ <int value="428624332" label="zh-t-i0-pinyin_old">
+ Pinyin input method (obsolete)
+ </int>
+ <int value="452111434" label="kn-t-i0-und_old">
+ Kannada transliteration (obsolete)
+ </int>
+ <int value="467269371" label="el-t-i0-und_old">
+ Greek transliteration (obsolete)
</int>
- <int value="428624332" label="zh-t-i0-pinyin">Pinyin input method</int>
- <int value="452111434" label="kn-t-i0-und">Kannada transliteration</int>
- <int value="467269371" label="el-t-i0-und">Greek transliteration</int>
<int value="469000663" label="xkb:es:cat:cat">Catalan keyboard</int>
- <int value="520692028" label="vkd_ta_itrans">Tamil keyboard (itrans)</int>
- <int value="601883646" label="vkd_th_tis">Thai keyboard (TIS 820-2531)</int>
+ <int value="472995125" label="vkd_ta_phone">Tamil keyboard (Phonetic)</int>
+ <int value="484753645" label="xkb:us:workman:eng">US Workman Keyboard</int>
+ <int value="490329655" label="zh-t-i0-wubi-1986">Wubi input method</int>
+ <int value="520496071" label="vkd_ckb_en">
+ Sorani Kurdish English-based keyboard
+ </int>
+ <int value="520692028" label="vkd_ta_itrans_old">
+ Tamil keyboard (itrans) (obsolete)
+ </int>
+ <int value="535728072" label="ne-t-i0-und">Nepali transliteration</int>
+ <int value="537062379" label="vkd_ru_phone_yazhert">
+ Russian Phonetic (YaZHert) keyboard
+ </int>
+ <int value="601883646" label="vkd_th_tis_old">
+ Thai keyboard (TIS 820-2531) (obsolete)
+ </int>
<int value="602570138" label="xkb:mk::mkd">Macedonian keyboard</int>
- <int value="629336408" label="vkd_ckb_ar">
- Sorani Kurdish Arabic-based keyboard
+ <int value="612541362" label="vkd_ar">Arabic keyboard</int>
+ <int value="629336408" label="vkd_ckb_ar_old">
+ Sorani Kurdish Arabic-based keyboard (obsolete)
</int>
<int value="629711326" label="xkb:il::heb">Hebrew keyboard</int>
<int value="683071754" label="xkb:hr::scr">Croatian keyboard</int>
+ <int value="774753710" label="vkd_th_tis">Thai keyboard (TIS 820-2531)</int>
+ <int value="787164771" label="vkd_lo">Lao keyboard</int>
<int value="789603234" label="xkb:by::bel">Belarusian keyboard</int>
+ <int value="789867412" label="vkd_ethi">Ethiopic keyboard</int>
<int value="822222165" label="xkb:ru:phonetic:rus">
Russian Phonetic keyboard
</int>
<int value="825747412" label="xkb:latam::spa">Latin American keyboard</int>
+ <int value="828287201" label="vkd_ta_inscript">Tamil keyboard (InScript)</int>
+ <int value="843503620" label="ur-t-i0-und">Urdu transliteration</int>
<int value="871656925" label="xkb:us::fil">US keyboard</int>
- <int value="1024422775" label="vkd_ml_phone">
- Malayalam keyboard (Phonetic)
+ <int value="1024422775" label="vkd_ml_phone_old">
+ Malayalam keyboard (Phonetic) (obsolete)
</int>
- <int value="1127372618" label="vkd_ta_tamil99">Tamil keyboard (Tamil99)</int>
- <int value="1194237527" label="bn-t-i0-und">Bengali transliteration</int>
- <int value="1196273343" label="vkd_te_phone">Telugu keyboard (Phonetic)</int>
- <int value="1201986464" label="pa-t-i0-und">Punjabi transliteration</int>
- <int value="1241606786" label="vkd_gu_phone">
- Gujarati keyboard (Phonetic)
+ <int value="1028639984" label="he-t-i0-und">Hebrew transliteration</int>
+ <int value="1091977227" label="vkd_my">Myanmar keyboard</int>
+ <int value="1127372618" label="vkd_ta_tamil99_old">
+ Tamil keyboard (Tamil99) (obsolete)
</int>
- <int value="1275989482" label="xkb:ee::est">Estonian keyboard</int>
- <int value="1342665179" label="or-t-i0-und">Oriya transliteration</int>
- <int value="1355267172" label="nacl_mozc_jp">
- Google Japanese Input (for Japanese keyboard)
+ <int value="1190741118" label="am-t-i0-und">Amharic transliteration</int>
+ <int value="1194237527" label="bn-t-i0-und_old">
+ Bengali transliteration (obsolete)
+ </int>
+ <int value="1196273343" label="vkd_te_phone_old">
+ Telugu keyboard (Phonetic) (obsolete)
</int>
- <int value="1376109158" label="zh-hant-t-i0-pinyin">
+ <int value="1201986464" label="pa-t-i0-und_old">
+ Punjabi transliteration (obsolete)
+ </int>
+ <int value="1203226200" label="vkd_kn_phone">Kannada keyboard (Phonetic)</int>
+ <int value="1241606786" label="vkd_gu_phone_old">
+ Gujarati keyboard (Phonetic) (obsolete)
+ </int>
+ <int value="1275989482" label="xkb:ee::est">Estonian keyboard</int>
+ <int value="1292575742" label="el-t-i0-und">Greek transliteration</int>
+ <int value="1321401457" label="zh-hant-t-i0-pinyin">
Traditional Pinyin input method
</int>
- <int value="1391164751" label="vkd_ne_phone">Nepali keyboard (Phonetic)</int>
+ <int value="1342665179" label="or-t-i0-und_old">
+ Oriya transliteration (obsolete)
+ </int>
+ <int value="1346294191" label="vkd_vi_tcvn">Vietnamese keyboard (TCVN)</int>
+ <int value="1355267172" label="nacl_mozc_jp_old">
+ Google Japanese Input (for Japanese keyboard) (obsolete)
+ </int>
+ <int value="1364126694" label="vkd_vi_viqr">Vietnamese keyboard (VIQR)</int>
+ <int value="1376109158" label="zh-hant-t-i0-pinyin_old">
+ Traditional Pinyin input method (obsolete)
+ </int>
+ <int value="1391164751" label="vkd_ne_phone_old">
+ Nepali keyboard (Phonetic) (obsolete)
+ </int>
<int value="1409029247" label="xkb:ca::fra">Canadian French keyboard</int>
- <int value="1486336701" label="zh-hant-t-i0-und">Zhuyin input method</int>
+ <int value="1411091864" label="vkd_th">Thai keyboard (Kedmanee)</int>
+ <int value="1425002521" label="vkd_ckb_ar">
+ Sorani Kurdish Arabic-based keyboard
+ </int>
+ <int value="1486336701" label="zh-hant-t-i0-und_old">
+ Zhuyin input method (obsolete)
+ </int>
+ <int value="1530194498" label="vkd_deva_phone">
+ Devanagari keyboard (Phonetic)
+ </int>
+ <int value="1624346366" label="zh-hant-t-i0-und">Zhuyin input method</int>
<int value="1643737979" label="xkb:fr:bepo:fra">French Bepo keyboard</int>
+ <int value="1680967466" label="sa-t-i0-und">Sanskrit transliteration</int>
<int value="1683010298" label="xkb:is::ice">Icelandic keyboard</int>
- <int value="1698488657" label="ar-t-i0-und">Arabic transliteration</int>
+ <int value="1691327142" label="vkd_gu_phone">
+ Gujarati keyboard (Phonetic)
+ </int>
+ <int value="1698488657" label="ar-t-i0-und_old">
+ Arabic transliteration (obsolete)
+ </int>
<int value="1718072990" label="xkb:us::eng">US keyboard</int>
- <int value="1756602568" label="zh-hant-t-i0-array-1992">
- Array input method
+ <int value="1756602568" label="zh-hant-t-i0-array-1992_old">
+ Array input method (obsolete)
</int>
<int value="1763643144" label="xkb:lt::lit">Lithuanian keyboard</int>
- <int value="1772226972" label="ur-t-i0-und">Urdu transliteration</int>
+ <int value="1772226972" label="ur-t-i0-und_old">
+ Urdu transliteration (obsolete)
+ </int>
+ <int value="1783807851" label="nacl_mozc_us_old">
+ Google Japanese Input (for US keyboard) (obsolete)
+ </int>
+ <int value="1842376130" label="vkd_ta_typewriter">
+ Tamil keyboard (Typewriter)
+ </int>
<int value="1847701260" label="xkb:pl::pol">Polish keyboard</int>
<int value="1851658441" label="xkb:hu:qwerty:hun">
Hungarian QWERTY keyboard
</int>
<int value="1882667893" label="xkb:us:colemak:eng">US Colemak keyboard</int>
<int value="1925299009" label="xkb:br::por">Brazilian keyboard</int>
- <int value="1934249765" label="vkd_th_pattajoti">
- Thai keyboard (Pattachote)
+ <int value="1934249765" label="vkd_th_pattajoti_old">
+ Thai keyboard (Pattachote) (obsolete)
+ </int>
+ <int value="1952551273" label="vkd_ta_tamil99">Tamil keyboard (Tamil99)</int>
+ <int value="1957701631" label="am-t-i0-und_old">
+ Amharic transliteration (obsolete)
</int>
- <int value="1957701631" label="am-t-i0-und">Amharic transliteration</int>
+ <int value="1960657481" label="vkd_vi_telex">Vietnamese keyboard (Telex)</int>
<int value="1970923579" label="xkb:us:intl:nld">Netherlands keyboard</int>
<int value="1983264676" label="xkb:no::nob">Norwegian keyboard</int>
<int value="2007323478" label="xkb:cz::cze">Czech keyboard</int>
<int value="2014669693" label="xkb:kz::kaz">Kazakh keyboard</int>
- <int value="2024146574" label="vkd_lo">Lao keyboard</int>
- <int value="2029882285" label="vkd_kn_phone">Kannada keyboard (Phonetic)</int>
+ <int value="2018878326" label="zh-hant-t-i0-cangjie-1987">
+ Cangjie input method
+ </int>
+ <int value="2024146574" label="vkd_lo_old">Lao keyboard (obsolete)</int>
+ <int value="2029882285" label="vkd_kn_phone_old">
+ Kannada keyboard (Phonetic) (obsolete)
+ </int>
<int value="2031967946" label="xkb:mt::mlt">Maltese keyboard</int>
- <int value="2051698871" label="nacl_mozc_us">
- Google Japanese Input (for US keyboard)
+ <int value="2051698871" label="nacl_mozc_us_old">
+ Google Japanese Input (for US keyboard) (obsolete)
</int>
<int value="2060414855" label="braille">Braille Keyboard</int>
+ <int value="2077260254" label="ko-t-i0-und">Korean input method</int>
<int value="2121258069" label="xkb:us:dvorak:eng">US Dvorak keyboard</int>
+ <int value="2143389015" label="vkd_ne_inscript">
+ Nepali keyboard (InScript)
+ </int>
</enum>
<enum name="InsecureContentType">
@@ -24758,6 +25366,7 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<int value="9" label="BLE not present"/>
<int value="10" label="WiFi not present"/>
<int value="11" label="Suspended"/>
+ <int value="12" label="MultiDevice host unverified"/>
</enum>
<enum name="InstantTethering_HostScanResult">
@@ -24786,6 +25395,7 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<int value="7" label="Cellular disabled"/>
<int value="8" label="Wi-Fi disabled"/>
<int value="9" label="Bluetooth controller disappeared"/>
+ <int value="10" label="MultiDevice host unverified"/>
</enum>
<enum name="IntelMaxMicroArchitecture">
@@ -24825,6 +25435,9 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
label="Subframe navigation start before main frame navigation start"/>
<int value="16"
label="IPC received from subframe while not tracking a committed load"/>
+ <int value="17"
+ label="PageLoadFeatures received from browser process while not
+ tracking a relevant committed load"/>
</enum>
<enum name="InterruptReason">
@@ -24855,6 +25468,7 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<int value="36" label="SERVER_FORBIDDEN"/>
<int value="37" label="SERVER_UNREACHABLE"/>
<int value="38" label="SERVER_CONTENT_LENGTH_MISMATCH"/>
+ <int value="39" label="SERVER_CROSS_ORIGIN_REDIRECT"/>
<int value="40" label="USER_CANCELED"/>
<int value="41" label="USER_SHUTDOWN"/>
<int value="50" label="CRASH"/>
@@ -26256,6 +26870,11 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
</int>
</enum>
+<enum name="LaunchType">
+ <int value="0" label="From icon"/>
+ <int value="1" label="Not from icon"/>
+</enum>
+
<enum name="LazyCSSParseUsage">
<int value="0" label="&gt;= 0%"/>
<int value="1" label="&gt; 10%"/>
@@ -26266,6 +26885,12 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<int value="6" label="= 100%"/>
</enum>
+<enum name="LazyLoad.FrameInitialDeferralAction">
+ <int value="0" label="Deferred"/>
+ <int value="1" label="Loaded because near or in viewport"/>
+ <int value="2" label="Loaded because hidden"/>
+</enum>
+
<enum name="LevelDBCorruptionRestoreValue">
<int value="0" label="Database Delete Success"/>
<int value="1" label="Database Delete Failure"/>
@@ -26452,7 +27077,9 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<int value="150" label="openSUSE Other"/>
<int value="151" label="openSUSE Leap 42.2"/>
<int value="152" label="openSUSE Leap 42.3"/>
- <int value="153" label="openSUSE Leap 15"/>
+ <int value="153" label="openSUSE Leap 15.0"/>
+ <int value="154" label="openSUSE Leap 15.1"/>
+ <int value="155" label="openSUSE Leap 15.2"/>
<int value="200" label="Ubuntu Other"/>
<int value="201" label="Ubuntu 14.04"/>
<int value="202" label="Ubuntu 16.04"/>
@@ -26703,6 +27330,13 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<int value="1" label="SinkNeverStarted"/>
</enum>
+<enum name="LocalSiteCharacteristicsDBInitStatus">
+ <int value="0" label="Success"/>
+ <int value="1" label="Corruption"/>
+ <int value="2" label="IO Error"/>
+ <int value="3" label="Unknown Error"/>
+</enum>
+
<enum name="LocalStorageOpenError">
<int value="0" label="Directory open failed"/>
<int value="1" label="Database open failed"/>
@@ -26717,6 +27351,11 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<int value="2" label="Area with references loaded"/>
</enum>
+<enum name="LockedFullscreenState">
+ <int value="0" label="Exited"/>
+ <int value="1" label="Entered"/>
+</enum>
+
<enum name="LockScreenActionAvailability">
<int value="0" label="Available"/>
<int value="1" label="Not available - no action handler app"/>
@@ -26821,23 +27460,25 @@ from previous Chrome versions.
label="enable-fill-on-account-select-no-highlighting"/>
<int value="-2143113994" label="enable-ephemeral-apps-in-webstore"/>
<int value="-2141661938" label="AnimatedAppMenuIcon:enabled"/>
- <int value="-2134717874" label="Multidevice:disabled"/>
<int value="-2134333982" label="ShowArcFilesApp:enabled"/>
<int value="-2134244069" label="HttpFormWarning:enabled"/>
<int value="-2132591642" label="enable-input-view"/>
<int value="-2124839789"
label="OmniboxUIExperimentHideSteadyStateUrlSchemeAndSubdomains:enabled"/>
+ <int value="-2123795624" label="ArcSmartTextSelection:enabled"/>
<int value="-2122048316"
label="DisplayPersistenceToggleInPermissionPrompts:enabled"/>
<int value="-2119827860" label="ash-disable-maximize-mode-window-backdrop"/>
<int value="-2119530966" label="enable-webrtc-dtls12"/>
<int value="-2119493239" label="enable-app-info-dialog-mac"/>
+ <int value="-2118893353" label="WebRtcRemoteEventLog:enabled"/>
<int value="-2117621241" label="ExperimentalProductivityFeatures:enabled"/>
<int value="-2117201726" label="disable-gpu-rasterization"/>
<int value="-2114831248" label="disable-new-ntp"/>
<int value="-2113705745"
label="CrossOriginMediaPlaybackRequiresUserGesture:enabled"/>
<int value="-2108564200" label="AutofillUpstream:disabled"/>
+ <int value="-2101682955" label="EnableNotificationIndicator:enabled"/>
<int value="-2099457894" label="Mash:enabled"/>
<int value="-2099035488" label="enable-data-reduction-proxy-bypass-warning"/>
<int value="-2098610409" label="disable-lcd-text"/>
@@ -26845,6 +27486,7 @@ from previous Chrome versions.
<int value="-2097515669" label="disable-cast"/>
<int value="-2091404586" label="TabStripKeyboardFocus:enabled"/>
<int value="-2090484194" label="ContextualSearchUrlActions:disabled"/>
+ <int value="-2088472280" label="KeyboardShortcutViewerApp:disabled"/>
<int value="-2083998415" label="VrLaunchIntent:enabled"/>
<int value="-2083195884" label="enable-firewall-hole-punching"/>
<int value="-2082462043" label="ViewPasswords:disabled"/>
@@ -26854,6 +27496,7 @@ from previous Chrome versions.
<int value="-2075870708" label="MediaRemotingEncrypted:disabled"/>
<int value="-2075807193" label="enable-webusb-on-any-origin"/>
<int value="-2075725205" label="disable-new-zip-unpacker"/>
+ <int value="-2074080173" label="NightLight:disabled"/>
<int value="-2067166422" label="enable-slimming-paint-v2"/>
<int value="-2066541315" label="Mus:enabled"/>
<int value="-2064164557" label="DownloadsForeground:disabled"/>
@@ -26868,6 +27511,7 @@ from previous Chrome versions.
<int value="-2048679945" label="NTPOfflinePageDownloadSuggestions:disabled"/>
<int value="-2047832738" label="enable-system-timezone-automatic-detection"/>
<int value="-2047822258" label="enable-avfoundation"/>
+ <int value="-2047190657" label="SyncUserConsentSeparateType:enabled"/>
<int value="-2043128632" label="enable-tab-switcher-in-document-mode"/>
<int value="-2041668231" label="V8ContextSnapshot:disabled"/>
<int value="-2040471724" label="CrOSComponent:disabled"/>
@@ -26876,6 +27520,7 @@ from previous Chrome versions.
label="KeepAliveRendererForKeepaliveRequests:enabled"/>
<int value="-2036149591" label="FaviconsFromWebManifest:disabled"/>
<int value="-2035126988" label="enabled-new-style-notification"/>
+ <int value="-2033908928" label="NightLight:enabled"/>
<int value="-2033225430" label="NTPMostLikelyFaviconsFromServer:disabled"/>
<int value="-2030217301" label="password-export:disabled"/>
<int value="-2029912304" label="StaleWhileRevalidate2:enabled"/>
@@ -26886,10 +27531,12 @@ from previous Chrome versions.
<int value="-2020024440" label="scroll-end-effect"/>
<int value="-2017953534" label="enable-hosted-app-shim-creation"/>
<int value="-2013551096" label="ViewsSimplifiedFullscreenUI:disabled"/>
+ <int value="-2013124655" label="EnableEphemeralFlashPermission:disabled"/>
<int value="-2012990889" label="SpannableInlineAutocomplete:enabled"/>
<int value="-2009622663" label="WebRtcHWH264Encoding:enabled"/>
<int value="-2008272679" label="disable-webrtc-hw-encoding"/>
<int value="-2005089558" label="BackgroundVideoTrackOptimization:disabled"/>
+ <int value="-2004231189" label="AppNotificationStatusMessaging:disabled"/>
<int value="-2003354337"
label="enable-search-button-in-omnibox-for-str-or-iip"/>
<int value="-2000567059" label="SimplifyHttpsIndicator:enabled"/>
@@ -26898,6 +27545,7 @@ from previous Chrome versions.
<int value="-1989747818" label="TabStripKeyboardFocus:disabled"/>
<int value="-1985025593" label="file-manager-enable-new-gallery"/>
<int value="-1983569861" label="WebXROrientationSensorDevice:disabled"/>
+ <int value="-1982700103" label="EnableAppsGridGapFeature:enabled"/>
<int value="-1980328793" label="trace-upload-url"/>
<int value="-1977496883" label="ViewPasswords:enabled"/>
<int value="-1973722176" label="VoiceSearchOnLocalNtp:enabled"/>
@@ -26926,6 +27574,7 @@ from previous Chrome versions.
<int value="-1943817505" label="SingleClickAutofill:enabled"/>
<int value="-1943507605" label="enable-new-video-renderer"/>
<int value="-1943313820" label="SystemKeyboardLock:disabled"/>
+ <int value="-1942730618" label="WebAuthenticationTouchId:disabled"/>
<int value="-1941852572" label="floating-virtual-keyboard"/>
<int value="-1940806558" label="enable-syncfs-directory-operation"/>
<int value="-1940377152" label="MacRTL:enabled"/>
@@ -26951,6 +27600,7 @@ from previous Chrome versions.
label="OverlayScrollbarFlashAfterAnyScrollUpdate:enabled"/>
<int value="-1907565048" label="HtmlBaseUsernameDetector:disabled"/>
<int value="-1907342706" label="ReadItLaterInMenu:disabled"/>
+ <int value="-1899715534" label="GamepadPollingInterval:enabled"/>
<int value="-1895719323" label="VrBrowsingTabsView:enabled"/>
<int value="-1892555086" label="disable-compositor-animation-timelines"/>
<int value="-1892000374" label="SeccompSandboxAndroid:enabled"/>
@@ -26992,7 +27642,6 @@ from previous Chrome versions.
label="enable-loading-ipc-optimization-for-small-resources"/>
<int value="-1844754731" label="Mash:disabled"/>
<int value="-1839874877" label="WebXROrientationSensorDevice:enabled"/>
- <int value="-1839637286" label="AutofillCreditCardBankNameDisplay:disabled"/>
<int value="-1839496458" label="disable-file-manager-touch-mode"/>
<int value="-1838482444" label="disable-settings-window"/>
<int value="-1837329460" label="NewEncodeCpuLoadEstimator:enabled"/>
@@ -27000,12 +27649,15 @@ from previous Chrome versions.
<int value="-1833149810" label="enable-accessibility-tab-switcher"/>
<int value="-1832575380" label="show-saved-copy"/>
<int value="-1832221649" label="disable-out-of-process-pac"/>
+ <int value="-1826649921" label="ContextualSuggestionsButton:disabled"/>
<int value="-1821058653" label="enable-delay-agnostic-aec"/>
<int value="-1817209284" label="PayWithGoogleV1:enabled"/>
<int value="-1816066138" label="CastAllowAllIPs:enabled"/>
<int value="-1812579951" label="ContentSuggestionsCategoryRanker:enabled"/>
+ <int value="-1811887751" label="ChromeModernFullRoll:disabled"/>
<int value="-1811394154" label="disable-webrtc-hw-vp8-encoding"/>
<int value="-1810294310" label="AndroidPaymentApps:enabled"/>
+ <int value="-1809835803" label="LayoutNG:disabled"/>
<int value="-1808576075" label="SystemTrayUnified:enabled"/>
<int value="-1808477331" label="MidiManagerCros:disabled"/>
<int value="-1807797669" label="google-doodle-url"/>
@@ -27024,6 +27676,7 @@ from previous Chrome versions.
<int value="-1772172557" label="enable-osk-overscroll"/>
<int value="-1768672408" label="ChromeDuplex:disabled"/>
<int value="-1767470652" label="out-of-process-pdf"/>
+ <int value="-1758468685" label="DownloadHomeV2:disabled"/>
<int value="-1755301960" label="ClearOldBrowsingData:enabled"/>
<int value="-1751928267" label="disable-icon-ntp"/>
<int value="-1749176684" label="PauseBackgroundTabs:disabled"/>
@@ -27035,6 +27688,7 @@ from previous Chrome versions.
<int value="-1735643253" label="enable-display-list-2d-canvas"/>
<int value="-1734254845" label="ash-enable-night-light"/>
<int value="-1732561795" label="ConsistentOmniboxGeolocation:enabled"/>
+ <int value="-1731149013" label="AndroidMessagesIntegration:enabled"/>
<int value="-1729926412" label="enable-webusb-notifications"/>
<int value="-1725507605" label="enable-web-midi"/>
<int value="-1719833926" label="disable-answers-in-suggest"/>
@@ -27042,6 +27696,7 @@ from previous Chrome versions.
<int value="-1714128884" label="disable-launcher-search-provider-api"/>
<int value="-1713564656" label="ProtectSyncCredentialOnReauth:enabled"/>
<int value="-1711751318" label="enable-data-reduction-proxy-lo-fi-preview"/>
+ <int value="-1710772665" label="disable-my-files-navigation"/>
<int value="-1703709912" label="enable-new-ntp"/>
<int value="-1703308540" label="disable-webaudio"/>
<int value="-1696366449" label="disable-permissions-bubbles"/>
@@ -27071,11 +27726,15 @@ from previous Chrome versions.
<int value="-1648216169" label="NewOmniboxAnswerTypes:disabled"/>
<int value="-1638815914" label="enable-experimental-productivity-features"/>
<int value="-1634878515" label="ChromeHomeModernLayout:enabled"/>
+ <int value="-1634490190"
+ label="AutofillCreditCardLocalCardMigration:disabled"/>
<int value="-1634154256" label="ZeroSuggestRedirectToChrome:enabled"/>
<int value="-1633586675" label="TabModalJsDialog:enabled"/>
<int value="-1631329950" label="ssl-version-max"/>
<int value="-1630419335" label="enable-download-notification"/>
<int value="-1625881240" label="FullscreenExitUI:disabled"/>
+ <int value="-1625777277"
+ label="AutofillUpstreamEditableCardholderName:disabled"/>
<int value="-1624854957" label="enable-es3-apis"/>
<int value="-1624593106" label="NewTabPageBackgrounds:enabled"/>
<int value="-1620804800" label="NoScriptPreviews:disabled"/>
@@ -27101,6 +27760,7 @@ from previous Chrome versions.
<int value="-1583533050" label="RuntimeHostPermissions:disabled"/>
<int value="-1581724231" label="ModalPermissionPrompts:enabled"/>
<int value="-1580376019" label="ShowAllDialogsWithViewsToolkit:enabled"/>
+ <int value="-1578503491" label="EnableContinueReading:disabled"/>
<int value="-1578295753" label="UserMediaScreenCapturing:disabled"/>
<int value="-1575772949" label="DesktopPWAsLinkCapturing:disabled"/>
<int value="-1575554415" label="AndroidPaymentAppsFilter:enabled"/>
@@ -27114,6 +27774,7 @@ from previous Chrome versions.
<int value="-1557527869" label="LoadingWithMojo:disabled"/>
<int value="-1555510175" label="PasswordImport:enabled"/>
<int value="-1553477903" label="ash-disable-text-filtering-in-overview-mode"/>
+ <int value="-1552898031" label="SingleTabMode:enabled"/>
<int value="-1549871007" label="OneGoogleBarOnLocalNtp:disabled"/>
<int value="-1547247328" label="OverrideTranslateTriggerInIndia:disabled"/>
<int value="-1546903171" label="enable-touch-drag-drop"/>
@@ -27122,8 +27783,10 @@ from previous Chrome versions.
<int value="-1544248549" label="ArcUseAuthEndpoint:enabled"/>
<int value="-1543316040"
label="DisplayPersistenceToggleInPermissionPrompts:disabled"/>
+ <int value="-1538492024" label="OmniboxReverseAnswers:enabled"/>
<int value="-1536293422" label="SharedArrayBuffer:enabled"/>
<int value="-1536242739" label="security-chip"/>
+ <int value="-1535758690" label="AutoplayIgnoreWebAudio:disabled"/>
<int value="-1532035450" label="DragTabsInTabletMode:disabled"/>
<int value="-1532014193" label="disable-encryption-migration"/>
<int value="-1520855274" label="PWAFullCodeCache:disabled"/>
@@ -27167,6 +27830,7 @@ from previous Chrome versions.
<int value="-1467332609" label="tab-management-experiment-type-anise"/>
<int value="-1466990325" label="CrosCompUpdates:enabled"/>
<int value="-1466759286" label="TabModalJsDialog:disabled"/>
+ <int value="-1465172796" label="CCTModule:disabled"/>
<int value="-1463489219" label="OfflinePagesCTSuppressNotifications:enabled"/>
<int value="-1463410070" label="IPH_DemoMode:enabled"/>
<int value="-1461261930" label="OutOfBlinkCORS:disabled"/>
@@ -27193,6 +27857,7 @@ from previous Chrome versions.
<int value="-1426150007" label="ignore-previews-blacklist"/>
<int value="-1426034869" label="NoCreditCardAbort:enabled"/>
<int value="-1423348289" label="NupPrinting:disabled"/>
+ <int value="-1420542268" label="AutofillEnableAccountWalletStorage:disabled"/>
<int value="-1419788257" label="enable-experimental-hotwording"/>
<int value="-1417122729"
label="AutofillCreditCardAblationExperiment:disabled"/>
@@ -27210,20 +27875,28 @@ from previous Chrome versions.
<int value="-1392562498" label="disable-origin-chip"/>
<int value="-1391693054"
label="ContentSuggestionsFaviconsFromNewServer:disabled"/>
+ <int value="-1388817073" label="OmniboxReverseAnswers:disabled"/>
<int value="-1386966873" label="disable-mac-views-native-app-windows"/>
+ <int value="-1385221197"
+ label="AllowSignedHTTPExchangeCertsWithoutExtension:enabled"/>
+ <int value="-1383597259" label="SyncUserConsentSeparateType:disabled"/>
<int value="-1382671832" label="OmniboxUIExperimentVerticalMargin:enabled"/>
<int value="-1377186702" label="DesktopIOSPromotion:disabled"/>
<int value="-1376510363" label="ServiceWorkerScriptFullCodeCache:disabled"/>
<int value="-1375111024" label="enable-fixed-position-compositing"/>
+ <int value="-1373942769" label="WebAuthenticationCtap2:disabled"/>
<int value="-1373705581" label="ManualSaving:enabled"/>
<int value="-1365503870" label="enable-simplified-fullscreen-ui"/>
<int value="-1363709707" label="MaterialDesignHistory:disabled"/>
<int value="-1358669137" label="enable-supervised-user-blacklist"/>
<int value="-1357655121" label="enable-iframe-based-signin"/>
<int value="-1357008397" label="ContextualSuggestionsCarousel:disabled"/>
+ <int value="-1351328710"
+ label="OmniboxUIExperimentJogTextfieldOnPopup:disabled"/>
<int value="-1349896789" label="DelayNavigation:enabled"/>
<int value="-1349872906"
label="disallow-autofill-sync-credential-for-reauth"/>
+ <int value="-1349826793" label="ArcInputMethod:disabled"/>
<int value="-1349532167" label="enable-wifi-credential-sync"/>
<int value="-1346722635" label="gesture-selection"/>
<int value="-1344375439" label="ServiceWorkerPaymentApps:disabled"/>
@@ -27247,6 +27920,7 @@ from previous Chrome versions.
<int value="-1311133348" label="VrBrowsingNativeAndroidUi:enabled"/>
<int value="-1310737697" label="MaterialDesignSettings:enabled"/>
<int value="-1304957199" label="OfflinePagesShowAlternateDinoPage:enabled"/>
+ <int value="-1303995589" label="shelf-new-ui"/>
<int value="-1302904242" label="enable-navigation-tracing"/>
<int value="-1302859198" label="enable-stylus-virtual-keyboard:disabled"/>
<int value="-1294050129" label="ContentFullscreen:disabled"/>
@@ -27272,6 +27946,7 @@ from previous Chrome versions.
<int value="-1255427595" label="HomePageButtonForceEnabled:enabled"/>
<int value="-1254070521" label="enable-slimming-paint-invalidation"/>
<int value="-1251411236" label="disable-new-md-input-view"/>
+ <int value="-1250611337" label="ChromeVoxArcSupport:disabled"/>
<int value="-1248478422" label="enable-zip-archiver-packer"/>
<int value="-1246840031" label="OptInImeMenu:disabled"/>
<int value="-1241747717" label="enable-android-password-link"/>
@@ -27284,6 +27959,7 @@ from previous Chrome versions.
<int value="-1218608640" label="disable-offline-load-stale-cache"/>
<int value="-1217425153" label="ChromeHomeClearUrlOnOpen:enabled"/>
<int value="-1216837777" label="clear-data-reduction-proxy-data-savings"/>
+ <int value="-1214870820" label="EnableNewStyleLauncher:enabled"/>
<int value="-1212855900" label="enable-all-bookmarks-view"/>
<int value="-1212273428" label="enable-experimental-app-list"/>
<int value="-1212167260" label="disable-app-window-cycling"/>
@@ -27321,11 +27997,14 @@ from previous Chrome versions.
<int value="-1151766565" label="enable-fullscreen-tab-detaching"/>
<int value="-1145702446" label="ChromeHomeInactivitySheetExpansion:enabled"/>
<int value="-1145246849" label="ThirdPartyDoodles:enabled"/>
+ <int value="-1143496217" label="enable-oop-rasterization"/>
+ <int value="-1143007275" label="EnableNewStyleLauncher:disabled"/>
<int value="-1137442543" label="enable-slimming-paint"/>
<int value="-1136627751" label="ignore-autocomplete-off-autofill"/>
<int value="-1136509631" label="ssl-interstitial-v1"/>
<int value="-1134307340" label="stop-loading-in-background:enabled"/>
<int value="-1132704128" label="AndroidPaymentAppsFilter:disabled"/>
+ <int value="-1128912963" label="MediaControlsExpandGesture:disabled"/>
<int value="-1127996427" label="enable-files-details-panel"/>
<int value="-1126217973" label="IdleTimeSpellChecking:disabled"/>
<int value="-1125840399" label="ViewsBrowserWindows:enabled"/>
@@ -27342,6 +28021,7 @@ from previous Chrome versions.
<int value="-1096595907" label="disable-new-virtual-keyboard-behavior"/>
<int value="-1095947169" label="ModalPermissionDialogView:disabled"/>
<int value="-1085492638" label="FetchKeepaliveTimeoutSetting:enabled"/>
+ <int value="-1084855234" label="UnfilteredBluetoothDevices:disabled"/>
<int value="-1084055006" label="disable-web-notification-custom-layouts"/>
<int value="-1082302549" label="scan-cards-in-web-payments"/>
<int value="-1078093206" label="ash-debug-shortcuts"/>
@@ -27359,6 +28039,7 @@ from previous Chrome versions.
<int value="-1052415111" label="malware-interstitial-v2"/>
<int value="-1052219252" label="disable-captive-portal-bypass-proxy"/>
<int value="-1048901516" label="ChromeMemex:enabled"/>
+ <int value="-1046641729" label="TranslateUI:enabled"/>
<int value="-1046627610" label="password-import:enabled"/>
<int value="-1045900007" label="NoCreditCardAbort:disabled"/>
<int value="-1045882995" label="UseNewDoodleApi:enabled"/>
@@ -27367,20 +28048,26 @@ from previous Chrome versions.
<int value="-1039555838" label="GamepadExtensions:enabled"/>
<int value="-1034344165" label="V8NoTurbo:disabled"/>
<int value="-1033738911" label="enable-mac-views-dialogs"/>
+ <int value="-1032031735" label="SuggestedTextTouchBar:enabled"/>
<int value="-1031350684" label="PdfIsolation:disabled"/>
<int value="-1029920490" label="IdleTimeSpellChecking:enabled"/>
<int value="-1028733699" label="MacViewsWebUIDialogs:disabled"/>
+ <int value="-1028251580" label="GamepadPollingInterval:disabled"/>
<int value="-1027254093" label="LockScreenNotifications:disabled"/>
<int value="-1027124889" label="NtlmV2Enabled:enabled"/>
<int value="-1022971520" label="enable-search-button-in-omnibox-for-str"/>
<int value="-1022165708" label="BreakingNewsPush:disabled"/>
<int value="-1020450980" label="gesture-deletion"/>
<int value="-1019967332" label="VrBrowsing:enabled"/>
+ <int value="-1019492310"
+ label="OmniboxUIExperimentJogTextfieldOnPopup:enabled"/>
+ <int value="-1016669222" label="CloudPrinterHandler:enabled"/>
<int value="-1016202433" label="disable-add-to-shelf"/>
<int value="-1015006759" label="ImportantSitesInCBD:disabled"/>
<int value="-1014649471" label="committed-interstitials"/>
<int value="-998255750" label="ExperimentalKeyboardLockUI:enabled"/>
<int value="-996673716" label="enable-web-app-frame"/>
+ <int value="-994558985" label="EnableNotificationIndicator:disabled"/>
<int value="-994088375" label="VrBrowsingExperimentalRendering:enabled"/>
<int value="-991253797"
label="OmniboxSpeculativeServiceWorkerStartOnQueryInput:disabled"/>
@@ -27394,8 +28081,10 @@ from previous Chrome versions.
<int value="-973509424" label="NewTabPageIcons:disabled"/>
<int value="-972737445" label="ArcUseAuthEndpoint:disabled"/>
<int value="-972425050" label="gesture-editing"/>
+ <int value="-970067535" label="BackgroundTaskComponentUpdate:disabled"/>
<int value="-969332901" label="stop-non-timers-in-background:disabled"/>
<int value="-968010468" label="SharedArrayBuffer:disabled"/>
+ <int value="-966290456" label="WebAuthenticationCtap2:enabled"/>
<int value="-965842218" label="MultiDeviceApi:disabled"/>
<int value="-964676765" label="enable-accelerated-mjpeg-decode"/>
<int value="-951394314" label="top-chrome-md"/>
@@ -27410,6 +28099,7 @@ from previous Chrome versions.
<int value="-918900957" label="AutofillCreditCardAssist:disabled"/>
<int value="-918618075" label="enable-service-worker"/>
<int value="-914210146" label="enable-web-based-signin"/>
+ <int value="-913294939" label="DriveFS:enabled"/>
<int value="-912456561" label="MidiManagerWinrt:enabled"/>
<int value="-908421850" label="PointerEvent:enabled"/>
<int value="-907234795" label="NewAudioRenderingMixingStrategy:disabled"/>
@@ -27419,6 +28109,8 @@ from previous Chrome versions.
<int value="-898594349" label="ash-enable-stable-overview-order"/>
<int value="-898499262" label="ImprovedA2HS:enabled"/>
<int value="-898005938" label="disable-pinch-virtual-viewport"/>
+ <int value="-897069393"
+ label="kAutofillRationalizeRepeatedServerPredictions:disabled"/>
<int value="-894214299" label="fill-on-account-select:enabled"/>
<int value="-894185031" label="HighDynamicRange:disabled"/>
<int value="-891856063" label="MidiManagerAndroid:enabled"/>
@@ -27467,12 +28159,17 @@ from previous Chrome versions.
<int value="-812461825" label="AutofillCreditCardSigninPromo:enabled"/>
<int value="-810684526"
label="AutofillToolkitViewsCreditCardDialogsMac:disabled"/>
+ <int value="-810373609" label="ChromeModernFullRoll:enabled"/>
+ <int value="-808486493" label="NewWallpaperPicker:disabled"/>
<int value="-802348444" label="disable-site-engagement-service"/>
<int value="-798187384" label="try-supported-channel-layouts"/>
+ <int value="-797310986" label="CSSFragmentIdentifiers:disabled"/>
<int value="-795600188" label="disable-async-dns"/>
<int value="-793921836" label="ShowAllDialogsWithViewsToolkit:disabled"/>
+ <int value="-792079435" label="EnableAppsGridGapFeature:disabled"/>
<int value="-790036192" label="overscroll-start-threshold"/>
<int value="-787426248" label="ChromeHomeSurvey:disabled"/>
+ <int value="-782536046" label="NewContactsPicker:enabled"/>
<int value="-780798969" label="disable-single-click-autofill"/>
<int value="-780599934" label="AutofillUpstreamSendPanFirstSix:enabled"/>
<int value="-778126349" label="DownloadsLocationChange:enabled"/>
@@ -27485,19 +28182,23 @@ from previous Chrome versions.
<int value="-763759697" label="enable-audio-support-for-desktop-share"/>
<int value="-762687134" label="ExperimentalCrostiniUI:enabled"/>
<int value="-759830869" label="enable-tab-discarding"/>
+ <int value="-758048639" label="InfiniteSessionRestore:enabled"/>
<int value="-757946835"
label="OmniboxUIExperimentShowSuggestionFavicons:enabled"/>
- <int value="-751273871" label="AutofillCreditCardBankNameDisplay:enabled"/>
+ <int value="-757379927" label="Canvas2DImageChromium:enabled"/>
<int value="-750175757" label="ClientLoFi:enabled"/>
<int value="-749048160" label="enable-panels"/>
<int value="-747463111" label="ContentSuggestionsNotifications:disabled"/>
<int value="-746328467" label="ExpensiveBackgroundTimerThrottling:disabled"/>
<int value="-744159181" label="disable-spdy-proxy-dev-auth-origin"/>
<int value="-743103250" label="enable-linkable-ephemeral-apps"/>
+ <int value="-742469530" label="DriveFS:disabled"/>
<int value="-741806604" label="DownloadsUi:disabled"/>
<int value="-738957187" label="OmniboxUIExperimentSwapTitleAndUrl:disabled"/>
+ <int value="-726892130" label="AndroidMessagesIntegration:disabled"/>
<int value="-723224470" label="enable-password-force-saving:enabled"/>
<int value="-722474177" label="browser-side-navigation:disabled"/>
+ <int value="-719819631" label="TranslateUI:disabled"/>
<int value="-719147284" label="ExperimentalProductivityFeatures:disabled"/>
<int value="-718884399" label="NewTabPageUIMd:enabled"/>
<int value="-718626298" label="SysInternals:enabled"/>
@@ -27511,11 +28212,15 @@ from previous Chrome versions.
<int value="-709058455" label="ui-slow-animations"/>
<int value="-707655322" label="Newblue:disabled"/>
<int value="-706733351" label="enable-floating-virtual-keyboard:enabled"/>
+ <int value="-705746939" label="ChromeDuet:enabled"/>
<int value="-704232562" label="UseMonitorColorSpace:enabled"/>
<int value="-702477233" label="ContentFullscreen:enabled"/>
<int value="-699767107" label="enable-sync-app-list"/>
<int value="-699198009" label="KeyboardShortcutViewer:enabled"/>
+ <int value="-697887799"
+ label="AutofillSaveCardDialogUnlabeledExpirationDate:disabled"/>
<int value="-697751423" label="disable-quickoffice-component-app"/>
+ <int value="-696693295" label="Canvas2DImageChromium:disabled"/>
<int value="-684900739" label="disable-merge-key-char-events"/>
<int value="-684223908" label="enable-android-wallpapers-app"/>
<int value="-680787130" label="ExperimentalVRFeatures:disabled"/>
@@ -27532,6 +28237,7 @@ from previous Chrome versions.
<int value="-650504533" label="enable-speculative-launch-service-worker"/>
<int value="-650176557" label="OfflinePagesSvelteConcurrentLoading:enabled"/>
<int value="-649956990" label="enable-harfbuzz-rendertext"/>
+ <int value="-648925189" label="ExploreSites:enabled"/>
<int value="-645455405" label="MacViewsNativeDialogs:enabled"/>
<int value="-641719457" label="disable-compositor-touch-hit-testing"/>
<int value="-639026783" label="disable-gpu-appcontainer"/>
@@ -27575,6 +28281,8 @@ from previous Chrome versions.
<int value="-536230323" label="SingleClickAutofill:disabled"/>
<int value="-535662704" label="BundledConnectionHelp:enabled"/>
<int value="-535208779" label="enable-native-cups"/>
+ <int value="-533552313"
+ label="AutofillUpstreamEditableCardholderName:enabled"/>
<int value="-531810064" label="saveas-menu-label"/>
<int value="-531792555" label="UseModernMediaControls:disabled"/>
<int value="-531651776" label="NewRemotePlaybackPipeline:enabled"/>
@@ -27606,10 +28314,12 @@ from previous Chrome versions.
<int value="-474806100" label="DataReductionProxyMainMenu:enabled"/>
<int value="-474322576" label="disable-quick-unlock-pin"/>
<int value="-473087416" label="DragTabsInTabletMode:enabled"/>
+ <int value="-472014137" label="HomepageTile:disabled"/>
<int value="-472013317" label="WebRTC-H264WithOpenH264FFmpeg:disabled"/>
<int value="-471405972" label="ViewsProfileChooser:disabled"/>
<int value="-471085510" label="MultiDeviceApi:enabled"/>
<int value="-470948890" label="OfflinePagesDescriptivePendingStatus:enabled"/>
+ <int value="-468697885" label="ArcInputMethod:enabled"/>
<int value="-462205750" label="enable-service-worker-sync"/>
<int value="-461292699" label="ContentSuggestionsCategoryOrder:enabled"/>
<int value="-460313418" label="ProgressBarThrottle:enabled"/>
@@ -27621,6 +28331,7 @@ from previous Chrome versions.
<int value="-435914745" label="ClipboardContentSetting:disabled"/>
<int value="-430360431" label="disable-password-generation"/>
<int value="-428599163" label="NTPDownloadSuggestions:enabled"/>
+ <int value="-426815606" label="HomepageTile:enabled"/>
<int value="-424701311" label="SignedHTTPExchange:disabled"/>
<int value="-418868128" label="enable-experimental-web-platform-features"/>
<int value="-410852857" label="ImprovedA2HS:disabled"/>
@@ -27636,15 +28347,18 @@ from previous Chrome versions.
<int value="-387606010" label="ArcBootCompletedBroadcast:enabled"/>
<int value="-385337473" label="enable-fast-unload"/>
<int value="-384589459" label="disable-supervised-user-safesites"/>
+ <int value="-381181808" label="DragAppsInTabletMode:enabled"/>
<int value="-378180863" label="disable-panels"/>
<int value="-378033324" label="disable-win32k-renderer-lockdown"/>
<int value="-374657496" label="OmniboxEnableClipboardProvider:enabled"/>
<int value="-374423260" label="OmniboxTabSwitchSuggestions:disabled"/>
<int value="-367474066" label="DialogTouchBar:enabled"/>
+ <int value="-366949535" label="KeyboardShortcutViewerApp:enabled"/>
<int value="-365920680" label="ImageCaptureAPI:disabled"/>
<int value="-364587218" label="ResourceLoadScheduler:enabled"/>
<int value="-364325011" label="enable-files-quick-view"/>
<int value="-364267715" label="disable-native-cups"/>
+ <int value="-362821234" label="ExperimentalUi:enabled"/>
<int value="-362022976" label="disable-quirks-client"/>
<int value="-361948582" label="material-security-verbose"/>
<int value="-360453785" label="LeftToRightUrls:disabled"/>
@@ -27658,6 +28372,7 @@ from previous Chrome versions.
<int value="-346413328" label="UseNewAcceptLanguageHeader:disabled"/>
<int value="-345838366" label="enable-hosted-apps-in-windows"/>
<int value="-345324571" label="enable-quirks-client"/>
+ <int value="-345181892" label="new-tab-button-position"/>
<int value="-344343842" label="disable-experimental-app-list"/>
<int value="-343769596" label="ServiceWorkerScriptStreaming:disabled"/>
<int value="-340622848" label="disable-javascript-harmony-shipping"/>
@@ -27678,17 +28393,16 @@ from previous Chrome versions.
<int value="-314605926" label="protect-sync-credential-on-reauth:enabled"/>
<int value="-311148335" label="v8-pac-mojo-out-of-process"/>
<int value="-310908854" label="new-wallpaper-picker"/>
- <int value="-305029910" label="AutofillUpstreamSendDetectedValues:disabled"/>
<int value="-300018686" label="disable-cloud-import"/>
<int value="-299841473" label="top-document-isolation:enabled"/>
<int value="-297716805"
label="CrossOriginMediaPlaybackRequiresUserGesture:disabled"/>
<int value="-290672626" label="enable-asm-wasm"/>
<int value="-288316828" label="enable-delegated-renderer"/>
+ <int value="-286603268" label="hide-android-files-in-files-app"/>
<int value="-284547865" label="UnifiedConsent:enabled"/>
<int value="-283388027" label="ManualFallbacksFilling:disabled"/>
<int value="-281844827" label="AutofillCreditCardAblationExperiment:enabled"/>
- <int value="-280111192" label="AutofillUpstreamSendDetectedValues:enabled"/>
<int value="-279920685" label="affiliation-based-matching:enabled"/>
<int value="-279493876" label="WebVRExperimentalRendering:enabled"/>
<int value="-278347667" label="default-tile-height"/>
@@ -27703,6 +28417,7 @@ from previous Chrome versions.
<int value="-270626757" label="log-net-log"/>
<int value="-268357961" label="enable-feature-policy"/>
<int value="-263150202" label="BundledConnectionHelp:disabled"/>
+ <int value="-260355779" label="UnfilteredBluetoothDevices:enabled"/>
<int value="-254887599" label="google-profile-info"/>
<int value="-250822813" label="PwaImprovedSplashScreen:enabled"/>
<int value="-250721831" label="AndroidAutofillAccessibility:disabled"/>
@@ -27715,6 +28430,7 @@ from previous Chrome versions.
label="NonValidatingReloadOnRefreshContentV2:disabled"/>
<int value="-231922000" label="enable-renderer-mojo-channel"/>
<int value="-230824955" label="NTPMostLikelyFaviconsFromServer:enabled"/>
+ <int value="-225505731" label="CCTModule:enabled"/>
<int value="-220599034" label="UsePdfCompositorServiceForPrint:enabled"/>
<int value="-216219963" label="ash-shelf-color-scheme"/>
<int value="-215534141" label="NativeWindowNavButtons:enabled"/>
@@ -27724,6 +28440,7 @@ from previous Chrome versions.
<int value="-206393363" label="enable-scroll-prediction"/>
<int value="-204355195" label="secondary-ui-md"/>
<int value="-202007318" label="AndroidAIAFetching:enabled"/>
+ <int value="-200805659" label="ContextualSuggestionsButton:enabled"/>
<int value="-196110497" label="force-text-direction"/>
<int value="-195029497" label="MediaRemoting:disabled"/>
<int value="-192919826" label="ViewsSimplifiedFullscreenUI:enabled"/>
@@ -27768,17 +28485,20 @@ from previous Chrome versions.
<int value="-88822940" label="ssl-version-min"/>
<int value="-88273414" label="ContentSuggestionsShowSummary:enabled"/>
<int value="-86788587" label="allow-autofill-sync-credential"/>
+ <int value="-86243376" label="LayoutNG:enabled"/>
<int value="-80353187" label="disable-display-color-calibration"/>
<int value="-79327236" label="ModeSpecificPowerButton:enabled"/>
<int value="-78035185" label="custom_summary"/>
<int value="-77872983" label="BookmarkAppsMac:disabled"/>
<int value="-76631048" label="disable-offline-auto-reload-visible-only"/>
+ <int value="-75418012" label="ContextualSuggestionsOptOut:disabled"/>
<int value="-72455054" label="WebVrAutopresent:disabled"/>
<int value="-70595606" label="ash-enable-unified-desktop"/>
<int value="-69427025" label="OfflinePagesPrefetchingUI:enabled"/>
<int value="-68877684" label="BackgroundVideoTrackOptimization:enabled"/>
<int value="-68225452" label="enable-translate-new-ux"/>
<int value="-67297229" label="OfflinePagesDescriptivePendingStatus:disabled"/>
+ <int value="-59530055" label="ChromeVoxArcSupport:enabled"/>
<int value="-59401847" label="ContentSuggestionsLargeThumbnail:disabled"/>
<int value="-58242474" label="ash-disable-swipe-to-close-in-overview-mode"/>
<int value="-57986995" label="DisablePostScriptPrinting:enabled"/>
@@ -27791,16 +28511,20 @@ from previous Chrome versions.
<int value="-48920737" label="enable-smooth-scrolling"/>
<int value="-45849989" label="ModeSpecificPowerButton:disabled"/>
<int value="-45532639" label="enable-default-media-session"/>
+ <int value="-45487487" label="NewTabPageCustomLinks:disabled"/>
<int value="-45074716" label="SystemDownloadManager:disabled"/>
<int value="-45067971" label="NewPrintPreview:disabled"/>
<int value="-40935502" label="ContextualSuggestionsSlimPeekUI:enabled"/>
<int value="-35388407" label="AshNewSystemMenu:disabled"/>
+ <int value="-30966385" label="enable-hardware-overlays"/>
<int value="-29847483" label="MemoryAblation:enabled"/>
+ <int value="-28295905" label="AutofillEnableAccountWalletStorage:enabled"/>
<int value="-23804418"
label="NTPArticleSuggestionsExpandableHeader:disabled"/>
<int value="-23090520" label="disable-search-button-in-omnibox"/>
<int value="-22544408" label="enable-video-player-chromecast-support"/>
<int value="-19354048" label="AutofillUpstreamSendPanFirstSix:disabled"/>
+ <int value="-18464041" label="AutofillPrefilledFields:disabled"/>
<int value="-16824589" label="ash-shelf-color"/>
<int value="-13918890" label="disable-download-notification"/>
<int value="-11260186" label="enable-offline-pages-as-saved-pages"/>
@@ -27820,8 +28544,11 @@ from previous Chrome versions.
<int value="19815558" label="EnableSettingsShortcutSearch:disabled"/>
<int value="23556595" label="MarkHttpAs:enabled"/>
<int value="27507364" label="apps-keep-chrome-alive"/>
+ <int value="29212695" label="OfflineIndicator:enabled"/>
<int value="31848187" label="ViewsTaskManager:disabled"/>
<int value="33778663" label="OriginTrials:enabled"/>
+ <int value="36422284"
+ label="AutofillSaveCardDialogUnlabeledExpirationDate:enabled"/>
<int value="37024318" label="disable-affiliation-based-matching"/>
<int value="44088203" label="ExpensiveBackgroundTimerThrottling:enabled"/>
<int value="48159177" label="reduced-referrer-granularity"/>
@@ -27830,6 +28557,7 @@ from previous Chrome versions.
<int value="52368742" label="enable-pixel-canvas-recording:disabled"/>
<int value="54571864" label="EnableDisplayZoomSetting:enabled"/>
<int value="56723110" label="enable-webfonts-intervention"/>
+ <int value="57555893" label="NewContactsPicker:disabled"/>
<int value="57639188" label="SoundContentSetting:disabled"/>
<int value="57791920" label="MemoryCoordinator:enabled"/>
<int value="58099178" label="SecondaryUiMd:enabled"/>
@@ -27864,6 +28592,7 @@ from previous Chrome versions.
<int value="118991027" label="enable-accelerated-fixed-root-background"/>
<int value="119185738"
label="OmniboxUIExperimentMaxAutocompleteMatches:disabled"/>
+ <int value="119309423" label="WebAssemblyThreads:disabled"/>
<int value="120429808" label="disable-new-profile-management"/>
<int value="121684313" label="QuickUnlockPin:enabled"/>
<int value="121858954" label="enable-supervised-user-safesites"/>
@@ -27871,9 +28600,11 @@ from previous Chrome versions.
<int value="125581289" label="WebRtcHWVP8Encoding:disabled"/>
<int value="125934378" label="enable-password-link"/>
<int value="131881947" label="D3DVsync:enabled"/>
+ <int value="133482330" label="AppNotificationStatusMessaging:enabled"/>
<int value="143725809" label="DownloadProgressInfoBar:enabled"/>
<int value="147342055" label="ChromeHomeClearUrlOnOpen:disabled"/>
<int value="147373243" label="enable-deferred-image-decoding"/>
+ <int value="151022756" label="ArcAvailableForChildAccount:disabled"/>
<int value="151101719" label="HtmlBaseUsernameDetector:enabled"/>
<int value="157217034" label="enable-tab-for-desktop-share"/>
<int value="157318016" label="AutomaticTabDiscarding:enabled"/>
@@ -27904,6 +28635,7 @@ from previous Chrome versions.
<int value="255375615" label="stop-non-timers-in-background:enabled"/>
<int value="259021228" label="OffMainThreadFetch:disabled"/>
<int value="262382944" label="GuestViewCrossProcessFrames:disabled"/>
+ <int value="265830810" label="BackgroundTaskComponentUpdate:enabled"/>
<int value="266322815" label="ChromeModernDesign:disabled"/>
<int value="266702296" label="disable-plugin-power-saver"/>
<int value="268535107"
@@ -27921,6 +28653,7 @@ from previous Chrome versions.
<int value="303058039" label="AccountConsistency:disabled"/>
<int value="303252119" label="AutofillExpandedPopupViews:disabled"/>
<int value="304901781" label="NewUsbBackend:enabled"/>
+ <int value="307543404" label="disable-team-drives"/>
<int value="313303258" label="WebPaymentsModifiers:disabled"/>
<int value="316182183" label="MediaDocumentDownloadButton:disabled"/>
<int value="319683583" label="ContentSuggestionsDebugLog:enabled"/>
@@ -27935,6 +28668,7 @@ from previous Chrome versions.
<int value="336429189" label="DisallowUnsafeHttpDownloads:disabled"/>
<int value="339671131" label="disable-per-user-timezone"/>
<int value="341152650" label="SoundContentSetting:enabled"/>
+ <int value="345664265" label="BlinkHeapIncrementalMarking:disabled"/>
<int value="346711293" label="enable-save-password-bubble"/>
<int value="348854923" label="v8-cache-strategies-for-cache-storage"/>
<int value="350399958" label="ModuleScriptsImportMetaUrl:disabled"/>
@@ -27959,6 +28693,7 @@ from previous Chrome versions.
<int value="378994579" label="Previews:enabled"/>
<int value="379326303" label="enable-add-to-shelf"/>
<int value="379428799" label="security-chip-animation"/>
+ <int value="380372760" label="V8Orinoco:disabled"/>
<int value="385969127" label="disable-win32k-lockdown"/>
<int value="387178525" label="VideoFullscreenOrientationLock:enabled"/>
<int value="387233614" label="HomePageButtonForceEnabled:disabled"/>
@@ -28003,6 +28738,7 @@ from previous Chrome versions.
<int value="468959230"
label="enable-non-validating-reload-on-refresh-content"/>
<int value="470011024" label="NonValidatingReloadOnNormalReload:enabled"/>
+ <int value="471969274" label="MediaControlsExpandGesture:enabled"/>
<int value="474743272" label="material-design-ink-drop"/>
<int value="475858648"
label="OverlayScrollbarFlashAfterAnyScrollUpdate:disabled"/>
@@ -28015,6 +28751,7 @@ from previous Chrome versions.
<int value="493903641" label="disable-appcontainer"/>
<int value="494733611" label="disable-drop-sync-credential"/>
<int value="497137719" label="OmniboxVoiceSearchAlwaysVisible:disabled"/>
+ <int value="500177932" label="ArcSmartTextSelection:disabled"/>
<int value="501477022" label="DrawOcclusion:enabled"/>
<int value="503189154" label="ViewsBrowserWindows:disabled"/>
<int value="503245473" label="disable-translate-new-ux"/>
@@ -28039,6 +28776,7 @@ from previous Chrome versions.
<int value="558873715" label="SiteDetails:disabled"/>
<int value="562979188" label="DesktopIOSPromotion:enabled"/>
<int value="564522013" label="Av1Decoder:disabled"/>
+ <int value="565406673" label="EnableVirtualKeyboardMdUi:enabled"/>
<int value="567368307" label="enable-experimental-canvas-features"/>
<int value="575394365" label="AndroidPaymentApps:disabled"/>
<int value="576701073" label="WebPaymentsJustInTimePaymentApp:disabled"/>
@@ -28048,6 +28786,7 @@ from previous Chrome versions.
<int value="582187448" label="DontPrefetchLibraries:enabled"/>
<int value="584541349" label="ContextualSearchSingleActions:disabled"/>
<int value="586021329" label="VibrateRequiresUserGesture:enabled"/>
+ <int value="588333474" label="OfflineIndicator:disabled"/>
<int value="592050831" label="disable-slimming-paint"/>
<int value="593707592" label="disable-network-portal-notification"/>
<int value="595371145" label="OmniboxRichEntitySuggestions:disabled"/>
@@ -28063,6 +28802,7 @@ from previous Chrome versions.
<int value="606512202" label="AutofillCreditCardPopupLayout:enabled"/>
<int value="606834606" label="force-color-profile"/>
<int value="609112512" label="touch-selection-strategy"/>
+ <int value="609580715" label="ArcCupsApi:disabled"/>
<int value="610545308" label="enable-potentially-annoying-security-features"/>
<int value="624317932" label="print-pdf-as-image"/>
<int value="624368375" label="OmniboxEntitySuggestions:enabled"/>
@@ -28073,14 +28813,17 @@ from previous Chrome versions.
<int value="630244477" label="ServiceWorkerPaymentApps:enabled"/>
<int value="630947363" label="touch-events"/>
<int value="632340413" label="network-settings-config"/>
+ <int value="633442161" label="ExperimentalUi:disabled"/>
<int value="634789085" label="LayeredAPI:disabled"/>
<int value="635076832" label="MarkHttpAs:disabled"/>
<int value="635971109" label="PrintPdfAsImage:disabled"/>
+ <int value="636341169" label="ExploreSites:disabled"/>
<int value="636425179" label="mhtml-generator-option"/>
<int value="637396292" label="AllBookmarks:enabled"/>
<int value="637452937" label="ChromeHomeSurvey:enabled"/>
<int value="642037198" label="SoleIntegration:disabled"/>
<int value="643725031" label="disable-touch-feedback"/>
+ <int value="644084236" label="CloseButtonsInactiveTabs:enabled"/>
<int value="644189071" label="PermissionsBlacklist:enabled"/>
<int value="646252875" label="ReadItLaterInMenu:enabled"/>
<int value="646738320" label="disable-gesture-editing"/>
@@ -28089,6 +28832,9 @@ from previous Chrome versions.
<int value="651844675" label="EasyUnlockPromotions:enabled"/>
<int value="652561231" label="CustomContextMenu:enabled"/>
<int value="659086147" label="OverlayScrollbarFlashWhenMouseEnter:enabled"/>
+ <int value="663027937" label="NewTabPageCustomLinks:enabled"/>
+ <int value="664363259" label="SiteCharacteristicsDatabase:enabled"/>
+ <int value="664591021" label="EnableContinueReading:enabled"/>
<int value="665409384"
label="AutofillToolkitViewsCreditCardDialogsMac:enabled"/>
<int value="679931272" label="DcheckIsFatal:enabled"/>
@@ -28129,6 +28875,7 @@ from previous Chrome versions.
<int value="732703958" label="enable-gesture-tap-highlight"/>
<int value="734900932" label="RecurrentInterstitialFeature:enabled"/>
<int value="736911267" label="ExperimentalCrostiniUI:disabled"/>
+ <int value="737421745" label="enable-accessibility-object-model"/>
<int value="738868972" label="GdiTextPrinting:disabled"/>
<int value="745783589" label="translate-force-trigger-on-english"/>
<int value="745868416" label="disable-system-timezone-automatic-detection"/>
@@ -28147,6 +28894,7 @@ from previous Chrome versions.
label="enable-fullscreen-handwriting-virtual-keyboard:enabled"/>
<int value="773743944" label="show-android-files-in-files-app"/>
<int value="773919225" label="disable-office-editing-component-extension"/>
+ <int value="774079453" label="SuggestedTextTouchBar:disabled"/>
<int value="777667507" label="DesktopPWAsLinkCapturing:enabled"/>
<int value="779086132" label="enable-data-reduction-proxy-alt"/>
<int value="779849093" label="OfflinePagesCTSuppressNotifications:disabled"/>
@@ -28171,6 +28919,7 @@ from previous Chrome versions.
<int value="841343322" label="disable-new-korean-ime"/>
<int value="841779535" label="password-export:enabled"/>
<int value="842432903" label="CaptureThumbnailOnNavigatingAway:enabled"/>
+ <int value="842789526" label="CloudPrinterHandler:disabled"/>
<int value="843896452" label="UserActivationV2:enabled"/>
<int value="846951416" label="CopylessPaste:enabled"/>
<int value="848324390" label="enable-lock-screen-apps"/>
@@ -28200,10 +28949,12 @@ from previous Chrome versions.
label="OmniboxUIExperimentElideSuggestionUrlAfterHost:enabled"/>
<int value="908523940" label="PassiveEventListenersDueToFling:disabled"/>
<int value="909439558" label="disable-device-discovery"/>
+ <int value="912119426" label="InfiniteSessionRestore:disabled"/>
<int value="913138924" label="RecurrentInterstitialFeature:disabled"/>
<int value="916316159" label="disable-new-app-list-mixer"/>
<int value="918046854" label="NtlmV2Enabled:disabled"/>
<int value="921536672" label="OfflinePagesDescriptiveFailStatus:enabled"/>
+ <int value="925712999" label="V8Orinoco:enabled"/>
<int value="926852901" label="DataReductionProxyMainMenu:disabled"/>
<int value="929462705" label="disable-link-disambiguation-popup"/>
<int value="935655516" label="password-import-export:disabled"/>
@@ -28214,6 +28965,7 @@ from previous Chrome versions.
<int value="939554480" label="enable-credit-card-scan"/>
<int value="939603162" label="BackgroundLoadingForDownloads:disabled"/>
<int value="941036016" label="ContentSuggestionsSettings:disabled"/>
+ <int value="941883332" label="ProactiveTabFreezeAndDiscard:disabled"/>
<int value="943319566" label="enable-intent-picker"/>
<int value="946688335" label="OmniboxSpareRenderer:disabled"/>
<int value="952558794" label="enable-remote-assistance"/>
@@ -28262,6 +29014,7 @@ from previous Chrome versions.
<int value="1049885154" label="OfflinePagesPrefetching:disabled"/>
<int value="1050048304" label="enable-font-cache-scaling"/>
<int value="1050321458" label="new-profile-management"/>
+ <int value="1050664817" label="CSSFragmentIdentifiers:enabled"/>
<int value="1053743655" label="NewOverviewAnimations:enabled"/>
<int value="1054910800" label="enable-timezone-tracking-option"/>
<int value="1057887829" label="AutofillScanThemeDialog:disabled"/>
@@ -28275,6 +29028,7 @@ from previous Chrome versions.
<int value="1070164693" label="MidiManagerDynamicInstantiation:disabled"/>
<int value="1070300488" label="disable-webgl"/>
<int value="1070449228" label="ContextualSuggestionsCarousel:enabled"/>
+ <int value="1071520357" label="WebAuthenticationTouchId:enabled"/>
<int value="1072010558" label="NTPModernLayout:disabled"/>
<int value="1074359194" label="UseSuggestionsEvenIfFew:enabled"/>
<int value="1075637651" label="disable-tablet-splitview"/>
@@ -28293,12 +29047,14 @@ from previous Chrome versions.
<int value="1105439588" label="enable-swipe-selection"/>
<int value="1107543566" label="enable-one-copy"/>
<int value="1108663108" label="disable-device-discovery-notifications"/>
+ <int value="1112051724" label="DetectingHeavyPages:enabled"/>
<int value="1112885300" label="VizHitTestDrawQuad:disabled"/>
<int value="1113365156" label="tab-management-experiment-type-chive"/>
<int value="1114629582" label="enable-floating-virtual-keyboard"/>
<int value="1115476442" label="PolicyTool:disabled"/>
<int value="1115635149" label="EnableUnifiedMultiDeviceSetup:enabled"/>
<int value="1116593018" label="CaptureThumbnailOnLoadFinished:disabled"/>
+ <int value="1117795262" label="BloatedRendererDetection:disabled"/>
<int value="1118109174" label="enable-launcher-search-provider-api"/>
<int value="1126061778" label="CaptureThumbnailOnLoadFinished:enabled"/>
<int value="1127183523" label="PassiveEventListenersDueToFling:enabled"/>
@@ -28332,14 +29088,17 @@ from previous Chrome versions.
<int value="1190035852" label="MediaRemoting:enabled"/>
<int value="1192302892" label="gesture-typing"/>
<int value="1192913630" label="OfflinePagesBackgroundLoading:disabled"/>
+ <int value="1194496204" label="NewWallpaperPicker:enabled"/>
<int value="1196644408" label="performance-monitor-gathering"/>
<int value="1196834473" label="disable-smart-virtual-keyboard"/>
<int value="1205849612" label="enable-sync-synced-notifications"/>
<int value="1209221384" label="enable-experimental-accessibility-features"/>
<int value="1210343926" label="enable-drop-sync-credential"/>
<int value="1211284676" label="V8NoTurbo:enabled"/>
+ <int value="1214219155" label="gamepad-polling-interval"/>
<int value="1214455758" label="VideoRotateToFullscreen:disabled"/>
<int value="1215531732" label="OmniboxUIExperiments:disabled"/>
+ <int value="1215768255" label="AutofillCreditCardLocalCardMigration:enabled"/>
<int value="1217907443" label="spurious-power-button-keyboard-accel"/>
<int value="1219317631" label="ContextualSuggestionsAboveArticles:disabled"/>
<int value="1219628795" label="PrintScaling:disabled"/>
@@ -28349,7 +29108,11 @@ from previous Chrome versions.
<int value="1220464509" label="enable-first-run-ui-transitions"/>
<int value="1221559505" label="enable-spelling-feedback-field-trial"/>
<int value="1222017136" label="WebRtcUseEchoCanceller3:disabled"/>
+ <int value="1222032915"
+ label="kAutofillRationalizeRepeatedServerPredictions:enabled"/>
<int value="1226624874" label="Mus:disabled"/>
+ <int value="1228115769" label="SiteCharacteristicsDatabase:disabled"/>
+ <int value="1229299518" label="SingleTabMode:disabled"/>
<int value="1235800887" label="V8Ignition:enabled"/>
<int value="1235940786" label="ChromeHomePersistentIph:enabled"/>
<int value="1237297772" label="no-pings"/>
@@ -28359,6 +29122,7 @@ from previous Chrome versions.
<int value="1247293682" label="topchrome-md"/>
<int value="1250071868" label="disable-timezone-tracking-option"/>
<int value="1253698118" label="ash-disable-stable-overview-order"/>
+ <int value="1257482622" label="PageAlmostIdle:enabled"/>
<int value="1257980502" label="disable-accelerated-video-decode"/>
<int value="1260186484" label="spurious-power-button-screen-accel"/>
<int value="1261713150" label="ChromeHomeOptOutSnackbar:disabled"/>
@@ -28399,10 +29163,12 @@ from previous Chrome versions.
<int value="1319725131" label="enable-distance-field-text"/>
<int value="1320201920" label="enable-touchpad-three-finger-click"/>
<int value="1330264457" label="OmniboxUIExperimentVerticalLayout:disabled"/>
+ <int value="1332120969" label="ChromeDuet:disabled"/>
<int value="1333847867" label="NoScriptPreviews:enabled"/>
<int value="1338864675" label="EnableTouchableAppContextMenu:disabled"/>
<int value="1339426771" label="TopSitesFromSiteEngagement:disabled"/>
<int value="1340690624" label="WebPaymentsMethodSectionOrderV2:disabled"/>
+ <int value="1343516821" label="ignore-previews-blocklist"/>
<int value="1344833841" label="ImeThread:enabled"/>
<int value="1351830811" label="do-not-ignore-autocomplete-off"/>
<int value="1352447982" label="enable-lcd-text"/>
@@ -28411,6 +29177,7 @@ from previous Chrome versions.
<int value="1361047396" label="disable-click-delay"/>
<int value="1361073386" label="ContentSuggestionsNotifications:enabled"/>
<int value="1363136936" label="VrCustomTabBrowsing:enabled"/>
+ <int value="1367467733" label="AutoplayIgnoreWebAudio:enabled"/>
<int value="1367529437" label="NTPAssetDownloadSuggestions:enabled"/>
<int value="1367671275" label="enable-proximity-auth-proximity-detection"/>
<int value="1369449914" label="SysInternals:disabled"/>
@@ -28429,7 +29196,9 @@ from previous Chrome versions.
<int value="1386300777"
label="OmniboxUIExperimentHideSuggestionUrlTrivialSubdomains:disabled"/>
<int value="1389729816" label="data-reduction-proxy-lo-fi"/>
+ <int value="1393500952" label="EnableVirtualKeyboardUkm:disabled"/>
<int value="1397069250" label="NetworkService:disabled"/>
+ <int value="1403195370" label="ArcCupsApi:enabled"/>
<int value="1405459667" label="enable-fast-text-autosizing"/>
<int value="1406046556" label="enable-slimming-paint-v175"/>
<int value="1406354320" label="MacViewsWebUIDialogs:enabled"/>
@@ -28439,6 +29208,7 @@ from previous Chrome versions.
<int value="1408331660" label="enhanced-bookmarks-experiment"/>
<int value="1409437197" label="OfflinePagesLimitlessPrefetching:enabled"/>
<int value="1410697724" label="mediadrm-enable-non-compositing"/>
+ <int value="1413158119" label="WebRtcRemoteEventLog:disabled"/>
<int value="1413948819" label="NupPrinting:enabled"/>
<int value="1416592483" label="ash-enable-mirrored-screen"/>
<int value="1418054870" label="SpecialLocale:enabled"/>
@@ -28463,6 +29233,7 @@ from previous Chrome versions.
<int value="1466380480" label="enable-device-discovery-notifications"/>
<int value="1466502102" label="DelayNavigation:disabled"/>
<int value="1469407485" label="disable-accelerated-2d-canvas"/>
+ <int value="1473838479" label="EnableVirtualKeyboardMdUi:disabled"/>
<int value="1474861626" label="disable-multi-mirroring"/>
<int value="1479248574" label="disable-voice-input"/>
<int value="1481562816" label="disable-password-link"/>
@@ -28494,18 +29265,21 @@ from previous Chrome versions.
<int value="1529979182" label="EnablePasswordSelection:enabled"/>
<int value="1530113113" label="disable-pushstate-throttle"/>
<int value="1530177325" label="LanguagesPreference:disabled"/>
- <int value="1533111748" label="Multidevice:enabled"/>
+ <int value="1534222388" label="EnableEphemeralFlashPermission:enabled"/>
<int value="1536921097" label="NavigationMojoResponse:disabled"/>
+ <int value="1538685213" label="DownloadHomeV2:enabled"/>
<int value="1538690515" label="OneGoogleBarOnLocalNtp:enabled"/>
<int value="1541723759" label="ServiceWorkerNavigationPreload:disabled"/>
<int value="1543027970" label="EnableDisplayZoomSetting:disabled"/>
<int value="1544552792" label="InterestFeedContentSuggestions:enabled"/>
<int value="1548776701" label="AllBookmarks:disabled"/>
<int value="1548942246" label="PassiveDocumentEventListeners:disabled"/>
+ <int value="1559034872" label="AutofillPrefilledFields:enabled"/>
<int value="1560188739" label="reader-mode-heuristics"/>
<int value="1563255033" label="memlog-stack-mode"/>
<int value="1567839560"
label="ChromeHomePersonalizedOmniboxSuggestions:disabled"/>
+ <int value="1571998166" label="DetectingHeavyPages:disabled"/>
<int value="1579461102" label="MemoryCoordinator:disabled"/>
<int value="1586022426" label="AutofillCreditCardAssist:enabled"/>
<int value="1589341623" label="disable-easy-unlock"/>
@@ -28521,6 +29295,7 @@ from previous Chrome versions.
<int value="1612446645" label="enable-weak-memorycache"/>
<int value="1612871297" label="WebPayments:disabled"/>
<int value="1612974229" label="allow-insecure-localhost"/>
+ <int value="1614596813" label="CloseButtonsInactiveTabs:disabled"/>
<int value="1615988672" label="GrantNotificationsToDSE:enabled"/>
<int value="1617187093" label="enable-improved-a2hs"/>
<int value="1621298798" label="VrBrowserKeyboard:enabled"/>
@@ -28548,6 +29323,9 @@ from previous Chrome versions.
<int value="1670161209" label="ClickToOpenPDFPlaceholder:enabled"/>
<int value="1670799163" label="ChromeHomeShowGoogleGWhenUrlCleared:enabled"/>
<int value="1673427566" label="ChromeHomeExpandButton:disabled"/>
+ <int value="1677167062" label="AutomaticPasswordGeneration:enabled"/>
+ <int value="1677258310" label="DragAppsInTabletMode:disabled"/>
+ <int value="1679558835" label="ArcAvailableForChildAccount:enabled"/>
<int value="1689123607" label="enable-app-link"/>
<int value="1689183477" label="enable-merge-key-char-events"/>
<int value="1690837904" label="save-previous-document-resources"/>
@@ -28601,6 +29379,7 @@ from previous Chrome versions.
<int value="1803465156" label="enable-zero-suggest-most-visited"/>
<int value="1803470125" label="SyncUSSSessions:enabled"/>
<int value="1809940714" label="SpeculativeLaunchServiceWorker:disabled"/>
+ <int value="1810311887" label="WebAssemblyThreads:enabled"/>
<int value="1812368073" label="enable-new-app-list-mixer"/>
<int value="1814671708" label="disable-password-manager-reauthentication"/>
<int value="1816843861" label="ServiceWorkerServicification:enabled"/>
@@ -28616,6 +29395,7 @@ from previous Chrome versions.
<int value="1830460973" label="disable-network-settings-config"/>
<int value="1831593339" label="stop-in-background:disabled"/>
<int value="1831835753" label="MaterialDesignIncognitoNTP:enabled"/>
+ <int value="1832552562" label="EnableVirtualKeyboardUkm:enabled"/>
<int value="1835523483" label="OmniboxUIExperimentSwapTitleAndUrl:enabled"/>
<int value="1838990777" label="V8Future:enabled"/>
<int value="1839740266" label="LocationHardReload:disabled"/>
@@ -28623,6 +29403,7 @@ from previous Chrome versions.
<int value="1845131710" label="Newblue:enabled"/>
<int value="1847024354" label="enable-hotword-hardware"/>
<int value="1849379463" label="OfflinePagesCTV2:enabled"/>
+ <int value="1849580433" label="disable-oop-rasterization"/>
<int value="1851358497" label="enable-ash-sidebar"/>
<int value="1852630189" label="NTPBookmarkSuggestions:disabled"/>
<int value="1855524566" label="allow-insecure-websocket-from-https-origin"/>
@@ -28662,6 +29443,7 @@ from previous Chrome versions.
<int value="1913298816" label="OverlayScrollbar:enabled"/>
<int value="1913926782" label="ChromeModernAlternateCardLayout:disabled"/>
<int value="1915178511" label="disable-blink-features"/>
+ <int value="1924192543" label="ProactiveTabFreezeAndDiscard:enabled"/>
<int value="1925627218" label="FullscreenToolbarReveal:disabled"/>
<int value="1927259098" label="TranslateLanguageByULP:enabled"/>
<int value="1928407249" label="NewPhotoPicker:enabled"/>
@@ -28680,6 +29462,7 @@ from previous Chrome versions.
<int value="1951466218" label="enable-data-reduction-proxy-lite-page"/>
<int value="1951645673" label="PasswordsKeyboardAccessory:disabled"/>
<int value="1955677113" label="trace-export-events-to-etw"/>
+ <int value="1957273171" label="PageAlmostIdle:disabled"/>
<int value="1957358530" label="ContextualSearchSecondTap:enabled"/>
<int value="1958387645" label="ScanCardsInWebPayments:enabled"/>
<int value="1959148757" label="OffMainThreadFetch:enabled"/>
@@ -28728,8 +29511,12 @@ from previous Chrome versions.
<int value="2063091429" label="OfflinePagesSharing:enabled"/>
<int value="2067634730" label="LsdPermissionPrompt:disabled"/>
<int value="2067735898" label="WebVrAutopresentFromIntent:enabled"/>
+ <int value="2069999572"
+ label="AllowSignedHTTPExchangeCertsWithoutExtension:disabled"/>
+ <int value="2071229145" label="BloatedRendererDetection:enabled"/>
<int value="2071340353" label="progress-bar-completion"/>
<int value="2071461362" label="disable-credit-card-scan"/>
+ <int value="2075207488" label="AutomaticPasswordGeneration:disabled"/>
<int value="2076787478" label="OmniboxDisplayTitleForCurrentUrl:disabled"/>
<int value="2076903744" label="progress-bar-animation"/>
<int value="2077917024"
@@ -28750,12 +29537,14 @@ from previous Chrome versions.
<int value="2101151142" label="disable-direct-write"/>
<int value="2104788328" label="use-winrt-midi-api"/>
<int value="2113804526" label="EnableAppShortcutSearch:enabled"/>
+ <int value="2114843059" label="ContextualSuggestionsOptOut:enabled"/>
<int value="2119964154" label="enable-download-resumption"/>
<int value="2121056855" label="IncreaseInputAudioBufferSize:disabled"/>
<int value="2121550859" label="PreferHtmlOverPlugins:enabled"/>
<int value="2121776031" label="auto-virtual-keyboard"/>
<int value="2122023503" label="enable-win32k-lockdown-mimetypes"/>
<int value="2122876605" label="enable-bleeding-edge-rendering-fast-paths"/>
+ <int value="2123183411" label="BlinkHeapIncrementalMarking:enabled"/>
<int value="2123567684" label="OptimizeLoadingIPCForSmallResources:enabled"/>
<int value="2126203058" label="force-show-update-menu-badge"/>
<int value="2129184006" label="NTPOfflinePageDownloadSuggestions:enabled"/>
@@ -28974,6 +29763,14 @@ from previous Chrome versions.
<int value="2" label="Failed to store DM Token to the device"/>
</enum>
+<enum name="MachineLevelUserCloudPolicyEnrollmentStartupDialog">
+ <int value="0" label="Shown"/>
+ <int value="1" label="ClosedSuccess"/>
+ <int value="2" label="ClosedRelaunch"/>
+ <int value="3" label="ClosedFail"/>
+ <int value="4" label="ClosedAbort"/>
+</enum>
+
<enum name="MacOSBluetoothOperationsResult">
<int value="-2" label="Unknown error domain"/>
<int value="-1" label="No error"/>
@@ -29260,7 +30057,7 @@ Called by update_use_counter_css.py.-->
<int value="161" label="width"/>
<int value="162" label="word-break"/>
<int value="163" label="word-spacing"/>
- <int value="164" label="word-wrap"/>
+ <int value="164" label="alias-word-wrap"/>
<int value="165" label="z-index"/>
<int value="166" label="alias-webkit-animation"/>
<int value="167" label="alias-webkit-animation-delay"/>
@@ -29278,26 +30075,26 @@ Called by update_use_counter_css.py.-->
<int value="179" label="webkit-background-composite"/>
<int value="180" label="alias-webkit-background-origin"/>
<int value="181" label="alias-webkit-background-size"/>
- <int value="182" label="webkit-border-after"/>
- <int value="183" label="webkit-border-after-color"/>
- <int value="184" label="webkit-border-after-style"/>
- <int value="185" label="webkit-border-after-width"/>
- <int value="186" label="webkit-border-before"/>
- <int value="187" label="webkit-border-before-color"/>
- <int value="188" label="webkit-border-before-style"/>
- <int value="189" label="webkit-border-before-width"/>
- <int value="190" label="webkit-border-end"/>
- <int value="191" label="webkit-border-end-color"/>
- <int value="192" label="webkit-border-end-style"/>
- <int value="193" label="webkit-border-end-width"/>
+ <int value="182" label="alias-webkit-border-after"/>
+ <int value="183" label="alias-webkit-border-after-color"/>
+ <int value="184" label="alias-webkit-border-after-style"/>
+ <int value="185" label="alias-webkit-border-after-width"/>
+ <int value="186" label="alias-webkit-border-before"/>
+ <int value="187" label="alias-webkit-border-before-color"/>
+ <int value="188" label="alias-webkit-border-before-style"/>
+ <int value="189" label="alias-webkit-border-before-width"/>
+ <int value="190" label="alias-webkit-border-end"/>
+ <int value="191" label="alias-webkit-border-end-color"/>
+ <int value="192" label="alias-webkit-border-end-style"/>
+ <int value="193" label="alias-webkit-border-end-width"/>
<int value="194" label="webkit-border-fit"/>
<int value="195" label="webkit-border-horizontal-spacing"/>
<int value="196" label="webkit-border-image"/>
<int value="197" label="alias-webkit-border-radius"/>
- <int value="198" label="webkit-border-start"/>
- <int value="199" label="webkit-border-start-color"/>
- <int value="200" label="webkit-border-start-style"/>
- <int value="201" label="webkit-border-start-width"/>
+ <int value="198" label="alias-webkit-border-start"/>
+ <int value="199" label="alias-webkit-border-start-color"/>
+ <int value="200" label="alias-webkit-border-start-style"/>
+ <int value="201" label="alias-webkit-border-start-width"/>
<int value="202" label="webkit-border-vertical-spacing"/>
<int value="203" label="webkit-box-align"/>
<int value="204" label="webkit-box-direction"/>
@@ -29359,17 +30156,17 @@ Called by update_use_counter_css.py.-->
<int value="260" label="webkit-line-clamp"/>
<int value="261" label="webkit-line-grid"/>
<int value="262" label="webkit-line-snap"/>
- <int value="263" label="webkit-logical-width"/>
- <int value="264" label="webkit-logical-height"/>
+ <int value="263" label="alias-webkit-logical-width"/>
+ <int value="264" label="alias-webkit-logical-height"/>
<int value="265" label="webkit-margin-after-collapse"/>
<int value="266" label="webkit-margin-before-collapse"/>
<int value="267" label="webkit-margin-bottom-collapse"/>
<int value="268" label="webkit-margin-top-collapse"/>
<int value="269" label="webkit-margin-collapse"/>
- <int value="270" label="webkit-margin-after"/>
- <int value="271" label="webkit-margin-before"/>
- <int value="272" label="webkit-margin-end"/>
- <int value="273" label="webkit-margin-start"/>
+ <int value="270" label="alias-webkit-margin-after"/>
+ <int value="271" label="alias-webkit-margin-before"/>
+ <int value="272" label="alias-webkit-margin-end"/>
+ <int value="273" label="alias-webkit-margin-start"/>
<int value="274" label="webkit-marquee"/>
<int value="275" label="webkit-marquee-direction"/>
<int value="276" label="webkit-marquee-increment"/>
@@ -29394,16 +30191,16 @@ Called by update_use_counter_css.py.-->
<int value="295" label="webkit-mask-repeat-x"/>
<int value="296" label="webkit-mask-repeat-y"/>
<int value="297" label="webkit-mask-size"/>
- <int value="298" label="webkit-max-logical-width"/>
- <int value="299" label="webkit-max-logical-height"/>
- <int value="300" label="webkit-min-logical-width"/>
- <int value="301" label="webkit-min-logical-height"/>
+ <int value="298" label="alias-webkit-max-logical-width"/>
+ <int value="299" label="alias-webkit-max-logical-height"/>
+ <int value="300" label="alias-webkit-min-logical-width"/>
+ <int value="301" label="alias-webkit-min-logical-height"/>
<int value="302" label="webkit-nbsp-mode"/>
<int value="303" label="order"/>
- <int value="304" label="webkit-padding-after"/>
- <int value="305" label="webkit-padding-before"/>
- <int value="306" label="webkit-padding-end"/>
- <int value="307" label="webkit-padding-start"/>
+ <int value="304" label="alias-webkit-padding-after"/>
+ <int value="305" label="alias-webkit-padding-before"/>
+ <int value="306" label="alias-webkit-padding-end"/>
+ <int value="307" label="alias-webkit-padding-start"/>
<int value="308" label="alias-webkit-perspective"/>
<int value="309" label="alias-webkit-perspective-origin"/>
<int value="310" label="webkit-perspective-origin-x"/>
@@ -29690,6 +30487,49 @@ Called by update_use_counter_css.py.-->
<int value="591" label="row-gap"/>
<int value="592" label="gap"/>
<int value="593" label="viewport-fit"/>
+ <int value="594" label="margin-block-start"/>
+ <int value="595" label="margin-block-end"/>
+ <int value="596" label="margin-inline-start"/>
+ <int value="597" label="margin-inline-end"/>
+ <int value="598" label="padding-block-start"/>
+ <int value="599" label="padding-block-end"/>
+ <int value="600" label="padding-inline-start"/>
+ <int value="601" label="padding-inline-end"/>
+ <int value="602" label="border-block-end-color"/>
+ <int value="603" label="border-block-end-style"/>
+ <int value="604" label="border-block-end-width"/>
+ <int value="605" label="border-block-start-color"/>
+ <int value="606" label="border-block-start-style"/>
+ <int value="607" label="border-block-start-width"/>
+ <int value="608" label="border-inline-end-color"/>
+ <int value="609" label="border-inline-end-style"/>
+ <int value="610" label="border-inline-end-width"/>
+ <int value="611" label="border-inline-start-color"/>
+ <int value="612" label="border-inline-start-style"/>
+ <int value="613" label="border-inline-start-width"/>
+ <int value="614" label="border-block-start"/>
+ <int value="615" label="border-block-end"/>
+ <int value="616" label="border-inline-start"/>
+ <int value="617" label="border-inline-end"/>
+ <int value="618" label="margin-block"/>
+ <int value="619" label="margin-inline"/>
+ <int value="620" label="padding-block"/>
+ <int value="621" label="padding-inline"/>
+ <int value="622" label="border-block-color"/>
+ <int value="623" label="border-block-style"/>
+ <int value="624" label="border-block-width"/>
+ <int value="625" label="border-inline-color"/>
+ <int value="626" label="border-inline-style"/>
+ <int value="627" label="border-inline-width"/>
+ <int value="628" label="border-block"/>
+ <int value="629" label="border-inline"/>
+ <int value="630" label="inset-block-start"/>
+ <int value="631" label="inset-block-end"/>
+ <int value="632" label="inset-block"/>
+ <int value="633" label="inset-inline-start"/>
+ <int value="634" label="inset-inline-end"/>
+ <int value="635" label="inset-inline"/>
+ <int value="636" label="inset"/>
</enum>
<enum name="MappedEditingCommands">
@@ -29865,6 +30705,15 @@ Called by update_use_counter_css.py.-->
<int value="2" label="Non-Secure"/>
</enum>
+<enum name="MashService">
+ <int value="0" label="Ash (window manager)"/>
+ <int value="1" label="Autoclick"/>
+ <int value="2" label="Quick launch"/>
+ <int value="3" label="Shortcut viewer"/>
+ <int value="4" label="Tap visualizer"/>
+ <int value="5" label="Font"/>
+</enum>
+
<enum name="MatchResult">
<int value="0" label="Valid match"/>
<int value="1" label="Invalid match"/>
@@ -30059,6 +30908,13 @@ Called by update_use_counter_css.py.-->
<int value="3" label="Supported with type"/>
</enum>
+<enum name="MediaLauncherActivityMediaType">
+ <int value="0" label="Audio"/>
+ <int value="1" label="Image"/>
+ <int value="2" label="Video"/>
+ <int value="3" label="Unknown"/>
+</enum>
+
<enum name="MediaLoadType">
<int value="0" label="URL"/>
<int value="1" label="MediaSource"/>
@@ -30251,6 +31107,14 @@ Called by update_use_counter_css.py.-->
<int value="7" label="Generic"/>
</enum>
+<enum name="MediaStatus">
+ <int value="-30002" label="AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED"/>
+ <int value="-30001" label="AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE"/>
+ <int value="-10004" label="AMEDIA_ERROR_INVALID_PARAMETER"/>
+ <int value="-10000" label="AMEDIA_ERROR_UNKNOWN"/>
+ <int value="0" label="AMEDIA_OK"/>
+</enum>
+
<enum name="MediaStreamRequestResult">
<int value="0" label="OK"/>
<int value="1" label="Permission Denied"/>
@@ -30785,6 +31649,34 @@ Called by update_use_counter_css.py.-->
<int value="6" label="Open tab switcher"/>
</enum>
+<enum name="MobileStartupIntent">
+ <int value="0" label="Intent to restore Chrome"/>
+ <int value="1" label="Intent for new page load"/>
+</enum>
+
+<enum name="MobileStartupToolbarFirstFocusStartupState">
+ <int value="0" label="Before native initialization complete"/>
+ <int value="1" label="After native initialization complete"/>
+ <int value="2" label="After first meaningful paint"/>
+ <int value="3" label="After first pageload finished"/>
+</enum>
+
+<enum name="ModuleBlacklistCacheReadResult">
+ <int value="0" label="Success"/>
+ <int value="1" label="Failed to open the file"/>
+ <int value="2" label="Failed to read the metadata"/>
+ <int value="3" label="Invalid version"/>
+ <int value="4" label="Failed to read the module entries"/>
+ <int value="5" label="The entries were not sorted"/>
+ <int value="6" label="Failed to read the MD5 digest"/>
+ <int value="7" label="Invalid MD5 digest"/>
+</enum>
+
+<enum name="ModuleBlacklistStatus">
+ <int value="0" label="Newly blacklisted"/>
+ <int value="1" label="Blocked"/>
+</enum>
+
<enum name="ModuleIndex">
<int value="0" label="chrome.dll"/>
<int value="1" label="chrome_elf.dll"/>
@@ -30852,6 +31744,30 @@ Called by update_use_counter_css.py.-->
</int>
</enum>
+<enum name="MountEncryptedEncryptionKeyStatus">
+ <int value="0" label="unknown">Key not loaded yet.</int>
+ <int value="1" label="keyfile">Key loaded from encrypted.key file.</int>
+ <int value="2" label="NeedsFinalization">
+ Key loaded from needs-finalization file.
+ </int>
+ <int value="3" label="Fresh">Freshly generated key.</int>
+</enum>
+
+<enum name="MountEncryptedSystemKeyStatus">
+ <int value="0" label="Unknown">No key loaded yet.</int>
+ <int value="1" label="NVRAMLockbox">Using lockbox salt as system key.</int>
+ <int value="2" label="NVRAMEncstateful">
+ Key in dedicated encstateful NVRAM space.
+ </int>
+ <int value="3" label="FinalizationPending">
+ TPM not ready, obfuscated key on disk.
+ </int>
+ <int value="4" label="Factory">Hard-coded factory key.</int>
+ <int value="5" label="KernelCommandLine">Key from kernel command line.</int>
+ <int value="6" label="ProductUUID">Using product UUID as system key.</int>
+ <int value="7" label="StaticFallback">Using hard-coded fallback key.</int>
+</enum>
+
<enum name="MouseEventFollowedByClick">
<int value="0" label="Missed event before click"/>
<int value="1" label="Caught event before click"/>
@@ -31167,6 +32083,15 @@ Called by update_use_counter_css.py.-->
<int value="10" label="FAILED_TO_FIND_NAMESPACE"/>
</enum>
+<enum name="NativeSmbFileShare_MountResult">
+ <int value="0" label="Succeeded"/>
+ <int value="1" label="Unknown failure"/>
+ <int value="2" label="Authentication failed"/>
+ <int value="3" label="Not found"/>
+ <int value="4" label="Unsupported device"/>
+ <int value="5" label="Mount exists"/>
+</enum>
+
<enum name="NatTypeCounters">
<int value="0" label="Not behind a NAT."/>
<int value="1" label="Behind a NAT of unknown type."/>
@@ -31437,6 +32362,8 @@ Called by update_net_error_codes.py.-->
<int value="175" label="SSL_VERSION_INTERFERENCE"/>
<int value="176" label="NO_BUFFER_SPACE"/>
<int value="177" label="SSL_CLIENT_AUTH_NO_COMMON_ALGORITHMS"/>
+ <int value="178" label="EARLY_DATA_REJECTED"/>
+ <int value="179" label="WRONG_VERSION_ON_EARLY_DATA"/>
<int value="200" label="CERT_COMMON_NAME_INVALID"/>
<int value="201" label="CERT_DATE_INVALID"/>
<int value="202" label="CERT_AUTHORITY_INVALID"/>
@@ -31730,6 +32657,7 @@ Called by update_net_error_codes.py.-->
<int value="11" label="Discarded: report-to not a string"/>
<int value="12" label="Removed (max-age = 0)"/>
<int value="13" label="Set (max-age &gt; 0)"/>
+ <int value="14" label="Discarded: missing remote endpoint"/>
</enum>
<enum name="NetNetworkErrorLoggingRequestOutcome">
@@ -31742,6 +32670,7 @@ Called by update_net_error_codes.py.-->
<int value="6" label="Discarded: unsampled success"/>
<int value="7" label="Discarded: unsampled failure"/>
<int value="8" label="Queued"/>
+ <int value="9" label="Discarded: include_subdomains without DNS error"/>
</enum>
<enum name="NetPreconnectUtilization">
@@ -31812,6 +32741,7 @@ Called by update_net_error_codes.py.-->
<int value="5" label="Failed: network error"/>
<int value="6" label="Succeeded: success"/>
<int value="7" label="Succeeded: remove endpoint"/>
+ <int value="8" label="Failed: CORS preflight check failed"/>
</enum>
<enum name="NetTrustAnchors">
@@ -32803,6 +33733,8 @@ Called by update_net_trust_anchors.py.-->
label="d49c6f289cd056519492480f192f00a6fc7c1862dab2e7b5d8e05f6678fae141"/>
<int value="492"
label="cbad7b1d384849df0946b7ee8e7f5f7ce3aed876fda7bc9d30d8b16f29ff2c53"/>
+ <int value="493"
+ label="e0c780c629903e126f1d919570dce7c496f85f33aae66b9a3147ee75f8d1620a"/>
</enum>
<enum name="Network3GGobiError">
@@ -33400,6 +34332,38 @@ Called by update_net_trust_anchors.py.-->
<int value="4" label="UNREGISTRATION_FAILED"/>
</enum>
+<enum name="NotificationHelperNotificationActivatorPrimaryStatus">
+ <int value="0" label="Success"/>
+ <int value="1" label="Chrome exe missing"/>
+ <int value="2" label="ShellExecute failed"/>
+</enum>
+
+<enum name="NotificationHelperNotificationActivatorSecondaryStatus">
+ <int value="0" label="Success"/>
+ <int value="1" label="LaunchId empty"/>
+ <int value="2" label="AllowSetForegroundWindow failed"/>
+ <int value="3" label="LaunchId empty, AllowSetForegroundWindow failed"/>
+ <int value="4" label="Handle missing"/>
+ <int value="5" label="LaunchId empty, Handle missing"/>
+ <int value="6" label="AllowSetForegroundWindow failed, Handle missing"/>
+ <int value="7"
+ label="LaunchId empty, AllowSetForegroundWindow failed, Handle missing"/>
+</enum>
+
+<enum name="NotificationHelperNotificationActivatorStatus">
+ <obsolete>
+ Deprecated as of 06/2018. Replaced by
+ NotificationHelperNotificationActivatorPrimaryStatus and
+ NotificationHelperNotificationActivatorSecondaryStatus.
+ </obsolete>
+ <int value="0" label="Success"/>
+ <int value="1" label="Chrome exe missing"/>
+ <int value="2" label="ShellExecute failed"/>
+ <int value="3" label="Launch id empty"/>
+ <int value="4" label="AllowSetForegroundWindow call failed"/>
+ <int value="5" label="Chrome process launch failed"/>
+</enum>
+
<enum name="NotifierType">
<int value="0" label="Application"/>
<int value="1" label="Arc++"/>
@@ -33471,6 +34435,54 @@ Called by update_net_trust_anchors.py.-->
<int value="7" label="Transport-layer default"/>
</enum>
+<enum name="NTPBackgroundCustomizationAvailability">
+ <int value="0" label="Background customization available"/>
+ <int value="1" label="Background customization feature unavailable"/>
+ <int value="2" label="Background customization unavailable due to theme"/>
+ <int value="3"
+ label="Background customization unavailable due to search provider"/>
+</enum>
+
+<enum name="NTPCustomizeAction">
+ <int value="0" label="'Chrome backgrounds' menu item clicked."/>
+ <int value="1" label="'Upload an image' menu item clicked."/>
+ <int value="2" label="'Restore default background' menu item clicked."/>
+ <int value="3" label="Attribution link on a customized background clicked."/>
+ <int value="4" label="'Add shortcut' link clicked."/>
+ <int value="5" label="'Edit shortcut' link clicked."/>
+ <int value="6" label="'Restore default shortcuts' menu item clicked."/>
+</enum>
+
+<enum name="NTPCustomizeChromeBackgroundAction">
+ <int value="0"
+ label="Collection selected in the 'Chrome backgrounds' dialog."/>
+ <int value="1" label="Image selected in the 'Chrome backgrounds' dialog."/>
+ <int value="2" label="'Cancel' clicked in the 'Chrome backgrounds' dialog."/>
+ <int value="3"
+ label="Image set as background (through double-click or 'Done')."/>
+</enum>
+
+<enum name="NTPCustomizedFeatures">
+ <int value="0" label="Background customized"/>
+ <int value="1" label="Shortcut customized"/>
+</enum>
+
+<enum name="NTPCustomizeLocalImageBackgroundAction">
+ <int value="0" label="'Cancel' clicked in the 'Upload an image' dialog"/>
+ <int value="1" label="'Done' clicked in the 'Upload an image' dialog"/>
+</enum>
+
+<enum name="NTPCustomizeShortcutAction">
+ <int value="0" label="A custom shortcut was removed."/>
+ <int value="1" label="'Cancel' was clicked in the 'Edit shortcut' dialog."/>
+ <int value="2" label="'Done' was clicked in the 'Edit shortcut' dialog."/>
+ <int value="3" label="A custom shortcut action was undone."/>
+ <int value="4"
+ label="All custom shortcuts were restored (via menu or message pop-up)."/>
+ <int value="5" label="A custom shortcut was added."/>
+ <int value="6" label="A custom shortcut was updated."/>
+</enum>
+
<enum name="NtpFollowAction">
<int value="0" label="PAGE_TRANSITION_LINK"/>
<int value="1" label="PAGE_TRANSITION_TYPED"/>
@@ -33543,6 +34555,13 @@ Called by update_net_trust_anchors.py.-->
<int value="3" label="Interactive request - quota exceeded"/>
</enum>
+<enum name="NTPShortcutCustomizationAvailability">
+ <int value="0" label="Shortcut customization available"/>
+ <int value="1" label="Shortcut customization feature unavailable"/>
+ <int value="2"
+ label="Shortcut customization unavailable due to search provider"/>
+</enum>
+
<enum name="NtpSnippetsFetchResult">
<int value="0" label="Success"/>
<int value="1" label="Empty hosts - deprecated"/>
@@ -33554,6 +34573,7 @@ Called by update_net_trust_anchors.py.-->
<int value="7" label="Out of interactive quota - deprecated"/>
<int value="8" label="Out of non-interactive quota - deprecated"/>
<int value="9" label="No API key available"/>
+ <int value="10" label="Access token invalid"/>
</enum>
<enum name="NTPSnippetsState">
@@ -33664,6 +34684,25 @@ Called by update_net_trust_anchors.py.-->
<int value="2" label="Null"/>
</enum>
+<enum name="NuxGoogleAppsInteractions">
+ <summary>
+ The button that a user pressed when interacting with the Google Apps NUX.
+ </summary>
+ <int value="0" label="Prompt Seen"/>
+ <int value="1" label="No Thanks"/>
+ <int value="2" label="Get Started"/>
+</enum>
+
+<enum name="NuxGoogleAppsSelections">
+ <summary>Google apps that can be added by the NUX.</summary>
+ <int value="0" label="Gmail"/>
+ <int value="1" label="YouTube"/>
+ <int value="2" label="Maps"/>
+ <int value="3" label="Translate"/>
+ <int value="4" label="News"/>
+ <int value="5" label="Chrome Web Store"/>
+</enum>
+
<enum name="OAuth2LoginAccountRevokedMigrationState">
<int value="0" label="Account ID migration not started"/>
<int value="1" label="Account ID migration in progress"/>
@@ -33678,6 +34717,11 @@ Called by update_net_trust_anchors.py.-->
label="Account was not seeded before FireRefreshTokenAvailable"/>
</enum>
+<enum name="OfflineIndicatorCTREvent">
+ <int value="0" label="Displayed"/>
+ <int value="1" label="Clicked"/>
+</enum>
+
<enum name="OfflineItemsStateAtCancel">
<int value="0" label="Downloading"/>
<int value="1" label="Paused"/>
@@ -33873,6 +34917,12 @@ Called by update_net_trust_anchors.py.-->
<int value="4" label="Not found"/>
</enum>
+<enum name="OfflinePagesLastNIsSavingSamePageEnum">
+ <int value="0" label="New page"/>
+ <int value="1" label="Same page, better expected quality"/>
+ <int value="2" label="Same page, same expected quality"/>
+</enum>
+
<enum name="OfflinePagesLoadStatus">
<int value="0" label="Success"/>
<int value="1" label="Store init failed"/>
@@ -33937,6 +34987,20 @@ Called by update_net_trust_anchors.py.-->
</int>
</enum>
+<enum name="OfflinePagesPublishArchiveMoveFileFailureReason">
+ <int value="0" label="Source missing"/>
+ <int value="1" label="Destination missing"/>
+</enum>
+
+<enum name="OfflinePagesPublishSource">
+ <int value="0" label="Published By Offline ID">
+ Reported when the publishing path finds the page by Offline Id
+ </int>
+ <int value="1" label="Published By Guid">
+ Reported when the publishing path finds the page by Guid.
+ </int>
+</enum>
+
<enum name="OfflinePagesRedirectResult">
<obsolete>
Deprecated 2016-08.
@@ -34292,6 +35356,12 @@ Called by update_net_trust_anchors.py.-->
<int value="4" label="auto, enabled in trial"/>
</enum>
+<enum name="OmniboxDocumentSuggestRequests">
+ <int value="1" label="requests sent"/>
+ <int value="2" label="requests invalidated"/>
+ <int value="3" label="(non-invalidated) replies received"/>
+</enum>
+
<enum name="OmniboxEnteredKeywordMode">
<int value="0" label="via tab"/>
<int value="1" label="via space at end"/>
@@ -34302,6 +35372,14 @@ Called by update_net_trust_anchors.py.-->
<int value="6" label="tap gesture on hint view"/>
</enum>
+<enum name="OmniboxFocusReason">
+ <int value="0" label="Omnibox tapped."/>
+ <int value="1" label="Omnibox long-pressed."/>
+ <int value="2" label="NTP omnibox tapped."/>
+ <int value="3" label="NTP omnibox long-pressed (from paste action)."/>
+ <int value="4" label="Accelerator tapped."/>
+</enum>
+
<enum name="OmniboxInputType">
<int value="0" label="invalid"/>
<int value="1" label="unknown"/>
@@ -34368,6 +35446,7 @@ Called by update_net_trust_anchors.py.-->
<int value="1219" label="APP from on-device service"/>
<int value="1220" label="LEGACY_ON_DEVICE from on-device service"/>
<int value="1424" label="CLIPBOARD from Clipboard provider"/>
+ <int value="1627" label="DOCUMENT via DocumentProvider"/>
</enum>
<enum name="OmniboxProviderType">
@@ -34385,6 +35464,8 @@ Called by update_net_trust_anchors.py.-->
<int value="12" label="on device (only used by Android GSA)"/>
<int value="13" label="on device chrome (chrome content provider)"/>
<int value="14" label="clipboard provider"/>
+ <int value="15" label="deprecated: Physical Web"/>
+ <int value="16" label="DocumentProvider"/>
</enum>
<enum name="OmniboxSearchEngine">
@@ -34546,11 +35627,33 @@ Called by update_net_trust_anchors.py.-->
<int value="3" label="(non-invalidated) replies received"/>
</enum>
+<enum name="OomInterventionBrowserMonitorStatus">
+ <int value="0" label="Enabled with a valid config"/>
+ <int value="1" label="Disabled since bad config param"/>
+ <int value="2" label="Enabled on device with no swap"/>
+</enum>
+
+<enum name="OomInterventionRendererStatus">
+ <int value="0" label="Detection only enabled on renderer"/>
+ <int value="1" label="Detection with trigger enabled on renderer"/>
+ <int value="2" label="Disabled since renderer cannot fetch memory total"/>
+</enum>
+
<enum name="OomInterventionUserDecision">
<int value="0" label="Declined"/>
<int value="1" label="Accepted"/>
</enum>
+<enum name="OopRasterGlyphCacheMissType">
+ <int value="0"
+ label="Missing font metrics, indicating an incorrect SkDescriptor"/>
+ <int value="1" label="Missing glyph metrics"/>
+ <int value="2" label="Missing glyph image"/>
+ <int value="3" label="Missing glyph path"/>
+ <int value="4" label="Missing glyph image, but a fallback was found"/>
+ <int value="5" label="Missing glyph path, but a fallback was found"/>
+</enum>
+
<enum name="OpenFileSystemResult">
<int value="0" label="OK."/>
<int value="1" label="In incognito mode."/>
@@ -34576,6 +35679,28 @@ Called by update_net_trust_anchors.py.-->
<int value="3" label="FailedInvalidConfiguration"/>
</enum>
+<enum name="OptOutBlacklistReason">
+ <int value="0" label="Not loaded">
+ The Blacklist was not loaded from disk when the page load committed and
+ prevented the page capping InfoBar.
+ </int>
+ <int value="1" label="Session policy">
+ The per-session policy prevented showing the page capping InfoBar.
+ </int>
+ <int value="2" label="Persistent policy">
+ The general persistent policy prevented showing the page capping InfoBar.
+ </int>
+ <int value="3" label="Host policy">
+ The per-host policy prevented showing the page capping InfoBar.
+ </int>
+ <int value="4" label="Type policy">
+ The per-type policy prevented showing the page capping InfoBar.
+ </int>
+ <int value="5" label="Allowed">
+ The page capping InfoBar was allowed to be shown.
+ </int>
+</enum>
+
<enum name="OriginTrialEnableResult">
<obsolete>
Obsolete as of M54 and replaced by OriginTrialTokenStatus.
@@ -34932,6 +36057,20 @@ Called by update_net_trust_anchors.py.-->
</int>
</enum>
+<enum name="PageLifecycleStateTransition">
+ <int value="0" label="Active to hidden and foregrounded"/>
+ <int value="1" label="Active to hidden and backgrounded"/>
+ <int value="2" label="Hidden and foregrounded to visible"/>
+ <int value="3" label="Hidden and foregrounded to hidden and backgrounded"/>
+ <int value="4" label="Hidden and foregrounded to frozen"/>
+ <int value="5" label="Hidden and backgrounded to visible"/>
+ <int value="6" label="Hidden and backgrounded to hidden and foregrounded"/>
+ <int value="7" label="Hidden and backgrounded to frozen"/>
+ <int value="8" label="Frozen to visible"/>
+ <int value="9" label="Frozen to hidden and foregrounded"/>
+ <int value="10" label="Frozen to hidden and backgrounded"/>
+</enum>
+
<enum name="PageLoadEvent">
<obsolete>
Deprecated in favor of {Committed|Provisional|InternalError}LoadEvent
@@ -34976,6 +36115,11 @@ Called by update_net_trust_anchors.py.-->
<int value="17" label="Invalid order - first meaningful paint / interactive"/>
<int value="18" label="First input delay without first input timestamp"/>
<int value="19" label="First input timestamp without first input delay"/>
+ <int value="20" label="Longest input delay without longest input timestamp"/>
+ <int value="21" label="Longest input timestamp without longest input delay"/>
+ <int value="22"
+ label="Longest input timestamp earlier than first input timestamp"/>
+ <int value="23" label="Longest input delay less than first input delay"/>
</enum>
<enum name="PageScaleFactorRange">
@@ -35139,6 +36283,14 @@ Called by update_net_trust_anchors.py.-->
<int value="8" label="Unknown"/>
</enum>
+<enum name="PageWhitelistingInitiatorCheck">
+ <int value="0" label="Initiator absent"/>
+ <int value="1" label="Neither candidate matches initiator"/>
+ <int value="2" label="Committed candidate matches initiator"/>
+ <int value="3" label="Pending candidate matches initiator"/>
+ <int value="4" label="Both candidates match initiator"/>
+</enum>
+
<enum name="PaletteModeCancelType">
<int value="0" label="Palette laser pointer mode is cancelled."/>
<int value="1" label="Palette laser pointer mode is switched out of"/>
@@ -35182,6 +36334,12 @@ Called by update_net_trust_anchors.py.-->
<int value="1" label="Parent Frame Known"/>
</enum>
+<enum name="ParkingAction">
+ <int value="0" label="Parked in Background"/>
+ <int value="1" label="Unparked in Background"/>
+ <int value="2" label="Unparked in Foreground"/>
+</enum>
+
<enum name="ParsedCookieStatus">
<obsolete>
Deprecated as of 9/2013. Experiment to measure control characters in cookies
@@ -36156,6 +37314,7 @@ Called by update_net_trust_anchors.py.-->
<int value="17" label="URL matched enterprise login URL"/>
<int value="18" label="Password Alert mode: no need to send ping"/>
<int value="19" label="Turned off by enterprise admin"/>
+ <int value="20" label="SafeBrowsing disabled"/>
</enum>
<enum name="PasswordProtectionSyncAccountType">
@@ -36179,6 +37338,22 @@ Called by update_net_trust_anchors.py.-->
<int value="4" label="Mark as legitimate"/>
</enum>
+<enum name="PasswordRequirementsFetcherResult">
+ <int value="0" label="Found no spec for current origin"/>
+ <int value="1" label="Found a spec for current origin"/>
+ <int value="2" label="Invalid origin">
+ The origin is an IP address, not HTTP/HTTPS, or not a valid URL.
+ </int>
+ <int value="3" label="Failed to fetch requirements file">
+ Server responded with an empty document or an error code.
+ </int>
+ <int value="4" label="Timeout">Server timed out.</int>
+ <int value="5" label="Failed to parse response">
+ Server responded with a document but it could not be parsed.
+ </int>
+ <int value="6" label="No URL Loader">No URL loader configured.</int>
+</enum>
+
<enum name="PasswordReusePasswordFieldDetected">
<int value="0" label="No password field"/>
<int value="1" label="Has password field"/>
@@ -37143,6 +38318,7 @@ Called by update_net_trust_anchors.py.-->
<int value="3" label="Mouse click to dismiss"/>
<int value="4" label="Touch to dismiss"/>
<int value="5" label="Lock screen"/>
+ <int value="6" label="Feedback"/>
</enum>
<enum name="PowerButtonPressType">
@@ -37179,6 +38355,26 @@ Called by update_net_trust_anchors.py.-->
<int value="4" label="More than two ports exist"/>
</enum>
+<enum name="PowerMLPreviousEventLoggingResult">
+ <int value="0" label="Success">Previous event was logged successfully.</int>
+ <int value="1" label="Error">Previous event was not logged successfully.</int>
+ <int value="2" label="ErrorModelPredictionMissing">
+ Previous event was not logged successfully because model was enabled but
+ there was no prediction for the previous event.
+ </int>
+ <int value="3" label="ErrorModelDisabled">
+ Previous event was not logged successfully because model was disabled.
+ </int>
+ <int value="4" label="ErrorMultiplePreviousEvents">
+ Previous event was not logged successfully because of multiple previous
+ events.
+ </int>
+ <int value="5" label="ErrorIdleStartMissing">
+ Previous event was not logged successfully because previous idle event had
+ no event start time.
+ </int>
+</enum>
+
<enum name="PowerSupplyType">
<summary>
The type of power supply connected to a Chrome OS system, as reported by the
@@ -37768,6 +38964,7 @@ Called by update_net_trust_anchors.py.-->
<int value="4" label="AMP Redirection"/>
<int value="5" label="NoScript"/>
<int value="6" label="Unspecified"/>
+ <int value="7" label="ResourceLoadingHints"/>
</enum>
<enum name="PreviewsUserOptedOut">
@@ -39239,6 +40436,13 @@ Called by update_net_trust_anchors.py.-->
<int value="5" label="NOTIFY_FACTORY_OF_SESSION_CLOSED"/>
</enum>
+<enum name="QuicWriteStatus">
+ <int value="0" label="WRITE_STATUS_OK"/>
+ <int value="1" label="WRITE_STATUS_BLOCKED"/>
+ <int value="2" label="WRITE_STATUS_ERROR"/>
+ <int value="3" label="WRITE_STATUS_MSG_TOO_BIG"/>
+</enum>
+
<enum name="QuotaOriginTypes">
<int value="0" label="Other"/>
<int value="1" label="None"/>
@@ -39328,6 +40532,12 @@ Called by update_net_trust_anchors.py.-->
<int value="1" label="Increment"/>
</enum>
+<enum name="RefreshTrigger">
+ <int value="0" label="NTP shown"/>
+ <int value="1" label="Foregrounded"/>
+ <int value="2" label="Fixed timer"/>
+</enum>
+
<enum name="RelaunchNotificationShowResult">
<int value="0" label="Shown"/>
<int value="1" label="Not shown for unknown reason"/>
@@ -39376,6 +40586,7 @@ Called by update_net_trust_anchors.py.-->
<int value="11" label="Failed to extract pid from lock file path"/>
<int value="12" label="Invalid lock file"/>
<int value="13" label="Orphaned lock file"/>
+ <int value="14" label="User refused to terminate process"/>
</enum>
<enum name="RemotingStartTrigger">
@@ -39541,6 +40752,8 @@ Called by update_net_trust_anchors.py.-->
<int value="44" label="InternalIntersectionObserver"/>
<int value="45" label="CompositorThreadTaskQueueDefault"/>
<int value="46" label="WorkerThreadTaskQueueDefault"/>
+ <int value="47" label="WorkerThreadTaskQueueV8"/>
+ <int value="48" label="WorkerThreadTaskQueueCompositor"/>
</enum>
<enum name="RendererSchedulerTaskUseCase">
@@ -39562,6 +40775,14 @@ Called by update_net_trust_anchors.py.-->
<int value="5" label="AnimationWorkletThread"/>
<int value="6" label="ServiceWorkerThread"/>
<int value="7" label="AudioWorkletThread"/>
+ <int value="8" label="FileThread"/>
+ <int value="9" label="DatabaseThread"/>
+ <int value="10" label="WebAudioThread"/>
+ <int value="11" label="ScriptStreamerThread"/>
+ <int value="12" label="OfflineAudioRenderThread"/>
+ <int value="13" label="ReverbConvolutionBackgroundThread"/>
+ <int value="14" label="HRTFDatabaseLoaderThread"/>
+ <int value="15" label="TestThread"/>
</enum>
<enum name="RendererType">
@@ -39839,6 +41060,16 @@ Called by update_net_trust_anchors.py.-->
<int value="4" label="SET_AUTH_CREDENTIALS"/>
</enum>
+<enum name="RequestBehavior">
+ <int value="0" label="Unknown"/>
+ <int value="1" label="Request with wait"/>
+ <int value="2" label="Request with content"/>
+ <int value="3" label="Request with timeout"/>
+ <int value="4" label="No request with wait"/>
+ <int value="5" label="No request with content"/>
+ <int value="6" label="No request with timeout"/>
+</enum>
+
<enum name="RequestedImageMimeType">
<int value="0" label="Png"/>
<int value="1" label="Jpeg"/>
@@ -40044,6 +41275,13 @@ Called by update_net_trust_anchors.py.-->
<int value="1" label="Cached StyleSheetContents was reused"/>
</enum>
+<enum name="ReusedPasswordType">
+ <int value="0" label="Saved password"/>
+ <int value="1" label="Sync password"/>
+ <int value="2" label="Other Gaia password"/>
+ <int value="3" label="Enterprise password"/>
+</enum>
+
<enum name="ReusePendingOrCommittedSiteEnum">
<int value="0" label="Had to create a new RenderProcessHost"/>
<int value="1" label="Could reuse an existing RenderProcessHost"/>
@@ -40086,6 +41324,13 @@ Called by update_net_trust_anchors.py.-->
<int value="1" label="Kill (He's dead, Jim!)"/>
</enum>
+<enum name="SafeBrowsingActivationPosition">
+ <int value="0" label="Only URL in redirect chain"/>
+ <int value="1" label="First URL in redirect chain"/>
+ <int value="2" label="Any middle URL in redirect chain"/>
+ <int value="3" label="Last redirect in URL chain"/>
+</enum>
+
<enum name="SafeBrowsingAppOptIn">
<int value="0" label="No opt-in preference in manifest"/>
<int value="1" label="Explicit opt-in via manifest"/>
@@ -40818,6 +42063,15 @@ Called by update_net_trust_anchors.py.-->
<int value="306" label="SHTML"/>
<int value="307" label="SHTM"/>
<int value="308" label="SHT"/>
+ <int value="309" label="SLK"/>
+ <int value="310" label="APPLESCRIPT"/>
+ <int value="311" label="SCPT"/>
+ <int value="312" label="SCPTD"/>
+ <int value="313" label="SEPLUGIN"/>
+ <int value="314" label="OSAS"/>
+ <int value="315" label="OSAX"/>
+ <int value="316" label="SETTINGCONTENT-MS"/>
+ <int value="317" label="OXT"/>
</enum>
<enum name="SBClientDownloadIsSignedBinary">
@@ -40939,6 +42193,16 @@ Called by update_net_trust_anchors.py.-->
<int value="9" label="Rollback: SBER2 absent so SBER1 must be cleared"/>
</enum>
+<enum name="ScriptSchedulingType">
+ <int value="0" label="NotSet"/>
+ <int value="1" label="Defer"/>
+ <int value="2" label="ParserBlocking"/>
+ <int value="3" label="ParserBlockingInline"/>
+ <int value="4" label="InOrder"/>
+ <int value="5" label="Async"/>
+ <int value="6" label="Immediate"/>
+</enum>
+
<enum name="ScrollAnchorRestorationStatus">
<int value="0" label="SUCCESS"/>
<int value="1" label="FAILED_NO_MATCHES"/>
@@ -41165,6 +42429,12 @@ Called by update_net_trust_anchors.py.-->
<int value="4" label="Received Answer - Too Large"/>
</enum>
+<enum name="SearchBoxActivationSource">
+ <int value="0" label="Mouse Press"/>
+ <int value="1" label="Key Press"/>
+ <int value="2" label="Gesture Tap"/>
+</enum>
+
<enum name="SearchEngine">
<obsolete>
Deprecated 8/2013. No longer generated.
@@ -41479,6 +42749,7 @@ Called by update_net_trust_anchors.py.-->
<int value="14" label="RedirectedResponseForNotFollowRequest"/>
<int value="15" label="DataPipeCreationFailed (insufficient resources)"/>
<int value="16" label="ResponseTypeCORSForRequestModeSameOrigin"/>
+ <int value="17" label="CouldNotCheckIsBodyUsed"/>
</enum>
<enum name="ServiceWorkerSite">
@@ -41549,16 +42820,16 @@ Called by update_net_trust_anchors.py.-->
<int value="6" label="REQUEST_JOB_ERROR_BAD_BLOB"/>
<int value="7" label="REQUEST_JOB_ERROR_NO_PROVIDER_HOST"/>
<int value="8" label="REQUEST_JOB_ERROR_NO_ACTIVE_VERSION"/>
- <int value="9" label="REQUEST_JOB_ERROR_NO_REQUEST"/>
+ <int value="9" label="REQUEST_JOB_ERROR_NO_REQUEST (deprecated)"/>
<int value="10" label="REQUEST_JOB_ERROR_FETCH_EVENT_DISPATCH"/>
<int value="11" label="REQUEST_JOB_ERROR_BLOB_READ"/>
<int value="12" label="REQUEST_JOB_ERROR_STREAM_ABORTED"/>
<int value="13" label="REQUEST_JOB_ERROR_KILLED"/>
<int value="14" label="REQUEST_JOB_ERROR_KILLED_WITH_BLOB"/>
<int value="15" label="REQUEST_JOB_ERROR_KILLED_WITH_STREAM"/>
- <int value="16" label="REQUEST_JOB_ERROR_DESTROYED"/>
- <int value="17" label="REQUEST_JOB_ERROR_DESTROYED_WITH_BLOB"/>
- <int value="18" label="REQUEST_JOB_ERROR_DESTROYED_WITH_STREAM"/>
+ <int value="16" label="REQUEST_JOB_ERROR_DESTROYED (deprecated)"/>
+ <int value="17" label="REQUEST_JOB_ERROR_DESTROYED_WITH_BLOB (deprecated)"/>
+ <int value="18" label="REQUEST_JOB_ERROR_DESTROYED_WITH_STREAM (deprecated)"/>
<int value="19" label="REQUEST_JOB_ERROR_BAD_DELEGATE"/>
<int value="20" label="REQUEST_JOB_ERROR_REQUEST_BODY_BLOB_FAILED"/>
</enum>
@@ -41928,6 +43199,17 @@ Called by update_net_trust_anchors.py.-->
<int value="19" label="SCHEME_FILESYSTEM"/>
</enum>
+<enum name="ShouldShowPromptResults">
+ <summary>
+ The results of the new and the old algorithm for detecting whether to show a
+ password prompt for the user.
+ </summary>
+ <int value="0" label="Old no, new no"/>
+ <int value="1" label="Old no, new yes"/>
+ <int value="2" label="Old yes, new no"/>
+ <int value="3" label="Old yes, new yes"/>
+</enum>
+
<enum name="ShowAllSavedPasswordsContext">
<int value="0" label="None"/>
<int value="1" label="Under password suggestions"/>
@@ -41935,6 +43217,15 @@ Called by update_net_trust_anchors.py.-->
<int value="3" label="Context menu"/>
</enum>
+<enum name="ShowTabSwitcherSnapshotResult">
+ <int value="0" label="Snapshot not attempted, page is still loading">
+ Snapshot was not attempted because the page is still loading and would
+ result in a stale snapshot.
+ </int>
+ <int value="1" label="Snapshot was attempted, but the snapshot failed."/>
+ <int value="2" label="Snapshot was successfully taken."/>
+</enum>
+
<enum name="ShutdownReason">
<summary>
The reason that the Chrome OS power manager shut down or rebooted the
@@ -42266,6 +43557,9 @@ Called by update_net_trust_anchors.py.-->
</enum>
<enum name="SimpleCacheHeaderSizeChange">
+ <obsolete>
+ Removed 2018-06-05
+ </obsolete>
<int value="0" label="Written for the first time"/>
<int value="1" label="Rewritten with same size"/>
<int value="2" label="Rewritten with larger size"/>
@@ -42510,6 +43804,7 @@ Called by update_net_trust_anchors.py.-->
<int value="22" label="CHROME_HOME_OPT_OUT_SURVEY"/>
<int value="23" label="SNIPPET_FETCH_NO_NEW_SUGGESTIONS"/>
<int value="24" label="MISSING_FILES_NO_SD_CARD"/>
+ <int value="25" label="OFFLINE_INDICATOR"/>
</enum>
<enum name="SnippetOpenMethod">
@@ -42846,6 +44141,8 @@ Called by update_net_trust_anchors.py.-->
<int value="16" label="VARY_MISMATCH"/>
<int value="17" label="ACCEPTED_NO_VARY"/>
<int value="18" label="ACCEPTED_MATCHING_VARY"/>
+ <int value="19" label="PUSH_DISABLED"/>
+ <int value="20" label="ALREADY_IN_CACHE"/>
</enum>
<enum name="SpdySessionGet">
@@ -43950,6 +45247,9 @@ Called by update_net_trust_anchors.py.-->
</enum>
<enum name="SubresourceFilterActions">
+ <obsolete>
+ Deprecated July 2018 in favor of SubresourceFilterActions2
+ </obsolete>
<int value="0" label="New Navigation"/>
<int value="1" label="UI Shown"/>
<int value="2" label="Details shown"/>
@@ -43969,6 +45269,15 @@ Called by update_net_trust_anchors.py.-->
<int value="14" label="Blocked popup (Strong Popup Blocker) (Deprecated)"/>
</enum>
+<enum name="SubresourceFilterActions2">
+ <int value="0" label="UI Shown"/>
+ <int value="1" label="UI suppressed (Smart Logic)"/>
+ <int value="2" label="Details shown"/>
+ <int value="3" label="Learn more clicked"/>
+ <int value="4" label="Whitelisted site via UI"/>
+ <int value="5" label="Forced filtering toggled on via devtools"/>
+</enum>
+
<enum name="SubresourceFilterActivationDecision">
<int value="0" label="Unknown"/>
<int value="1" label="Activated"/>
@@ -43976,6 +45285,7 @@ Called by update_net_trust_anchors.py.-->
<int value="3" label="Unsupported scheme (deprecated)"/>
<int value="4" label="URL whitelisted"/>
<int value="5" label="Activation conditions not met"/>
+ <int value="6" label="Forced activation (e.g. devtools toggle)"/>
</enum>
<enum name="SubresourceFilterActivationState">
@@ -44622,6 +45932,8 @@ would be helpful to identify which type is being sent.
<int value="37" label="Printers"/>
<int value="38" label="Reading List"/>
<int value="39" label="User Events"/>
+ <int value="40" label="Mountain Shares"/>
+ <int value="41" label="User Consents"/>
</enum>
<enum name="SyncModelTypeStoreInitResult">
@@ -44676,6 +45988,7 @@ would be helpful to identify which type is being sent.
<int value="1" label="Saved in the content area"/>
<int value="2" label="Cleared on Chrome sign-out"/>
<int value="3" label="Changed in the content area"/>
+ <int value="4" label="Not sync password hash change event"/>
</enum>
<enum name="SyncPromoAction">
@@ -44722,7 +46035,11 @@ would be helpful to identify which type is being sent.
</enum>
<enum name="SyncStopSource">
- <int value="0" label="Profile destruction"/>
+ <int value="0" label="DEPRECATED 2018-06 Profile destruction">
+ Supposedly meant that Sync was stopped due to the profile being destroyed.
+ However, it was recorded during most profile destructions, even if Sync was
+ never enabled in the first place. We stopped recording this in 2018-06.
+ </int>
<int value="1" label="Sign out"/>
<int value="2" label="Birthday error"/>
<int value="3" label="Chrome sync settings"/>
@@ -45056,6 +46373,22 @@ would be helpful to identify which type is being sent.
<int value="1" label="Native Speech"/>
</enum>
+<enum name="TextToSpeechVoiceIdHashes">
+ <int value="-2140886774" label="patts: Chrome OS UK English"/>
+ <int value="-1258442847" label="patts: Chrome OS Nederlands"/>
+ <int value="-1065336279" label="patts: Chrome OS espanol"/>
+ <int value="-1000148973" label="patts: Chrome OS Deutsch"/>
+ <int value="-691354709" label="patts: Chrome OS portugues do Brasil"/>
+ <int value="6716838" label="patts: Chrome OS Hindi"/>
+ <int value="130099200" label="patts: Chrome OS Bahasa Indonesia"/>
+ <int value="437696625" label="patts: Chrome OS Korean"/>
+ <int value="992554727" label="patts: Chrome OS French"/>
+ <int value="1016507512" label="patts: Chrome OS espanol de Estados Unidos"/>
+ <int value="1208419825" label="patts: Chrome OS US English"/>
+ <int value="1417057269" label="patts: Chrome OS italiano"/>
+ <int value="1835109015" label="patts: Chrome OS Indian English"/>
+</enum>
+
<enum name="ThreadType">
<int value="0" label="UI"/>
<int value="1" label="Blocking"/>
@@ -45781,6 +47114,7 @@ Full version information for the fingerprint enum values:
<int value="27" label="kSettingsResetPromptLastTriggeredForStartupUrls"/>
<int value="28" label="kSettingsResetPromptLastTriggeredForHomepage"/>
<int value="29" label="kMediaStorageIdSalt"/>
+ <int value="30" label="kModuleBlacklistCacheMD5Digest"/>
</enum>
<enum name="TranslateBubbleUiEvent">
@@ -45882,6 +47216,8 @@ Full version information for the fingerprint enum values:
<int value="14" label="Aborted by too often denied rule"/>
<int value="15" label="Aborted by matches previous language"/>
<int value="16" label="Decision made to create infobar on Android"/>
+ <int value="17" label="Show omnibar icon to the user"/>
+ <int value="18" label="Suppress infobar but show omnibar icon"/>
</enum>
<enum name="TranslateLanguage">
@@ -46020,6 +47356,7 @@ Full version information for the fingerprint enum values:
<int value="14" label="Disabled by initialized, connected, passphrase"/>
<int value="15"
label="Disabled by history, initialized, connected, passphrase"/>
+ <int value="16" label="Disabled by URL-keyed anonymized data collection"/>
</enum>
<enum name="UmaCleanExitConsistency">
@@ -46067,6 +47404,33 @@ Full version information for the fingerprint enum values:
<int value="7" label="kNoStore"/>
</enum>
+<enum name="UnifiedConsentBumpAction">
+ <int value="0" label="Opt into Unified Consent was clicked"/>
+ <int value="1" label="More options: Opt into Unified Consent was selected"/>
+ <int value="2" label="More options: Review settings was selected"/>
+ <int value="3" label="More options: Make no changes was selected"/>
+ <int value="4" label="Abort: The user made no action"/>
+</enum>
+
+<enum name="UnifiedConsentBumpSuppressReason">
+ <int value="0" label="None (consent bump was shown)"/>
+ <int value="1" label="User wasn't signed in"/>
+ <int value="2" label="User wasn't syncing everything"/>
+ <int value="3" label="On-by-default privacy setting was off"/>
+ <int value="4" label="User opted into Unity in settings"/>
+ <int value="5" label="User signed out"/>
+ <int value="6" label="Sync was paused"/>
+</enum>
+
+<enum name="UnifiedConsentSyncAndGoogleServicesSettings">
+ <int value="0" label="None of the services are enabled"/>
+ <int value="1" label="'Sync and all Google services' is enabled"/>
+ <int value="2" label="'Activity and interactions' is enabled"/>
+ <int value="3" label="'Make searches and browsing better' is enabled"/>
+ <int value="4" label="'Safe browsing extended reporting' is enabled"/>
+ <int value="5" label="'Enhanced spell check' is enabled"/>
+</enum>
+
<enum name="UniformityTrialGroupNotActive">
<int value="0" label="Invalid"/>
<int value="1" label="Group not reported"/>
@@ -46106,6 +47470,17 @@ Full version information for the fingerprint enum values:
<int value="8" label="IMY"/>
</enum>
+<enum name="UpdateClientErrors">
+ <int value="0" label="(No Error)"/>
+ <int value="1" label="Update in progress"/>
+ <int value="2" label="Update canceled"/>
+ <int value="3" label="Retry later"/>
+ <int value="4" label="Service error"/>
+ <int value="5" label="Update-check error"/>
+ <int value="6" label="CRX not found"/>
+ <int value="7" label="Invalid argument"/>
+</enum>
+
<enum name="UpdateEngineAttemptResult">
<int value="0" label="Update Succeeded"/>
<int value="1" label="Internal Error"/>
@@ -46652,6 +48027,7 @@ Full version information for the fingerprint enum values:
<int value="9" label="Synced Notifications"/>
<int value="10" label="WiFi Credentials"/>
<int value="11" label="Reading List"/>
+ <int value="12" label="User Events"/>
</enum>
<enum name="UserType">
@@ -46672,6 +48048,51 @@ Full version information for the fingerprint enum values:
<int value="2" label="Child user changed type to regular"/>
</enum>
+<enum name="UtilityProcessNameHash">
+ <summary>
+ The hash of a utility process name generated using metrics::HashName. Update
+ these using sheet available at http://bit.ly/2sKxPdR.
+ </summary>
+ <int value="-2115497279" label="network"/>
+ <int value="-2071993701" label="shape_detection"/>
+ <int value="-2061353184" label="content_gpu"/>
+ <int value="-2006071118" label="tracing"/>
+ <int value="-1913809341" label="chrome_printing"/>
+ <int value="-1866379343" label="service_manager"/>
+ <int value="-1656677225" label="file"/>
+ <int value="-1632474908" label="viz"/>
+ <int value="-1615505903" label="media_gallery_util"/>
+ <int value="-1450594275" label="identity"/>
+ <int value="-1307090589" label="ui"/>
+ <int value="-1289115149" label="device"/>
+ <int value="-1015990949" label="proxy_resolver"/>
+ <int value="-988537037" label="video_capture"/>
+ <int value="-725144915" label="local_state"/>
+ <int value="-461949820" label="heap_profiling"/>
+ <int value="-407184831" label="catalog"/>
+ <int value="-400619253" label="mus_demo"/>
+ <int value="-254080081" label="cdm"/>
+ <int value="-2816355" label="profile_import"/>
+ <int value="69152809" label="font_service"/>
+ <int value="357224138" label="user_id"/>
+ <int value="498331100" label="preferences"/>
+ <int value="573935755" label="removable_storage_writer"/>
+ <int value="685091421" label="unzip_service"/>
+ <int value="692677280" label="audio"/>
+ <int value="737685379" label="file_util"/>
+ <int value="862971321" label="data_decoder"/>
+ <int value="882338710" label="metrics"/>
+ <int value="1051118555" label="resource_coordinator"/>
+ <int value="1395049324" label="patch_service"/>
+ <int value="1484328260" label="autoclick_app"/>
+ <int value="1803540096" label="tap_visualizer_app"/>
+ <int value="1937572987" label="shortcut_viewer_app"/>
+ <int value="1967189975" label="util_win"/>
+ <int value="1968783712" label="quick_launch_app"/>
+ <int value="1998508722" label="echo"/>
+ <int value="2077967579" label="pdf_compositor"/>
+</enum>
+
<enum name="V8CacheBehaviour">
<int value="0" label="kProduceCodeCache">
The compilation produced a code cache
@@ -47073,7 +48494,9 @@ Full version information for the fingerprint enum values:
<int value="21" label="DolbyVision profile5"/>
<int value="22" label="DolbyVision profile7"/>
<int value="23" label="Theora"/>
- <int value="24" label="AV1 Profile0"/>
+ <int value="24" label="AV1 Profile Main"/>
+ <int value="25" label="AV1 Profile High"/>
+ <int value="26" label="AV1 Profile Pro"/>
</enum>
<enum name="VideoDecodeAcceleratorError">
@@ -47320,6 +48743,10 @@ Full version information for the fingerprint enum values:
<int value="66" label=".gslides"/>
</enum>
+<enum name="ViewsTextServicesContextMenu">
+ <int value="0" label="EMOJI"/>
+</enum>
+
<enum name="VirtualKeyboardContainerType">
<int value="0" label="FULL_WIDTH"/>
<int value="1" label="FLOATING"/>
@@ -47607,6 +49034,7 @@ Full version information for the fingerprint enum values:
<int value="12" label="SSL client certificate selector was suppressed in VR"/>
<int value="13"
label="Media router presentation request dialog was suppressed in VR"/>
+ <int value="14" label="Context menu was suppressed in VR"/>
</enum>
<enum name="VRUnsupportedMode">
@@ -47619,6 +49047,8 @@ Full version information for the fingerprint enum values:
<int value="6" label="The keyboard version is out-of-date"/>
<int value="7" label="The default search engine wasn't selected"/>
<int value="8" label="Unhandled ConnectionInfo"/>
+ <int value="9" label="Unhandled certificate info"/>
+ <int value="10" label="Unhandled connection security info"/>
</enum>
<enum name="VRViewerType">
@@ -47773,6 +49203,7 @@ Full version information for the fingerprint enum values:
<int value="5" label="Policy"/>
<int value="6" label="Third party"/>
<int value="7" label="Device policy"/>
+ <int value="8" label="One-shot"/>
</enum>
<enum name="WarmupStateOnLaunch">
@@ -47945,10 +49376,18 @@ Full version information for the fingerprint enum values:
<enum name="WebAudioAutoplayStatus">
<int value="0" label="The AudioContext failed to autoplay"/>
- <int value="1" label="Failed to autoplay but start() called on user gesture"/>
+ <int value="1"
+ label="(Deprecated) Failed to autoplay but start() called on user
+ gesture"/>
<int value="2" label="The AudioContext successfully autoplayed"/>
</enum>
+<enum name="WebAudioAutoplayUnlockType">
+ <int value="0" label="AudioContext construction"/>
+ <int value="1" label="AudioContext resume()"/>
+ <int value="2" label="Source Node start()"/>
+</enum>
+
<enum name="WebBluetoothConnectGATTOutcome">
<int value="0" label="Success"/>
<int value="1" label="Device no longer in range"/>
@@ -48223,6 +49662,16 @@ Full version information for the fingerprint enum values:
<int value="4" label="Other"/>
</enum>
+<enum name="WebRtcPeerConnectionUsagePattern">
+ <summary>
+ These values are integers representing a set of flags indicating how the
+ PeerConnection is used. For flag values, see header file
+ webrtc/pc/peerconnection.h, enum class UsageEvent. Only interesting values
+ are called out with labels.
+ </summary>
+ <int value="0" label="Unused and unclosed"/>
+</enum>
+
<enum name="WebRtcVideoCodecs">
<int value="0" label="Unknown"/>
<int value="1" label="VP8"/>
@@ -48363,6 +49812,7 @@ Full version information for the fingerprint enum values:
<int value="-1820397898" label="/manageAccessibility"/>
<int value="-1737559358" label="/flash"/>
<int value="-1688600161" label="/manageProfile"/>
+ <int value="-1569772500" label="/manageAccessibility/tts"/>
<int value="-1351149930" label="/backgroundSync"/>
<int value="-1312744606" label="/knownNetworks"/>
<int value="-1297176639" label="/fonts"/>
@@ -48441,49 +49891,72 @@ Full version information for the fingerprint enum values:
<enum name="WebUIUrlHashes">
<int value="-2103246641" label="chrome://signin-internals/"/>
<int value="-2034706497" label="chrome://net-internals/"/>
+ <int value="-2031269077" label="chrome://signin-error/"/>
+ <int value="-2025866230" label="chrome://usb-internals/"/>
+ <int value="-2024468885" label="chrome://ntp-tiles-internals/"/>
+ <int value="-1977692791" label="chrome://crash/"/>
<int value="-1911971715" label="chrome://history/"/>
<int value="-1887206190" label="chrome://nfc-debug/"/>
+ <int value="-1825876526" label="chrome://delayeduithreadhang/"/>
<int value="-1808179141" label="chrome://password-manager-internals/"/>
+ <int value="-1777503123" label="chrome://thumb2/"/>
<int value="-1743341803" label="chrome://bookmarks/"/>
<int value="-1729122580" label="chrome://chrome-urls/"/>
+ <int value="-1704400468" label="chrome://quit/"/>
<int value="-1700864659" label="chrome://slow/"/>
<int value="-1697077152" label="chrome://device-log/"/>
<int value="-1690355375" label="chrome://mobilesetup/"/>
<int value="-1681544613" label="chrome://print/"/>
<int value="-1647734092" label="chrome://net-export/"/>
+ <int value="-1638649228" label="chrome://webapks/"/>
<int value="-1591890659" label="chrome://syncfs-internals/"/>
<int value="-1493822642" label="chrome://invalidations/"/>
+ <int value="-1475777739" label="chrome://physical-web-diagnostics/"/>
<int value="-1440785181" label="chrome://profile-signin-confirmation/"/>
+ <int value="-1423026122" label="chrome://md-user-manager/"/>
<int value="-1398642514" label="chrome://gesture/"/>
<int value="-1382906531" label="chrome://managed-user-passphrase/"/>
<int value="-1379571130" label="chrome://newtab/"/>
<int value="-1378421581" label="chrome://media-router/"/>
<int value="-1313432739" label="chrome://plugins/"/>
+ <int value="-1239015343" label="chrome://kill/"/>
+ <int value="-1224398205" label="chrome://prefs-internals/"/>
<int value="-1169621742" label="chrome://linux-proxy-config/"/>
+ <int value="-1137946367" label="chrome://webrt-logs/"/>
<int value="-1108319739" label="chrome://sync-internals/"/>
<int value="-1082746738" label="chrome://credits/"/>
<int value="-1078583150" label="chrome://view-cert-dialog/"/>
+ <int value="-1043041749" label="chrome://offline-internals/"/>
<int value="-986409800" label="chrome://identity-internals/"/>
<int value="-969979971" label="chrome://sandbox/"/>
<int value="-946383082" label="chrome://translate-internals/"/>
<int value="-936786926" label="chrome://settings/"/>
+ <int value="-907485548" label="chrome://policy-tool/"/>
+ <int value="-905972126" label="chrome://signin-email-confirmation/"/>
<int value="-902637811" label="chrome://appcache-internals/"/>
+ <int value="-892484505" label="chrome://sys-internals/"/>
<int value="-891260101" label="chrome://inspect/"/>
<int value="-853789543" label="chrome://bluetooth-pairing/"/>
<int value="-823585847" label="chrome://chrome-signin/"/>
<int value="-756514973" label="chrome://version/"/>
<int value="-753390931" label="chrome://interstitials/"/>
+ <int value="-734627230" label="chrome://extension-icon/"/>
<int value="-727952446" label="chrome://nacl/"/>
<int value="-707542503" label="chrome://choose-mobile-network/"/>
<int value="-672072143" label="chrome://site-engagement/"/>
<int value="-661305899" label="chrome://set-time/"/>
<int value="-644310325" label="chrome://os-credits/"/>
+ <int value="-631384656" label="chrome://assistant-optin/"/>
<int value="-624584089"
label="chrome-extension://eemcgdkfndhakfknompkggombfjjjeno/ (Bookmark
Manager)"/>
<int value="-606058756" label="chrome://accessibility/"/>
+ <int value="-566908909" label="chrome://suggestions/"/>
+ <int value="-528306235" label="chrome://sync/"/>
<int value="-516792794" label="chrome://downloads/"/>
<int value="-512782085" label="chrome://salsa/"/>
+ <int value="-511253776" label="chrome://snippets-internals/"/>
+ <int value="-485494550" label="chrome://interventions-internals/"/>
<int value="-451371558" label="chrome://serviceworker-internals/"/>
<int value="-377028639" label="chrome://copresence/"/>
<int value="-359703631" label="chrome://slow_trace/"/>
@@ -48492,11 +49965,18 @@ Full version information for the fingerprint enum values:
<int value="-176639700" label="chrome://omnibox/"/>
<int value="-106823253" label="chrome://conflicts/"/>
<int value="-90956977" label="chrome://dns/"/>
+ <int value="-89853739" label="chrome://thumbnails/"/>
+ <int value="-88246682" label="chrome://uithreadhang/"/>
+ <int value="-68100096" label="chrome://welcome-win10/"/>
<int value="-42737706" label="chrome://extensions-frame/"/>
<int value="-2353438" label="chrome://sim-unlock/"/>
<int value="1377205" label="chrome://history-frame/"/>
+ <int value="9727114" label="chrome://favicon/"/>
+ <int value="14651785" label="chrome://download-internals/"/>
<int value="34035361" label="chrome://apps/"/>
<int value="43923599" label="chrome://tracing/"/>
+ <int value="47779771" label="chrome://media-router-internals/"/>
+ <int value="48333657" label="chrome://about/"/>
<int value="58807865" label="chrome://local-state/"/>
<int value="112165789" label="chrome://device-emulator/"/>
<int value="114748825" label="chrome-devtools://devtools/"/>
@@ -48504,29 +49984,45 @@ Full version information for the fingerprint enum values:
<int value="171659041" label="chrome://webrtc-device-provider/"/>
<int value="253258497" label="chrome://components/"/>
<int value="260253931" label="chrome://devices/"/>
+ <int value="275260142" label="chrome://eoc-internals/"/>
<int value="325375649" label="chrome://settings-frame/"/>
<int value="361621847" label="chrome://make-metro/"/>
+ <int value="461287992" label="chrome://help/"/>
+ <int value="520299179" label="chrome://media-engagement/"/>
<int value="554090510" label="chrome://first-run/"/>
<int value="581234974" label="chrome://tcmalloc/"/>
+ <int value="607659257" label="chrome://cast/"/>
<int value="646837226" label="chrome://crashes/"/>
<int value="659389881" label="chrome://gpu/"/>
<int value="689991895" label="chrome://supervised-user-internals/"/>
<int value="742272091" label="chrome://extensions/"/>
+ <int value="754315733" label="chrome://theme/"/>
<int value="784140714" label="chrome://predictors/"/>
<int value="812624791" label="chrome://dom-distiller/"/>
+ <int value="821023334" label="chrome://screenlock-icon/"/>
+ <int value="894368493" label="chrome://internet-config-dialog/"/>
+ <int value="911597664" label="chrome://multidevice-setup/"/>
<int value="918960088" label="chrome://instant/"/>
<int value="943766809" label="chrome://view-cert/"/>
<int value="977219287" label="chrome://memory/"/>
<int value="985294599" label="chrome://webrtc-logs/"/>
<int value="1055519744" label="chrome://webrtc-internals/"/>
+ <int value="1066907868" label="chrome://physical-web/"/>
<int value="1109407387" label="chrome://keyboardoverlay/"/>
+ <int value="1131405887" label="chrome://taskscheduler-internals/"/>
+ <int value="1148733422" label="chrome://restart/"/>
<int value="1211642987" label="chrome://voicesearch/"/>
<int value="1213428635" label="chrome://memory-redirect/"/>
+ <int value="1214710734" label="chrome://welcome/"/>
+ <int value="1221097359" label="chrome://constrained-test/"/>
<int value="1281801197" label="chrome://terms/"/>
+ <int value="1286620182" label="chrome://reset-password/"/>
+ <int value="1306215264" label="chrome://activationmessage/"/>
<int value="1340926535" label="chrome://network/"/>
<int value="1354146226" label="chrome://tab-modal-confirm-dialog/"/>
<int value="1371905827" label="chrome://flags/"/>
<int value="1396129399" label="chrome://flash/"/>
+ <int value="1399992914" label="chrome://java-crash/"/>
<int value="1403605293" label="chrome://internet-detail-dialog/"/>
<int value="1427179406" label="chrome://gcm-internals/"/>
<int value="1454088830" label="chrome://uber-frame/"/>
@@ -48534,7 +50030,9 @@ Full version information for the fingerprint enum values:
<int value="1463418339" label="chrome://proximity-auth/"/>
<int value="1466599095" label="chrome://oobe/"/>
<int value="1467342679" label="chrome://memory-internals/"/>
+ <int value="1476643520" label="chrome://internet-detail-dialog/"/>
<int value="1540230808" label="chrome://power/"/>
+ <int value="1554928128" label="chrome://sync-confirmation/?consent-bump"/>
<int value="1568301017" label="chrome://media-internals/"/>
<int value="1585293659" label="chrome://system/"/>
<int value="1603463396" label="chrome://help-frame/"/>
@@ -48542,15 +50040,18 @@ Full version information for the fingerprint enum values:
<int value="1628875649" label="chrome://quota-internals/"/>
<int value="1631369147" label="chrome://domain-reliability-internals/"/>
<int value="1662453825" label="chrome://indexeddb-internals/"/>
+ <int value="1677735296" label="chrome://sync-confirmation/"/>
<int value="1687272877" label="chrome://syncresources/"/>
<int value="1725906496" label="chrome://imageburner/"/>
<int value="1765337366" label="chrome://certificate-manager/"/>
+ <int value="1776179126" label="chrome://thumb/"/>
<int value="1797107942" label="chrome://md-settings/"/>
<int value="1887784693" label="chrome://policy/"/>
<int value="1926101309" label="chrome://cryptohome/"/>
<int value="1961263039" label="chrome://profiler/"/>
<int value="1975618905" label="chrome://app-list/"/>
<int value="2040878656" label="chrome://bluetooth-internals/"/>
+ <int value="2052019697" label="chrome://userimage/"/>
<int value="2114840772" label="chrome://drive-internals/"/>
<int value="3251925547" label="chrome://offline-internals/"/>
</enum>
@@ -48786,6 +50287,7 @@ Full version information for the fingerprint enum values:
<int value="29" label="chrome::RESULT_CODE_SXS_MIGRATION_FAILED"/>
<int value="30" label="chrome::RESULT_CODE_ACTION_DISALLOWED_BY_POLICY"/>
<int value="31" label="chrome::RESULT_CODE_INVALID_SANDBOX_STATE"/>
+ <int value="32" label="chrome::RESULT_CODE_CLOUD_POLICY_ENROLLMENT_FAILED"/>
<int value="259" label="0x103 - STILL_ACTIVE."/>
<int value="85436397" label="0x517a7ed - Crashpad simulated exception"/>
<int value="1073807364" label="0x40010004 - DBG_TERMINATE_PROCESS"/>
@@ -48904,12 +50406,46 @@ Full version information for the fingerprint enum values:
</enum>
<enum name="WindowsNotificationSetReadyCallbackStatus">
+ <obsolete>
+ Removed from code May 2018. Replaced with
+ WindowsNotificationSetReadyCallbackStatus2.
+ </obsolete>
<int value="0" label="SUCCESS"/>
<int value="1" label="COM_NOT_INITIALIZED"/>
<int value="2" label="COM_SERVER_MISCONFIGURATION"/>
<int value="3" label="SHORTCUT_MISCONFIGURATION"/>
</enum>
+<enum name="WindowsNotificationSetReadyCallbackStatus2">
+ <int value="0" label="Success"/>
+ <int value="1" label="Misconfig - Shortcut"/>
+ <int value="2" label="Misconfig - ComServer"/>
+ <int value="3" label="Misconfig - Shortcut and ComServer"/>
+ <int value="4" label="Misconfig - ComInitialization"/>
+ <int value="5" label="Misconfig - Shortcut and ComInitialization"/>
+ <int value="6" label="Misconfig - ComServer and ComInitialization"/>
+ <int value="7"
+ label="Misconfig - Shortcut and ComServer and ComInitialization"/>
+</enum>
+
+<enum name="WindowsNotificationStartMenuShortcutStatus">
+ <int value="0" label="Success"/>
+ <int value="1" label="Get shortcut path failed"/>
+ <int value="2" label="Shortcut missing"/>
+ <int value="3" label="Toast activator CLSID incorrect"/>
+</enum>
+
+<enum name="WindowsNotificationStartMenuShortStatus">
+ <obsolete>
+ Deprecated 06/2018. Replaced with WindowsNotificationStartMenuShortcutStatus
+ where typo is fixed.
+ </obsolete>
+ <int value="0" label="Success"/>
+ <int value="1" label="Get shortcut path failed"/>
+ <int value="2" label="Shortcut missing"/>
+ <int value="3" label="Toast activator CLSID incorrect"/>
+</enum>
+
<enum name="WindowsNotificationUserManagerShowupStatus">
<obsolete>
Deprecated 05/2018 as this is no longer needed.
diff --git a/chromium/tools/metrics/histograms/histograms.xml b/chromium/tools/metrics/histograms/histograms.xml
index 4ae2094b23c..033f900cd45 100644
--- a/chromium/tools/metrics/histograms/histograms.xml
+++ b/chromium/tools/metrics/histograms/histograms.xml
@@ -95,6 +95,22 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Accessibility.CrosDictation" enum="BooleanEnabled">
+ <owner>zhelfins@chromium.org</owner>
+ <owner>dtseng@chromium.org</owner>
+ <summary>
+ Whether the ChromeOS dictation feature is enabled (checked once 45 secs
+ after startup).
+ </summary>
+</histogram>
+
+<histogram name="Accessibility.CrosDictation.ToggleDictationMethod"
+ enum="CrosDictationToggleDictationMethod">
+ <owner>zhelfins@chromium.org</owner>
+ <owner>dtseng@chromium.org</owner>
+ <summary>Records how users invoke Dictation.</summary>
+</histogram>
+
<histogram name="Accessibility.CrosFocusHighlight" enum="BooleanEnabled">
<owner>dmazzoni@chromium.org</owner>
<summary>
@@ -244,6 +260,17 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Accessibility.iOS.NewLargerTextCategory" enum="BooleanHit">
+ <owner>mrsuyi@chromium.org</owner>
+ <summary>
+ When a web page reloads or user changes text size category in Settings,
+ FontSizeTabHelper gets the category and maps it to a scaling number. This is
+ hit if the category is not listed in the map defined in
+ /ios/chrome/browser/web/font_size_tab_helper.mm. In that case, we should
+ update the code by adding an entry for the new category in that map.
+ </summary>
+</histogram>
+
<histogram name="Accessibility.Mac.DifferentiateWithoutColor"
enum="BooleanEnabled">
<owner>ellyjones@chromium.org</owner>
@@ -300,6 +327,15 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Accessibility.OOBEStartupSoundDelay" units="ms">
+ <owner>lpalmaro@chromium.org</owner>
+ <owner>alemate@chromium.org</owner>
+ <summary>
+ Delay between login_prompt_visible and Chrome OS OOBE startup sound
+ playback. Depends on sound subsystem initialization time.
+ </summary>
+</histogram>
+
<histogram name="Accessibility.State" enum="BooleanEnabled">
<obsolete>
Deprecated 12/2016 in Issue 672205 with the addition of
@@ -550,6 +586,155 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Ads.Features.AdResourceIsIsolated" enum="AdIsolatedInfo">
+ <owner>csharrison@chromium.org</owner>
+ <owner>jkarlin@chromium.org</owner>
+ <summary>
+ For a given ad request, logs information related to whether it is isolated
+ from the top-level context. Logged per ad subresource request.
+ </summary>
+</histogram>
+
+<histogram name="Ads.Features.ResourceIsSecure" enum="AdSecureInfo">
+ <owner>csharrison@chromium.org</owner>
+ <owner>jkarlin@chromium.org</owner>
+ <summary>
+ For a given request, logs information related to whether it is marked as an
+ ad, and whether it is secure (e.g. https). Logged per subresource request.
+ </summary>
+</histogram>
+
+<histogram name="AnchorElementMetrics.Clicked.ContainsImage" enum="Boolean">
+ <owner>chelu@chromium.org</owner>
+ <summary>
+ True if the anchor element contains an image element, false if it is not.
+ This histogram is recorded when the anchor element is clicked.
+ </summary>
+</histogram>
+
+<histogram name="AnchorElementMetrics.Clicked.HrefEngagementScore"
+ units="score">
+ <obsolete>
+ Deprecated 07/2018. Replaced with
+ AnchorElementMetrics.Clicked.HrefEngagementScore2.
+ </obsolete>
+ <owner>chelu@chromium.org</owner>
+ <summary>
+ The target link (href) engagement score of an anchor element. The score is
+ retrived from the site engagement service. Currently all scores reported are
+ set to 0. This will soon change. This histogram is recorded when the anchor
+ element is clicked.
+ </summary>
+</histogram>
+
+<histogram name="AnchorElementMetrics.Clicked.HrefEngagementScore2"
+ units="score">
+ <owner>chelu@chromium.org</owner>
+ <summary>
+ The site engagement score of the target link (href) of an anchor element.
+ The score is retrived from the site engagement service. This histogram is
+ recorded when the anchor element is clicked.
+ </summary>
+</histogram>
+
+<histogram name="AnchorElementMetrics.Clicked.HrefEngagementScorePositive"
+ units="score">
+ <owner>chelu@chromium.org</owner>
+ <summary>
+ The site engagement score of the target link (href) of an anchor element.
+ The score is retrived from the site engagement service. This histogram is
+ recorded when the anchor element is clicked, and the score is larger than 0.
+ </summary>
+</histogram>
+
+<histogram name="AnchorElementMetrics.Clicked.IsInIFrame" enum="Boolean">
+ <owner>chelu@chromium.org</owner>
+ <summary>
+ True if the anchor element is within an iframe, false if it is not. This
+ histogram is recorded when the anchor element is clicked.
+ </summary>
+</histogram>
+
+<histogram name="AnchorElementMetrics.Clicked.IsSameHost" enum="Boolean">
+ <owner>chelu@chromium.org</owner>
+ <summary>
+ True if the target link of the anchor element has the same host as the root
+ document. This histogram is recorded when the anchor element is clicked.
+ </summary>
+</histogram>
+
+<histogram name="AnchorElementMetrics.Clicked.IsUrlIncrementedByOne"
+ enum="Boolean">
+ <owner>chelu@chromium.org</owner>
+ <summary>
+ True if the target URL of the anchor element and the URL of the root
+ document only differ by one number, and the number in the target URL equals
+ the number in the the URL of the root document plus one. This histogram is
+ recorded when the anchor element is clicked.
+ </summary>
+</histogram>
+
+<histogram name="AnchorElementMetrics.Clicked.RatioArea" units="%">
+ <owner>chelu@chromium.org</owner>
+ <summary>
+ The ratio times 100 between the clickable region area of an anchor element,
+ and the viewport area. This histogram is recorded when the anchor element is
+ clicked.
+ </summary>
+</histogram>
+
+<histogram name="AnchorElementMetrics.Clicked.RatioDistanceCenterToVisibleTop"
+ units="%">
+ <owner>chelu@chromium.org</owner>
+ <summary>
+ The ratio times 100 between the distance from the center of the clickable
+ region of an anchor element to the top edge of the visible region, and the
+ viewport height. This histogram is recorded when the anchor element is
+ clicked.
+ </summary>
+</histogram>
+
+<histogram name="AnchorElementMetrics.Clicked.RatioDistanceRootBottom"
+ units="%">
+ <owner>chelu@chromium.org</owner>
+ <summary>
+ The ratio times 100 between the distance from the bottom of the clickable
+ region of an anchor element to the bottom edge of the root frame, and the
+ viewport height. This histogram is recorded when the anchor element is
+ clicked.
+ </summary>
+</histogram>
+
+<histogram name="AnchorElementMetrics.Clicked.RatioDistanceRootTop" units="%">
+ <owner>chelu@chromium.org</owner>
+ <summary>
+ The ratio times 100 between the distance from the top of the clickable
+ region of an anchor element to the top edge of the root frame, and the
+ viewport height. This histogram is recorded when the anchor element is
+ clicked.
+ </summary>
+</histogram>
+
+<histogram name="AnchorElementMetrics.Clicked.RatioDistanceTopToVisibleTop"
+ units="%">
+ <owner>chelu@chromium.org</owner>
+ <summary>
+ The ratio times 100 between the distance from the top of the clickable
+ region of an anchor element to the top edge of the visible region, and the
+ viewport height. This histogram is recorded when the anchor element is
+ clicked.
+ </summary>
+</histogram>
+
+<histogram name="AnchorElementMetrics.Clicked.RatioVisibleArea" units="%">
+ <owner>chelu@chromium.org</owner>
+ <summary>
+ The ratio times 100 between the visible clickable region area of an anchor
+ element, and the viewport area. This histogram is recorded when the anchor
+ element is clicked.
+ </summary>
+</histogram>
+
<histogram name="Android.Activity.ChromeTabbedActivity.StopReason"
enum="AndroidActivityStopReason">
<owner>dfalcantara@chromium.org</owner>
@@ -653,6 +838,26 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Android.ChromeBrowserProvider.CallerHasPermission"
+ enum="ClientAppId">
+ <owner>yfriedman@chromium.org</owner>
+ <summary>
+ Android: Count of requests to Chrome browser which are granted to other apps
+ to read/write user's bookmarks and history. Only records cases when the app
+ has permission according to Android's permission manager.
+ </summary>
+</histogram>
+
+<histogram name="Android.ChromeBrowserProvider.SignaturePassed"
+ enum="ClientAppId">
+ <owner>yfriedman@chromium.org</owner>
+ <summary>
+ Android: Count of requests to Chrome browser which are granted to other apps
+ to read/write user's bookmarks and history. Only records cases where the app
+ is a system app or signed by Google.
+ </summary>
+</histogram>
+
<histogram name="Android.ChromeHome.DurationOpen" units="ms">
<owner>mdjones@chromium.org</owner>
<owner>twellington@chromium.org</owner>
@@ -1210,6 +1415,9 @@ uploading your change for review.
</histogram>
<histogram name="Android.InstantApps.ApiCallDuration2" units="ms">
+ <obsolete>
+ Not being recorded as of 2017.
+ </obsolete>
<owner>mariakhomenko@chromium.org</owner>
<summary>
Measures the amount of time spent in the getInstantAppIntent() API call.
@@ -1217,23 +1425,28 @@ uploading your change for review.
</histogram>
<histogram name="Android.InstantApps.ApiCallDurationWithApp" units="ms">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
<summary>
Measures the amount of time spent in the getInstantAppIntent() API call when
- the API was able to find an Instant App for the URL.
+ the API was able to find an Instant App for the URL. This is recorded for
+ external intents coming into Chrome only and measures the delay before we
+ dispatch the intent to Instant Apps.
</summary>
</histogram>
<histogram name="Android.InstantApps.ApiCallDurationWithoutApp" units="ms">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
<summary>
Measures the amount of time spent in the getInstantAppIntent() API call when
- the API was not able to find an Instant App for the URL.
+ the API was not able to find an Instant App for the URL. This is recorded
+ for external intents coming into Chrome that get checked for their Instant
+ Apps eligibility, but end up being loaded in Chrome. It's critical to keep
+ this latency low for our startup performance.
</summary>
</histogram>
<histogram name="Android.InstantApps.CallSource" enum="InstantAppsCallSource">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
<summary>
For intents to load a web page in browser from Instant Apps, records where
the request to load came from.
@@ -1242,32 +1455,45 @@ uploading your change for review.
<histogram name="Android.InstantApps.DirectInstantAppsIntent"
enum="DirectIntentType">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
<summary>
Records events that occur when a user clicks on an intent:// URL that is
- dispatched to instant apps.
+ dispatched to instant apps. The intent:// URLs to the Instant Apps are
+ explicitly disabled unless they are launched from Google SERP, but we record
+ other attempts as well.
+ </summary>
+</histogram>
+
+<histogram name="Android.InstantApps.EligiblePageLoaded" enum="Boolean">
+ <owner>thildebr@chromium.org</owner>
+ <summary>
+ Records whether any given successful page load (for http and https schemes
+ only) could have been handled by an Instant App.
</summary>
</histogram>
<histogram name="Android.InstantApps.FallbackDuration" units="ms">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
<summary>
Measures the time from when we first received an eligible intent for Instant
- Apps to the time we processed it in the case where the Instant Apps
- activity had to invoke a fallback intent.
+ Apps to the time we processed it in the case where the Instant Apps activity
+ had to invoke a fallback intent. This happens only on Android N and older.
</summary>
</histogram>
<histogram name="Android.InstantApps.HandleIntentDuration" units="ms">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
<summary>
Measures the amount of time spent triaging an incoming event to decide
- whether it needs to be routed to Instant Apps.
+ whether it needs to be routed to Instant Apps. This is time from
+ ChromeLauncherActivity.onCreate() call to the time either startActivity() is
+ called or the request proceeds. This is a superset of
+ Android.InstantApps.ApiCallDurationWith[out]App.
</summary>
</histogram>
<histogram name="Android.InstantApps.ShouldShowBanner" enum="InstantAppsBanner">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
<summary>
Logs the reasons the banner is shown or hidden on an instant apps eligible
pages. Triggered every time asynchronous Instant Apps API indicates the
@@ -1276,6 +1502,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Android.Intent.LaunchExternalAppFormSubmitHasUserGesture"
+ enum="Boolean" expires_after="M71">
+ <owner>tedchoc@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
+ <summary>
+ When an external application was launched as a result of a form submit, this
+ tracks whether there was a user gesture associated with the submit.
+ </summary>
+</histogram>
+
<histogram name="Android.IsLastSharedAppInfoRetrieved"
enum="BooleanIsLastSharedAppInfoRetrieved">
<owner>jaekyun@chromium.org</owner>
@@ -1341,9 +1577,11 @@ uploading your change for review.
The duration of each failed ActivityManager.getMyMemoryState() call made by
MemoryPressureMonitor.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -1354,9 +1592,11 @@ uploading your change for review.
The duration of each successful ActivityManager.getMyMemoryState() call made
by MemoryPressureMonitor.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -1488,7 +1728,7 @@ uploading your change for review.
</histogram>
<histogram name="Android.Omnibox.InvalidMatch" enum="MatchResult">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>tedchoc@chromium.org</owner>
<summary>
Recorded every time AutocompleteController.java interacts with
autocomplete_controller_android.cc via an index reference to an item.
@@ -1497,15 +1737,22 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Android.OmniboxFocusReason" enum="OmniboxFocusReason">
+ <owner>mdjones@chromium.org</owner>
+ <owner>twellington@chromium.org</owner>
+ <owner>amaralp@chromium.org</owner>
+ <summary>Records how the omnibox was focused.</summary>
+</histogram>
+
<histogram name="Android.PackageStats.CacheSize" units="MB">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>nyquist@chromium.org</owner>
<summary>
Records the size of the user's cache at startup on Android O and above.
</summary>
</histogram>
<histogram name="Android.PackageStats.CodeSize" units="MB">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>nyquist@chromium.org</owner>
<summary>
At startup, records the space on disk taken by Chrome application including
APK resources, compiled libraries, and extracted native code. Only recorded
@@ -1514,7 +1761,7 @@ uploading your change for review.
</histogram>
<histogram name="Android.PackageStats.DataSize" units="MB">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>nyquist@chromium.org</owner>
<summary>
Records the size of the user's data directory at startup on Android O and
above. Does not include cache size.
@@ -1920,7 +2167,7 @@ uploading your change for review.
</histogram>
<histogram name="Android.SysUtilsLowEndMatches" enum="BooleanEqual">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
Measures whether Chrome low-end detection logic based on RAM size matches
the Android system utility value for isLowRamDevice(). This is recorded once
@@ -1931,7 +2178,7 @@ uploading your change for review.
<histogram name="Android.TabNavigationInterceptResult"
enum="NavigationInterceptResult">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>thildebr@chromium.org</owner>
<summary>
The distribution of results when running ExternalNavigationHandler, this
shows how often we send intents to be handled by other applications.
@@ -1981,6 +2228,15 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Android.WebView.LoadUrl.DataUriHasOctothorpe" enum="Boolean">
+ <owner>smcgruer@chromium.org</owner>
+ <summary>
+ Records if a data url passed to loadUrl had a '#' character. This is to be
+ used in the effort to deprecate the incorrect treatment of '#' characters in
+ data URIs; see http://crbug.com/823666#c30.
+ </summary>
+</histogram>
+
<histogram name="Android.WebView.Startup.CreationTime.Stage1.FactoryInit"
units="ms">
<owner>changwan@chromium.org</owner>
@@ -2021,7 +2277,7 @@ uploading your change for review.
</histogram>
<histogram name="Android.WebView.VariationsEnableState"
- enum="AndroidWebViewVariationsEnableState" expires_after="M69">
+ enum="AndroidWebViewVariationsEnableState" expires_after="M70">
<owner>paulmiller@chromium.org</owner>
<owner>changwan@chromium.org</owner>
<summary>
@@ -2336,6 +2592,14 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Apps.AppListAppMovingType" enum="AppListAppMovingType">
+ <owner>weidongg@chromium.org</owner>
+ <summary>
+ The different ways to move an app in app list's apps grid. Logged when the
+ app moving succeeds.
+ </summary>
+</histogram>
+
<histogram name="Apps.AppListBadgedAppsCount" units="apps">
<owner>vadimt@chromium.org</owner>
<summary>
@@ -2444,6 +2708,17 @@ uploading your change for review.
<summary>The state of a Play Store app search request.</summary>
</histogram>
+<histogram name="Apps.AppListSearchBoxActivated"
+ enum="SearchBoxActivationSource">
+ <owner>newcomer@chromium.org</owner>
+ <summary>
+ The number of times the applist searchbox has been activated. This is split
+ by keystroke, mouse press, and gesture tap activations. This is gathered
+ each time the searchbox goes from inactive to active, not necessarily empty
+ to non-empty.
+ </summary>
+</histogram>
+
<histogram name="Apps.AppListSearchCommenced" units="searches">
<owner>tapted@chromium.org</owner>
<summary>
@@ -2858,6 +3133,22 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Apps.NumberOfPages" units="page(s)">
+ <owner>weidongg@chromium.com</owner>
+ <summary>
+ The number of pages that users have in the top level apps grid of their
+ Launcher. This metric is recorded every time the launcher is shown.
+ </summary>
+</histogram>
+
+<histogram name="Apps.NumberOfPagesNotFull" units="page(s)">
+ <owner>weidongg@chromium.com</owner>
+ <summary>
+ The number of pages that are not full in the top level apps grid of
+ Launcher. This metric is recorded every time the launcher is shown.
+ </summary>
+</histogram>
+
<histogram name="Apps.PaginationTransition.AnimationSmoothness" units="%">
<owner>wutao@chromium.org</owner>
<summary>
@@ -3085,6 +3376,17 @@ uploading your change for review.
<summary>Cumulative count of low memory kills in one user session.</summary>
</histogram>
+<histogram name="Arc.LowMemoryKiller.FirstKillLatency" units="ms">
+ <owner>cywang@google.com</owner>
+ <owner>elijahtaylor@google.com</owner>
+ <owner>shihuis@google.com</owner>
+ <summary>
+ When Chrome OS is in low memory state, TabManager kills some victims to free
+ memory. This value is the elapsed time between TabManager receiving the low
+ memory notification and the first kill.
+ </summary>
+</histogram>
+
<histogram name="Arc.LowMemoryKiller.FreedSize" units="KB">
<owner>elijahtaylor@google.com</owner>
<owner>shihuis@google.com</owner>
@@ -3203,161 +3505,45 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Arc.Provisioning.Result" enum="ArcProvisioningResult">
- <obsolete>
- Deprecated on 2016-09-15 and replaced by Arc.Provisioning.Result.Managed and
- Arc.Provisioning.Result.Unmanaged.
- </obsolete>
- <owner>alexchau@google.com</owner>
- <owner>phweiss@google.com</owner>
- <summary>
- The result (success or the type of failure) of ARC provisioning.
- </summary>
-</histogram>
-
-<histogram name="Arc.Provisioning.Result.Child" enum="ArcProvisioningResult">
- <owner>alexchau@google.com</owner>
- <owner>phweiss@google.com</owner>
- <summary>
- The result (success or the type of failure) of ARC provisioning for child
- accounts.
- </summary>
-</histogram>
-
-<histogram name="Arc.Provisioning.Result.Managed" enum="ArcProvisioningResult">
- <owner>alexchau@google.com</owner>
- <owner>phweiss@google.com</owner>
- <summary>
- The result (success or the type of failure) of ARC provisioning on managed
- devices.
- </summary>
-</histogram>
-
-<histogram name="Arc.Provisioning.Result.RobotAccount"
- enum="ArcProvisioningResult">
- <owner>alexchau@google.com</owner>
- <owner>phweiss@google.com</owner>
- <summary>
- The result (success or the type of failure) of ARC provisioning on managed
- devices with a robot account (Public Session or Kiosk).
- </summary>
-</histogram>
-
-<histogram name="Arc.Provisioning.Result.Unmanaged"
+<histogram base="true" name="Arc.Provisioning.Result"
enum="ArcProvisioningResult">
- <owner>alexchau@google.com</owner>
- <owner>phweiss@google.com</owner>
- <summary>
- The result (success or the type of failure) of ARC provisioning on unmanaged
- devices.
- </summary>
-</histogram>
-
-<histogram name="Arc.Provisioning.TimeDelta.Failure.Child" units="ms">
- <owner>alexchau@google.com</owner>
- <owner>phweiss@google.com</owner>
- <summary>
- Elapsed time from the signing in process start to call to onSignInFailed for
- child account.
- </summary>
-</histogram>
-
-<histogram name="Arc.Provisioning.TimeDelta.Failure.Managed" units="ms">
- <owner>alexchau@google.com</owner>
- <owner>phweiss@google.com</owner>
- <summary>
- Elapsed time from the signing in process start to call to onSignInFailed for
- managed users.
- </summary>
-</histogram>
-
-<histogram name="Arc.Provisioning.TimeDelta.Failure.RobotAccount" units="ms">
- <owner>alexchau@google.com</owner>
- <owner>phweiss@google.com</owner>
- <summary>
- Elapsed time from the signing in process start to call to onSignInFailed for
- managed users with a robot account (Public Session or Kiosk).
- </summary>
-</histogram>
+<!-- Name completed by histogram_suffixes name="ArcUserTypes" -->
-<histogram name="Arc.Provisioning.TimeDelta.Failure.Unmanaged" units="ms">
<owner>alexchau@google.com</owner>
<owner>phweiss@google.com</owner>
<summary>
- Elapsed time from the signing in process start to call to onSignInFailed for
- unmanaged users.
+ The result (success or the type of failure) of ARC provisioning. The base
+ value has been deprecated on 2016-09-15 in favour of per user type values.
</summary>
</histogram>
-<histogram name="Arc.Provisioning.TimeDelta.Success.Child" units="ms">
- <owner>alexchau@google.com</owner>
- <owner>phweiss@google.com</owner>
- <summary>
- Elapsed time from the signing in process start to successful call to
- onSignInComplete for child account.
- </summary>
-</histogram>
+<histogram name="Arc.Provisioning.TimeDelta.Failure" units="ms">
+<!-- Name completed by histogram_suffixes name="ArcUserTypes" -->
-<histogram name="Arc.Provisioning.TimeDelta.Success.Managed" units="ms">
<owner>alexchau@google.com</owner>
<owner>phweiss@google.com</owner>
<summary>
- Elapsed time from the signing in process start to successful call to
- onSignInComplete for managed users.
+ Elapsed time from the signing in process start to call to onSignInFailed.
</summary>
</histogram>
-<histogram name="Arc.Provisioning.TimeDelta.Success.RobotAccount" units="ms">
- <owner>alexchau@google.com</owner>
- <owner>phweiss@google.com</owner>
- <summary>
- Elapsed time from the signing in process start to successful call to
- onSignInComplete for managed users with a robot account (Public Session or
- Kiosk).
- </summary>
-</histogram>
+<histogram name="Arc.Provisioning.TimeDelta.Success" units="ms">
+<!-- Name completed by histogram_suffixes name="ArcUserTypes" -->
-<histogram name="Arc.Provisioning.TimeDelta.Success.Unmanaged" units="ms">
<owner>alexchau@google.com</owner>
<owner>phweiss@google.com</owner>
<summary>
Elapsed time from the signing in process start to successful call to
- onSignInComplete for unmanaged users.
+ onSignInComplete.
</summary>
</histogram>
-<histogram name="Arc.Reauthorization.Result.Child" enum="ArcProvisioningResult">
- <owner>khmel@google.com</owner>
- <summary>
- The result (success or the type of failure) of ARC reauthorization for child
- account.
- </summary>
-</histogram>
-
-<histogram name="Arc.Reauthorization.Result.Managed"
- enum="ArcProvisioningResult">
- <owner>khmel@google.com</owner>
- <summary>
- The result (success or the type of failure) of ARC reauthorization on
- managed devices.
- </summary>
-</histogram>
-
-<histogram name="Arc.Reauthorization.Result.RobotAccount"
- enum="ArcProvisioningResult">
- <owner>khmel@google.com</owner>
- <summary>
- The result (success or the type of failure) of ARC reauthorization on
- managed devices with a robot account (Public Session or Kiosk).
- </summary>
-</histogram>
+<histogram name="Arc.Reauthorization.Result" enum="ArcProvisioningResult">
+<!-- Name completed by histogram_suffixes name="ArcUserTypes" -->
-<histogram name="Arc.Reauthorization.Result.Unmanaged"
- enum="ArcProvisioningResult">
<owner>khmel@google.com</owner>
<summary>
- The result (success or the type of failure) of ARC reauthorization on
- unmanaged devices.
+ The result (success or the type of failure) of ARC reauthorization.
</summary>
</histogram>
@@ -3386,6 +3572,38 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Arc.StateByUserType" enum="ArcEnableState">
+<!-- Name completed by histogram_suffixes name="ArcUserTypes" -->
+
+ <owner>elijahtaylor@google.com</owner>
+ <owner>shihuis@google.com</owner>
+ <owner>khmel@google.com</owner>
+ <summary>
+ Similar to &quot;Arc.State&quot; metric but has separation by user type.
+ </summary>
+</histogram>
+
+<histogram name="Arc.Supervision.Transition.Result"
+ enum="ArcSupervisionTransitionResult" expires_after="M71">
+ <owner>phongo@google.com</owner>
+ <owner>brunokim@google.com</owner>
+ <summary>
+ The result (success or the type of failure) of ARC supervision transition
+ events.
+ </summary>
+</histogram>
+
+<histogram name="Arc.UserInteraction" enum="ArcUserInteraction">
+ <owner>jhorwich@chromium.org</owner>
+ <owner>elijahtaylor@chromium.org</owner>
+ <owner>shihuis@google.com</owner>
+ <owner>maajid@chromium.org</owner>
+ <summary>
+ Counts user interactions with ARC by type, such as ARC app launches via the
+ shelf or launcher.
+ </summary>
+</histogram>
+
<histogram name="ArcAuth.AccountCheckStatus" enum="ArcAuthAccountCheckStatus">
<owner>elijahtaylor@google.com</owner>
<summary>The status of account check before GMS Sign-in.</summary>
@@ -3681,12 +3899,12 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Ash.GestureTarget" enum="GestureActionType">
+<histogram name="Ash.GestureTarget" enum="AshGestureActionType">
<owner>kuscher@google.com</owner>
<owner>rbyers@chromium.org</owner>
<summary>
- The gesture-events recognized and dispatched by the browser gesture
- recognizer for various UI components.
+ The gesture-events recognized and dispatched for UI components owned by Ash.
+ For browser gestures, see Event.Touch.GestureType.
</summary>
</histogram>
@@ -4165,18 +4383,27 @@ uploading your change for review.
</histogram>
<histogram name="Ash.TouchPositionX" units="pixels">
+ <obsolete>
+ Deprecated 07/2018 due to lack of usage.
+ </obsolete>
<owner>tdanderson@chromium.org</owner>
<owner>kuscher@google.com</owner>
<summary>The position of the touch-events along the X axis.</summary>
</histogram>
<histogram name="Ash.TouchPositionY" units="pixels">
+ <obsolete>
+ Deprecated 07/2018 due to lack of usage.
+ </obsolete>
<owner>tdanderson@chromium.org</owner>
<owner>kuscher@google.com</owner>
<summary>The position of the touch-events along the Y axis.</summary>
</histogram>
<histogram name="Ash.TouchRadius" units="pixels">
+ <obsolete>
+ Deprecated 07/2018 due to lack of usage.
+ </obsolete>
<owner>tdanderson@chromium.org</owner>
<owner>kuscher@google.com</owner>
<summary>The radius of a touch event.</summary>
@@ -5898,6 +6125,15 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Autofill.CreditCardUploadDisallowedForNetwork"
+ enum="CreditCardUploadDisallowedNetwork">
+ <owner>jsaul@google.com</owner>
+ <summary>
+ When a credit card is not allowed to be offered upload save due to its
+ network, logs what the card network was.
+ </summary>
+</histogram>
+
<histogram name="Autofill.DaysSinceLastUse.CreditCard" units="days">
<owner>sebsg@chromium.org</owner>
<summary>
@@ -5917,7 +6153,7 @@ uploading your change for review.
<histogram name="Autofill.DaysSinceLastUse.StoredCreditCard" units="days">
<owner>rogerm@chromium.org</owner>
-<!-- Name completed by histogram_suffixes name="AutofillStoredCreditCardCount" -->
+<!-- Name completed by histogram_suffixes name="AutofillCreditCardType" -->
<summary>
Logs the number of days that have passed since each credit card belonging to
@@ -6192,6 +6428,21 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Autofill.LocalCardMigrationBubbleOffer"
+ enum="AutofillLocalCardMigrationBubbleOffer">
+ <owner>siyua@chromium.org</owner>
+ <summary>
+ Record events related to bubble showing. Logged when bubble is requested or
+ is actually shown to users.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.LocalCardMigrationBubbleUserInteraction"
+ enum="AutofillLocalCardMigrationBubbleUserInteraction">
+ <owner>siyua@chromium.org</owner>
+ <summary>Record how bubble is closed by different user interactions.</summary>
+</histogram>
+
<histogram name="Autofill.MacAddressBook" enum="AutofillMacAddressBook">
<obsolete>
Deprecated as of 8/2015.
@@ -6546,6 +6797,43 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Autofill.SaveCardCardholderNamePrefilled" enum="Boolean">
+ <owner>jsaul@google.com</owner>
+ <summary>
+ If the cardholder name fix flow is shown when credit card upload is offered,
+ records if the cardholder name textfield was prefilled with the name from
+ the user's Google Account.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.SaveCardCardholderNameWasEdited" enum="Boolean">
+ <owner>jsaul@google.com</owner>
+ <summary>
+ If the cardholder name fix flow is shown during credit card upload and the
+ user accepts upload, logs whether the final cardholder name was changed from
+ its prefilled value or not.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.SaveCardWithFirstAndLastNameComplete" enum="Boolean">
+ <owner>sebsg@chromium.org</owner>
+<!-- Name completed by histogram_suffixes name="AutofillCreditCardType" -->
+
+ <summary>
+ Records if a card was saved from a form that had split name fields.
+ </summary>
+</histogram>
+
+<histogram name="Autofill.SaveCardWithFirstAndLastNameOffered" enum="Boolean">
+ <owner>sebsg@chromium.org</owner>
+<!-- Name completed by histogram_suffixes name="AutofillCreditCardType" -->
+
+ <summary>
+ Records if a card was offered to be saved from a form that had split name
+ fields.
+ </summary>
+</histogram>
+
<histogram name="Autofill.SaveCreditCardPrompt"
enum="AutofillSaveCreditCardPrompt">
<owner>jdonnelly@chromium.org</owner>
@@ -6626,7 +6914,7 @@ uploading your change for review.
<histogram name="Autofill.StoredCreditCardCount" units="cards">
<owner>rogerm@chromium.org</owner>
-<!-- Name completed by histogram_suffixes name="AutofillStoredCreditCardCount" -->
+<!-- Name completed by histogram_suffixes name="AutofillCreditCardType" -->
<summary>
The number of credit cards a user has stored, measured at Chrome profile
@@ -6636,7 +6924,7 @@ uploading your change for review.
<histogram name="Autofill.StoredCreditCardDisusedCount" units="cards">
<owner>rogerm@chromium.org</owner>
-<!-- Name completed by histogram_suffixes name="AutofillStoredCreditCardCount" -->
+<!-- Name completed by histogram_suffixes name="AutofillCreditCardType" -->
<summary>
The number of disused credit cards a user has stored, measured at Chrome
@@ -7077,7 +7365,7 @@ uploading your change for review.
</histogram>
<histogram name="BackgroundMode.OnStartup.AutoLaunchState"
- enum="AutoLaunchState">
+ enum="AutoLaunchState" expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
Logged during BackgroundModeManager's initialization. Indicates the
@@ -7086,7 +7374,7 @@ uploading your change for review.
</histogram>
<histogram name="BackgroundMode.OnStartup.IsBackgroundModePrefEnabled"
- enum="BooleanEnabled">
+ enum="BooleanEnabled" expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
Logged during BackgroundModeManager's initialization. Indicates the state of
@@ -7404,8 +7692,11 @@ uploading your change for review.
Time spent to create a v8::Context instance during a page loading in the
main-frame window.
- Note: this histogram is emitted for all clients, both ones which have
- high-resolution timer available and those which don't.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -7416,8 +7707,11 @@ uploading your change for review.
Time spent to create a v8::Context instance during a page loading in a
non-main-frame window, e.g. iframe.
- Note: this histogram is emitted for all clients, both ones which have
- high-resolution timer available and those which don't.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -7428,8 +7722,11 @@ uploading your change for review.
Time spent initializing LocalWindowProxy during a page loading in main
windows.
- Note: this histogram is emitted for all clients, both ones which have
- high-resolution timer available and those which don't.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -7440,8 +7737,11 @@ uploading your change for review.
Time spent initializing RemoteWindowProxy during a page loading in main
frame of OOPIF.
- Note: this histogram is emitted for all clients, both ones which have
- high-resolution timer available and those which don't.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -7463,8 +7763,11 @@ uploading your change for review.
Time spent initializing LocalWindowProxy during a page loading in non-main
windows, e.g. iframe.
- Note: this histogram is emitted for all clients, both ones which have
- high-resolution timer available and those which don't.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -7474,8 +7777,11 @@ uploading your change for review.
<summary>
Time spent initializing RemoteWindowProxy during a page loading in OOPIF.
- Note: this histogram is emitted for all clients, both ones which have
- high-resolution timer available and those which don't.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -7525,23 +7831,55 @@ uploading your change for review.
<histogram name="Blink.Canvas.DrawImage" units="microseconds">
<owner>junov@chromium.org</owner>
- <summary>Time spent on 2D canvas drawImage API call.</summary>
+ <summary>
+ Time spent on 2D canvas drawImage API call.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="Blink.Canvas.GetImageData" units="microseconds">
<owner>junov@chromium.org</owner>
- <summary>Time spent on 2D canvas getImageData API call.</summary>
+ <summary>
+ Time spent on 2D canvas getImageData API call.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="Blink.Canvas.OffscreenCommitTimer" units="microseconds">
<owner>junov@chromium.org</owner>
<owner>xidachen@chromium.org</owner>
- <summary>Wall clock durations of OffscreenCanvas.commit() calls.</summary>
+ <summary>
+ Wall clock durations of OffscreenCanvas.commit() calls.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="Blink.Canvas.PutImageData" units="microseconds">
<owner>junov@chromium.org</owner>
- <summary>Time spent on 2D canvas putImageData API call.</summary>
+ <summary>
+ Time spent on 2D canvas putImageData API call.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="Blink.Canvas.ToBlob.CompleteEncodingDelay"
@@ -7565,6 +7903,12 @@ uploading your change for review.
also gathered into this histogram, because the logic flow is exactly the
same as canvas.toBlob. It's worth to note that the values can come from idle
tasks on either main or worker thread.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -7613,6 +7957,12 @@ uploading your change for review.
also gathered into this histogram, because the logic flow is exactly the
same as canvas.toBlob. It's worth to note that the values can come from idle
tasks on either main or worker thread.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -7626,12 +7976,26 @@ uploading your change for review.
also gathered into this histogram, because the logic flow is exactly the
same as canvas.toBlob. It's worth to note that the values can come from idle
tasks on either main or worker thread.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
<histogram name="Blink.Canvas.ToDataURL" units="microseconds">
<owner>junov@chromium.org</owner>
- <summary>Time spent on 2D canvas toDataURL API call.</summary>
+ <summary>
+ Time spent on 2D canvas toDataURL API call.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="Blink.CheckerableImageCount" enum="CheckerableImageType">
@@ -7797,22 +8161,40 @@ uploading your change for review.
<summary>
Time spent updating compositing in the Blink document lifecycle.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
<histogram name="Blink.CookieJar.SyncCookiesSetTime" units="microseconds">
<owner>kinuko@chromium.org</owner>
<owner>dcheng@chromium.org</owner>
- <summary>Microseconds per sync IPC call to set cookies.</summary>
+ <summary>
+ Microseconds per sync IPC call to set cookies.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="Blink.CookieJar.SyncCookiesTime" units="microseconds">
<owner>kinuko@chromium.org</owner>
<owner>dcheng@chromium.org</owner>
- <summary>Microseconds per sync IPC call to fetch cookies.</summary>
+ <summary>
+ Microseconds per sync IPC call to fetch cookies.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="Blink.DecodedImage.CanvasExpanded"
@@ -7896,9 +8278,11 @@ uploading your change for review.
<summary>
The total microseconds spent in ResourceFetcher::requestResource.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -7946,9 +8330,11 @@ uploading your change for review.
Time spent computing IntersectionObserver observations in the Blink document
lifecycle.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -7960,6 +8346,42 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction"
+ enum="LazyLoad.FrameInitialDeferralAction">
+ <owner>sclittle@chromium.org</owner>
+ <summary>
+ Records the initial lazy loading action taken for a cross-origin iframe.
+ </summary>
+</histogram>
+
+<histogram
+ name="Blink.LazyLoad.CrossOriginFrames.LoadStartedAfterBeingDeferred"
+ enum="NQEEffectiveConnectionType">
+ <owner>sclittle@chromium.org</owner>
+ <summary>
+ Records the effective connection type whenever a lazily-loaded iframe that
+ wasn't initially hidden or near the viewport starts loading. The count for
+ an effective connection type in this histogram can be subtracted from the
+ 'Deferred' bucket from the
+ Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction.* histogram for the
+ corresponding effective connection type to determine the number of iframes
+ that LazyLoad is avoiding to load altogether.
+ </summary>
+</histogram>
+
+<histogram name="Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred"
+ enum="NQEEffectiveConnectionType">
+ <owner>sclittle@chromium.org</owner>
+ <summary>
+ Records the effective connection type whenever a lazily-loaded iframe that
+ wasn't initially hidden or near the viewport becomes visible. The count for
+ an effective connection type in this histogram can be subtracted from the
+ corresponding count in
+ Blink.LazyLoad.CrossOriginFrames.LoadStartedAfterBeingDeferred to determine
+ how many iframes were loaded unnecessarily by LazyLoad.
+ </summary>
+</histogram>
+
<histogram name="Blink.MediaDocument.DownloadButton"
enum="MediaDocumentDownloadButtonType">
<obsolete>
@@ -8014,7 +8436,15 @@ uploading your change for review.
<histogram name="Blink.Paint.UpdateTime" units="microseconds">
<owner>paint-dev@chromium.org</owner>
- <summary>Time spent updating paint in the Blink document lifecycle.</summary>
+ <summary>
+ Time spent updating paint in the Blink document lifecycle.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="Blink.PaintInvalidation.UpdateTime" units="microseconds">
@@ -8036,12 +8466,28 @@ uploading your change for review.
document lifecycle. Available when SlimmingPaintInvalidation or
SlimmingPaintV2 is enabled.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
+<histogram name="Blink.ResourceFetcher.StaleWhileRevalidate"
+ enum="BooleanAttempted" expires_after="M71">
+ <owner>dtapuska@chromium.org</owner>
+ <owner>kenjibaheux@google.com</owner>
+ <summary>Count of resources attempted Stale Revalidation.</summary>
+</histogram>
+
+<histogram name="Blink.ResourceFetcher.StaleWhileRevalidateDuration" units="ms"
+ expires_after="M71">
+ <owner>dtapuska@chromium.org</owner>
+ <owner>kenjibaheux@google.com</owner>
+ <summary>Duration of completed stale revalidation attempts.</summary>
+</histogram>
+
<histogram base="true" name="Blink.ResourceLoadScheduler.DecodedBytes"
units="bytes">
<!-- Name completed by histogram_suffixes name="ResourceLoadScheduler.FrameType" -->
@@ -8180,6 +8626,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Blink.Script.SchedulingType" enum="ScriptSchedulingType"
+ expires_after="2018-12-31">
+ <owner>kouhei@chromium.org</owner>
+ <owner>hiroshige@chromium.org</owner>
+ <summary>
+ Number of script elements for each scheduling type, recorded for each
+ successful #prepare-a-script.
+ </summary>
+</histogram>
+
<histogram name="Blink.ScriptValueSerializer.DOMWrapperCount" units="objects">
<obsolete>
Used to justify distribution of serialized data in the wild, but unlikely to
@@ -8225,9 +8681,11 @@ uploading your change for review.
regions, touch event rects, and main thread scrolling reasons). These values
are calculated during the main-thread blink lifecycle.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -8260,33 +8718,39 @@ uploading your change for review.
<summary>
Time spent updating style and layout in the Blink document lifecycle.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
<histogram name="Blink.UseCounter.AnimatedCSSProperties"
enum="MappedCSSProperties">
- <owner>rbyers@chromium.org</owner>
+ <owner>loonybear@chromium.org</owner>
<summary>
Records usage of animated CSS properties used on a page, either statically
or dynamically, from the time the page is initialised to when it is closed
or navigated away from. Each property is counted at most once per page per
- view.
+ view via PageLoadMetricsObserver.
</summary>
<details>
- Warning: This histogram represents pre-renderer metrics and so is flawed
- under OOPIF.
-
This histogram counts CSS properties only when they are animated by a CSS
Animation. Refer to Blink.UseCounter.CSSProperties for more details.
+
+ As of M69, Blink.UseCounter.AnimatedCSSProperties is moved from the blink
+ side to the browser side.
</details>
</histogram>
<histogram
name="Blink.UseCounter.AnimatedCSSProperties_TestBrowserProcessLogging"
enum="MappedCSSProperties">
+ <obsolete>
+ Renamed to Blink.UseCounter.AnimatedCSSProperties in 03/2018, M69. The old
+ blink UseCounter is flawed in OOPIF, so moved to the browser side instead.
+ </obsolete>
<owner>loonybear@chromium.org</owner>
<summary>
Records usage of animated CSS properties used across all frames in a page,
@@ -8295,25 +8759,17 @@ uploading your change for review.
once per page view except kTotalPagesMeasuredCSSSampleId which represents a
page load (enum value of 1) and is counted exactly once per page view.
</summary>
- <details>
- This histogram tracks same usage as Blink.UseCounter.AnimatedCSSProperties.
- Once it is verified this counter is correct. It will replace the current
- counter.
- </details>
</histogram>
<histogram name="Blink.UseCounter.CSSProperties" enum="MappedCSSProperties">
- <owner>rbyers@chromium.org</owner>
+ <owner>loonybear@chromium.org</owner>
<summary>
Records usage of CSS properties used on a page, either statically or
dynamically, from the time the page is initialised to when it is closed or
- navigated away from. Each property is counted at most once per page per
- view.
+ navigated away from. Each property is counted at most once per page per view
+ via PageLoadMetricsObserver.
</summary>
<details>
- Warning: This histogram represents pre-renderer metrics and so is flawed
- under OOPIF.
-
The first time a CSS property is parsed on a page, the histogram is updated
to increment the counter. Each histogram bucket corresponds to a CSS
property (eg. width, border-radius). The exception is the 'Total pages
@@ -8332,11 +8788,18 @@ uploading your change for review.
the Blink.UseCounter.SVGImage.CSSProperties histogram.
As of M57 this histogram supercedes WebCore.FeatureObserver.CSSProperties.
+
+ As of M69, Blink.UseCounter.AnimatedCSSProperties is moved from the blink
+ side to the browser side.
</details>
</histogram>
<histogram name="Blink.UseCounter.CSSProperties_TestBrowserProcessLogging"
enum="MappedCSSProperties">
+ <obsolete>
+ Renamed to Blink.UseCounter.CSSProperties in 03/2018, M69. The old blink
+ UseCounter is flawed in OOPIF, so moved to the browser side instead.
+ </obsolete>
<owner>loonybear@chromium.org</owner>
<summary>
Records usage of CSS properties used across all frames in a page, either
@@ -8345,14 +8808,10 @@ uploading your change for review.
page per view except kTotalPagesMeasuredCSSSampleId which represents a page
load (enum value of 1) and is counted exactly once per page view.
</summary>
- <details>
- This histogram tracks same usage as Blink.UseCounter.CSSProperties. Once it
- is verified this counter is correct. It will replace the current counter.
- </details>
</histogram>
<histogram name="Blink.UseCounter.Extensions.Features" enum="FeatureObserver">
- <owner>rbyers@chromium.org</owner>
+ <owner>loonybear@chromium.org</owner>
<summary>
Count of how many page loads use various features for pages with a
chrome-extension:// URL only. The PageVisits bucket is incremented for each
@@ -8366,7 +8825,7 @@ uploading your change for review.
</histogram>
<histogram name="Blink.UseCounter.Features" enum="FeatureObserver">
- <owner>rbyers@chromium.org</owner>
+ <owner>loonybear@chromium.org</owner>
<summary>
Count of how many page loads use various features across all frames in a
page. The PageVisits bucket is incremented for each page load, and the other
@@ -8386,7 +8845,7 @@ uploading your change for review.
</histogram>
<histogram name="Blink.UseCounter.Features_Legacy" enum="FeatureObserver">
- <owner>rbyers@chromium.org</owner>
+ <owner>loonybear@chromium.org</owner>
<summary>
Count of how many page loads use various features. The PageVisits bucket is
incremented for each page load, and the other buckets incremented at most
@@ -8402,24 +8861,25 @@ uploading your change for review.
<histogram name="Blink.UseCounter.Features_TestBrowserProcessLogging"
enum="FeatureObserver">
<obsolete>
- Renamed to Blink.UseCounter.Features in 03/2019, M67. The old blink
+ Renamed to Blink.UseCounter.Features in 03/2018, M67. The old blink
UseCounter is flawed in OOPIF, so moved to the browser side (this) instead.
</obsolete>
- <owner>rbyjkers@chromium.org</owner>
+ <owner>loonybear@chromium.org</owner>
<summary>
Count of how many page loads use various features across all frames in a
page. The PageVisits bucket is incremented for each page load, and the other
buckets incremented at most once per PageVisit via the WebCore::UseCounter
class. This counter lives in browser process.
</summary>
- <details>
- This histogram is now renamed to &quot;Blink.UseCounter.Features&quot;.
- </details>
</histogram>
<histogram name="Blink.UseCounter.SVGImage.AnimatedCSSProperties"
enum="MappedCSSProperties">
- <owner>rbyers@chromium.org</owner>
+ <obsolete>
+ Removed in 06/2018, M69 since the histogram is not really useful. See
+ https://crbug.com/804645.
+ </obsolete>
+ <owner>loonybear@chromium.org</owner>
<summary>
Like Blink.UseCounter.AnimatedCSSProperties but specifically for the case of
CSS properties used inside of an SVG image.
@@ -8435,7 +8895,11 @@ uploading your change for review.
<histogram name="Blink.UseCounter.SVGImage.CSSProperties"
enum="MappedCSSProperties">
- <owner>rbyers@chromium.org</owner>
+ <obsolete>
+ Removed in 06/2018, M69 since the histogram is not really useful. See
+ https://crbug.com/804645.
+ </obsolete>
+ <owner>loonybear@chromium.org</owner>
<summary>
Like Blink.UseCounter.CSSProperties but specifically for the case of CSS
properties used inside of an SVG image.
@@ -8452,7 +8916,7 @@ uploading your change for review.
</histogram>
<histogram name="Blink.UseCounter.SVGImage.Features" enum="FeatureObserver">
- <owner>rbyers@chromium.org</owner>
+ <owner>loonybear@chromium.org</owner>
<summary>
Like Blink.UseCounter.Features except specifically for the case of SVG
Images.
@@ -8468,6 +8932,36 @@ uploading your change for review.
</details>
</histogram>
+<histogram name="Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold"
+ enum="NQEEffectiveConnectionType">
+ <owner>sclittle@chromium.org</owner>
+ <summary>
+ Records the effective connection type whenever a lazyload-eligible (i.e.
+ cross-origin and non-hidden) iframe that was initially below the fold
+ becomes visible before it finishes loading.
+ </summary>
+</histogram>
+
+<histogram name="Blink.VisibleLoadTime.LazyLoadEligibleFrames.AboveTheFold"
+ units="ms">
+ <owner>sclittle@chromium.org</owner>
+ <summary>
+ Milliseconds spent waiting for an above the fold iframe to load. Only fires
+ for iframes that would be eligible for lazy loading, i.e. cross-origin and
+ non-hidden.
+ </summary>
+</histogram>
+
+<histogram name="Blink.VisibleLoadTime.LazyLoadEligibleFrames.BelowTheFold"
+ units="ms">
+ <owner>sclittle@chromium.org</owner>
+ <summary>
+ Milliseconds spent waiting for a below the fold iframe to load. Only fires
+ for iframes that would be eligible for lazy loading, i.e. cross-origin and
+ non-hidden.
+ </summary>
+</histogram>
+
<histogram name="Blink.XHR.setRequestHeader.HeaderValueCategoryInRFC7230"
enum="XMLHttpRequestHeaderValueCategoryInRFC7230">
<obsolete>
@@ -8481,9 +8975,26 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="BlinkGC.AtomicPhaseMarking" units="ms">
+ <owner>oilpan-reviews@chromium.org</owner>
+ <summary>
+ Duration of finishing marking the transitive closure of objects during the
+ final Blink garbage collection pause. Recorded at the end of each garbage
+ collection.
+ </summary>
+</histogram>
+
<histogram name="BlinkGC.CollectGarbage" units="ms">
+ <obsolete>
+ Deprecated 06/2018. The sample taken here was a mix of marking, sweeping and
+ compaction. Replaced by BlinkGC.AtomicPhaseMarking for the marking phase and
+ BlinkGC.TimeForTotalCollectGarbage for the overal time.
+ </obsolete>
<owner>haraken@chromium.org</owner>
- <summary>Duration of time taken to run Heap::collectGarbage().</summary>
+ <summary>
+ Duration of time taken to run Heap::collectGarbage(). Recorded at the end of
+ each garbage collection.
+ </summary>
</histogram>
<histogram name="BlinkGC.CollectionRate" units="%">
@@ -8611,7 +9122,13 @@ uploading your change for review.
<histogram name="BlinkGC.TimeForTotalCollectGarbage" units="ms">
<owner>haraken@chromium.org</owner>
<owner>hpayer@chromium.org</owner>
- <summary>Duration of total Blink garbage collection time.</summary>
+ <summary>
+ Duration of total Blink garbage collection time when the garbage collector
+ is invoked for finishing a garbage collection. This includes finishing up
+ any already running garbage collection operation as well as potentially
+ performing a follow-up collection synchronously. Recorded each time after
+ invoking the Blink garbage collector.
+ </summary>
</histogram>
<histogram name="BlinkGC.TotalAllocatedSpace" units="KB">
@@ -8628,6 +9145,23 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="BloatedRenderer.HandlingInBrowser"
+ enum="BloatedRendererHandlingInBrowser">
+ <owner>ulan@chromium.org</owner>
+ <summary>
+ Records how a bloated renderer was handled in the browser process.
+ </summary>
+</histogram>
+
+<histogram name="BloatedRenderer.HandlingInResourceCoordinator"
+ enum="BloatedRendererHandlingInResourceCoordinator">
+ <owner>ulan@chromium.org</owner>
+ <summary>
+ Records how a bloated renderer was handled in the resource coordinator
+ service.
+ </summary>
+</histogram>
+
<histogram name="BloatedRenderer.V8.NearV8HeapLimitHandling"
enum="NearV8HeapLimitHandling">
<owner>ulan@chromium.org</owner>
@@ -9521,6 +10055,20 @@ uploading your change for review.
<summary>Maximal amount of memory allocated by decoder.</summary>
</histogram>
+<histogram name="Browser.Tabs.SelectionToVisibilityRequestTime"
+ units="microseconds">
+ <owner>sadrul@chromium.org</owner>
+ <owner>sky@chromium.org</owner>
+ <summary>
+ The time it takes for the browser to request a tab to be visible. Note that
+ this only measures the time from the browser deciding to make the tab
+ visible (after a click, or keyboard-shortcut to switch tabs), until the tab
+ is requested to become visible. The time it takes to actually make the tab
+ visible and show on screen is measured in a separate metric, in
+ RWH_TabSwitchPaintDuration.
+ </summary>
+</histogram>
+
<histogram name="BrowserActions.NumTabCreatedInBackground" units="tabNum">
<owner>ltian@chromium.org</owner>
<summary>
@@ -9667,6 +10215,14 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="BrowserServices.TwaOpenTime" units="ms">
+ <owner>peconn@chromium.org</owner>
+ <summary>
+ Triggered when a TrustedWebActivity is paused, recording the time since it
+ had been resumed.
+ </summary>
+</histogram>
+
<histogram name="BrowserServices.VerificationResult"
enum="BrowserServicesVerificationResult">
<owner>peconn@chromium.org</owner>
@@ -10334,6 +10890,16 @@ uploading your change for review.
<summary>Count of child process crashes grouped by process type.</summary>
</histogram>
+<histogram name="ChildProcess.Crashed.UtilityProcessHash"
+ enum="UtilityProcessNameHash">
+ <owner>wfh@chromium.org</owner>
+ <summary>
+ Count of child utility process crashes, bucketed by the hash of their
+ process name. The process name is typically the service name of the mojo
+ service.
+ </summary>
+</histogram>
+
<histogram name="ChildProcess.Crashed2" enum="ProcessType2">
<owner>wfh@chromium.org</owner>
<summary>Count of child process crashes grouped by process type.</summary>
@@ -10498,6 +11064,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="ChildProcess.Launched.UtilityProcessHash"
+ enum="UtilityProcessNameHash">
+ <owner>wfh@chromium.org</owner>
+ <summary>
+ Count of child utility process launches, bucketed by the hash of their
+ process name. The process name is typically the service name of the mojo
+ service.
+ </summary>
+</histogram>
+
<histogram name="Chrome.Android.Activity.CrashCounts" enum="AndroidActivityId">
<obsolete>
Deprecated 04/2016 as doesn't have data nor owner.
@@ -10583,7 +11159,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Chrome.ProcessSingleton.NotifyResult" enum="NotifyResult">
+<histogram name="Chrome.ProcessSingleton.NotifyResult" enum="NotifyResult"
+ expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
The result of every rendez-vous reported once per browser process launch.
@@ -10659,7 +11236,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Chrome.ProcessSingleton.TimeToCreate" units="ms">
+<histogram name="Chrome.ProcessSingleton.TimeToCreate" units="ms"
+ expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
Time it takes to grab the process singleton. Reported once per successful
@@ -10667,7 +11245,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Chrome.ProcessSingleton.TimeToFailure" units="ms">
+<histogram name="Chrome.ProcessSingleton.TimeToFailure" units="ms"
+ expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
Time it takes to return an error from the process singleton algorithm (nor
@@ -10676,7 +11255,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Chrome.ProcessSingleton.TimeToNotify" units="ms">
+<histogram name="Chrome.ProcessSingleton.TimeToNotify" units="ms"
+ expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
Time it takes to find the process singleton owner and notify it. Reported
@@ -10931,6 +11511,19 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="ChromeOS.MessageCenter.ScrollActionReason"
+ enum="ChromeOSMessageCenterScrollActionReason" expires_after="2018-11-30">
+ <owner>yoshiki@chromium.org</owner>
+ <owner>omrilio@chromium.org</owner>
+ <summary>
+ The cause of the scroll event by the user on the message center. Only the
+ first event after the message center opens is recorded. For example, the
+ user opens the message center and scrolls by mouse then by key, only the
+ mouse event is recorded. If the user closes and reopens the message center
+ before the second event, both events are recorded.
+ </summary>
+</histogram>
+
<histogram name="ChromeOS.PlatformVerification.Available"
enum="BooleanAvailable">
<owner>dkrahn@chromium.org</owner>
@@ -11130,9 +11723,11 @@ uploading your change for review.
<summary>
Input event delivery latency from the browser to the plugin.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -11245,7 +11840,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="clickjacking.discard_download" units="ms">
+<histogram name="clickjacking.discard_download" units="ms"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The length of time between a dangerous download appearing on the downloads
@@ -11262,7 +11858,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="clickjacking.launch_url" units="ms">
+<histogram name="clickjacking.launch_url" units="ms" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The length of time between the external protocol dialog being shown and the
@@ -11270,7 +11866,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="clickjacking.open_download" units="ms">
+<histogram name="clickjacking.open_download" units="ms"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The length of time between a download appearing on the download shelf, and
@@ -11587,6 +12184,12 @@ uploading your change for review.
<summary>Chrome OS only. Time it takes to mount a component image.</summary>
</histogram>
+<histogram name="ComponentUpdater.UpdateCompleteError"
+ enum="UpdateClientErrors">
+ <owner>sorin@chromium.org</owner>
+ <summary>The result of an install or an update check.</summary>
+</histogram>
+
<histogram name="ComponentUpdater.UpdateCompleteResult" enum="BooleanError">
<owner>sorin@chromium.org</owner>
<summary>The result of an install or an update check.</summary>
@@ -11660,6 +12263,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Compositing.Browser.DrawResult" enum="DrawResult"
+ expires_after="M72">
+ <owner>kylechar@chromium.org</owner>
+ <summary>
+ How often the layer compositor successfully submitted content to the display
+ compositor, or what caused an abort. This is reported fairly late in the
+ pipeline, during the final stages of submitting content.
+ </summary>
+</histogram>
+
<histogram name="Compositing.Browser.GPUMemoryForTilingsInKb" units="Kb">
<owner>yigu@chromium.org</owner>
<summary>
@@ -11682,6 +12295,12 @@ uploading your change for review.
do hit testing on LayerTreeImpl (in a browser process).
Team: animations-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -11691,9 +12310,11 @@ uploading your change for review.
Time spent updating layers, in microseconds. Recorded when layers are
updated (in a browser process).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -11704,9 +12325,11 @@ uploading your change for review.
Time spent updating layer draw properties, in microseconds. Recorded when a
LayerTreeImpl's draw properties are updated (in a browser process).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -11759,9 +12382,11 @@ uploading your change for review.
Time spent updating (i.e. recording) a picture pile, in microseconds.
Recorded when picture pile is updated (in a browser process).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -11795,9 +12420,11 @@ uploading your change for review.
Time spent completing a compositor rasterization task, in microseconds.
Recorded after the task finishes (in a browser process).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -11827,7 +12454,20 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Compositing.CopyFromSurfaceTime" units="ms">
+<histogram name="Compositing.CompositorFrameSinkSupport.SubmitResult"
+ enum="CompositorFrameSinkSubmitResult">
+ <owner>fsamuel@chromium.org</owner>
+ <summary>
+ The result of submitting a CompositorFrame to a CompositorFrameSink.
+ ACCEPTED means the frame was accepted by the CompositorFrameSink.
+ COPY_OUTPUT_REQUESTS_NOT_ALLOWED means an unprivileged client attempted to
+ readback a texture. SURFACE_INVARIANTS_VIOLATION means size or device scale
+ factor changed but a new viz::LocalSurfaceId was not allocated.
+ </summary>
+</histogram>
+
+<histogram name="Compositing.CopyFromSurfaceTime" units="ms"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The turn around time taken for the async readback of pixels is measured
@@ -11852,9 +12492,11 @@ uploading your change for review.
Time spent drawing of composited layers by GLRenderer, in microseconds. This
is logged once per frame, when a frame should be drawn.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -11865,9 +12507,11 @@ uploading your change for review.
Time spent drawing of composited layers by SoftwareRenderer, in
microseconds. This is logged once per frame, when a frame should be drawn.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -11877,9 +12521,11 @@ uploading your change for review.
<summary>
Time spent to remove invisible quads from the quad_list in CompositorFrame.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -12127,6 +12773,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Compositing.Renderer.DrawResult" enum="DrawResult"
+ expires_after="M72">
+ <owner>kylechar@chromium.org</owner>
+ <summary>
+ How often the layer compositor successfully submitted content to the display
+ compositor, or what caused an abort. This is reported fairly late in the
+ pipeline, during the final stages of submitting content.
+ </summary>
+</histogram>
+
<histogram name="Compositing.Renderer.GPUMemoryForTilingsInKb" units="Kb">
<owner>yigu@chromium.org</owner>
<summary>
@@ -12149,6 +12805,12 @@ uploading your change for review.
do hit testing on LayerTreeImpl (in a renderer process).
Team: animations-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -12158,9 +12820,11 @@ uploading your change for review.
Time spent updating layers, in microseconds. Recorded when layers are
updated (in a renderer process).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -12171,9 +12835,11 @@ uploading your change for review.
Time spent updating layer draw properties, in microseconds. Recorded when a
LayerTreeImpl's draw properties are updated (in a renderer process).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -12227,9 +12893,11 @@ uploading your change for review.
Time spent updating (i.e. recording) a picture pile, in microseconds.
Recorded when picture pile is updated (in a renderer process).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -12263,9 +12931,11 @@ uploading your change for review.
Time spent completing a compositor rasterization task, in microseconds.
Recorded after the task finishes (in a renderer process).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -12345,9 +13015,11 @@ uploading your change for review.
Time spent aggregating compositor frames from different surfaces in
microseconds. This is logged once per frame.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -12674,6 +13346,14 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="ContentSettings.EphemeralFlashPermission"
+ enum="ContentSettings.EphemeralFlashPermission" expires_after="M71">
+ <owner>rhalavati@chromium.org</owner>
+ <summary>
+ Records the number of times Flash permission is granted for a host.
+ </summary>
+</histogram>
+
<histogram name="ContentSettings.Exceptions">
<owner>lshang@chromium.org</owner>
<summary>
@@ -12988,6 +13668,18 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="ContentSettings.Popups.StrongBlockerActivationPosition"
+ enum="SafeBrowsingActivationPosition">
+ <owner>csharrison@chromium.org</owner>
+ <owner>ericrobinson@chromium.org</owner>
+ <summary>
+ For pages that trigger Safe Browsing triggered popup blocker (in warn or
+ enforce modes), records the position in the redirect chain for the page the
+ activation was triggered by. If SubresourceFilterConsiderRedirects is
+ disabled, then always returns &quot;Only navigation&quot;.
+ </summary>
+</histogram>
+
<histogram name="ContentSuggestions.Feed.NetworkRequestStatusCode"
enum="CombinedHttpResponseAndNetErrorCode">
<owner>pnoland@chromium.org</owner>
@@ -13168,6 +13860,15 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="ContextualSuggestions.FetchLatencyMilliseconds" units="ms">
+ <owner>pnoland@chromium.org</owner>
+ <owner>fgorski@chromium.org</owner>
+ <summary>
+ Android: the amount of time taken elapsed between a contextual suggestion
+ fetch starting and ending. Recorded when a fetch is completed.
+ </summary>
+</histogram>
+
<histogram name="ContextualSuggestions.FetchRequestProtoSizeKB" units="KB">
<owner>pnoland@chromium.org</owner>
<summary>
@@ -13186,7 +13887,19 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="ContextualSuggestions.FetchResponseNetworkBytes" units="bytes">
+ <owner>pnoland@chromium.org</owner>
+ <summary>
+ Android: The number of bytes in the response received when a contextual
+ suggestions fetch completes. Recorded when the response is received.
+ </summary>
+</histogram>
+
<histogram name="ContextualSuggestions.FetchResponseSizeKB" units="KB">
+ <obsolete>
+ Removed 2018-06-01 in favor of a histogram that measures bytes received over
+ the network directly instead of the uncompressed KB.
+ </obsolete>
<owner>pnoland@chromium.org</owner>
<summary>
Android: The size of the response body received when a contextual
@@ -13417,7 +14130,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Cookie.KillDatabaseResult" enum="BooleanSuccess">
+<histogram name="Cookie.KillDatabaseResult" enum="BooleanSuccess"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Whether killing the database because it was corrupted beyond repair
@@ -13625,7 +14339,8 @@ uploading your change for review.
<summary>The amount of time (ms) to migrate a v7 database to v8.</summary>
</histogram>
-<histogram name="Cookie.TimeDatabaseMigrationToV9" units="ms">
+<histogram name="Cookie.TimeDatabaseMigrationToV9" units="ms"
+ expires_after="2018-08-30">
<owner>erikchen@chromium.org</owner>
<summary>The amount of time (ms) to migrate a v8 database to v9.</summary>
</histogram>
@@ -13678,7 +14393,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Cookie.TimeLoadDBQueueWait" units="ms">
+<histogram name="Cookie.TimeLoadDBQueueWait" units="ms"
+ expires_after="2018-08-30">
<owner>erikchen@chromium.org</owner>
<summary>
This histogram records the wall-clock delay between the Load task being
@@ -13720,9 +14436,11 @@ uploading your change for review.
metadata. The metadata would be used to feed Icing for CopylessPaste feature
on Android. This only counts pages with failed or empty JSON extraction.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -13738,9 +14456,11 @@ uploading your change for review.
metadata. The metadata would be used to feed Icing for CopylessPaste feature
on Android. This only counts pages with successful JSON extraction.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -13990,24 +14710,60 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Crostini.AppsInstalledAtLogin" units="apps">
+ <owner>jopra@chromium.org</owner>
+ <owner>tbuckley@chromium.org</owner>
+ <summary>
+ Records the number of Crostini apps that surface in the launcher at login
+ time (not including the Terminal). This only logs if Crostini is enabled for
+ the current user.
+ </summary>
+</histogram>
+
<histogram name="Crostini.SetupResult" enum="CrostiniSetupResult">
<owner>benwells@chromium.org</owner>
<owner>tbuckley@chromium.org</owner>
<summary>
- Recorded each time the user initiates the Crostini setup UI, recording the
+ Recorded each time the user completes the Crostini setup UI, recording the
result of the setup.
</summary>
</histogram>
+<histogram name="Crostini.SetupSource" enum="CrostiniUISurface">
+ <owner>benwells@chromium.org</owner>
+ <owner>tbuckley@chromium.org</owner>
+ <summary>
+ Recorded each time the user initiates the Crostini setup UI, recording the
+ UI surface that invoked the setup.
+ </summary>
+</histogram>
+
+<histogram name="Crostini.TimeFromDeviceSetupToInstall" units="ms">
+ <owner>benwells@chromium.org</owner>
+ <owner>tbuckley@chromium.org</owner>
+ <summary>
+ The time from a user setting up their device, to the user enabling Crostini.
+ </summary>
+</histogram>
+
<histogram name="Crostini.UninstallResult" enum="CrostiniUninstallResult">
<owner>benwells@chromium.org</owner>
<owner>tbuckley@chromium.org</owner>
<summary>
- Recorded each time the user initiates the Crostini uninstall UI, recording
+ Recorded each time the user completes the Crostini uninstall UI, recording
the result of the uninstall.
</summary>
</histogram>
+<histogram name="Crostini.UninstallSource" enum="CrostiniUISurface">
+ <owner>benwells@chromium.org</owner>
+ <owner>tbuckley@chromium.org</owner>
+ <summary>
+ Recorded each time the user initiates the Crostini uninstall UI, recording
+ the UI surface that initiated the uninstall.
+ </summary>
+</histogram>
+
<histogram name="CryptAuth.DeviceSyncSoftwareFeaturesResult"
enum="BooleanSuccess">
<owner>hansberry@chromium.org</owner>
@@ -14381,7 +15137,8 @@ uploading your change for review.
<histogram name="CustomTabs.ConnectionStatusOnReturn.GSA"
enum="CustomTabsConnection">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>nyquist@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
Android: Recorded whenever user closes the custom tab by hitting the close
button or back to return to the caller app. Keeps track of the connection
@@ -14392,7 +15149,8 @@ uploading your change for review.
<histogram name="CustomTabs.ConnectionStatusOnReturn.NonGSA"
enum="CustomTabsConnection">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>nyquist@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
Android: Recorded whenever user closes the custom tab by hitting the close
button or back to return to the caller app. Keeps track of the connection
@@ -14427,6 +15185,47 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="CustomTabs.DynamicModule.CreateActivityDelegateTime"
+ units="ms">
+ <owner>mvanouwerkerk@chromium.org</owner>
+ <summary>
+ Time to create an activity delegate for a custom tabs dynamic module.
+ Android only.
+ </summary>
+</histogram>
+
+<histogram name="CustomTabs.DynamicModule.CreatePackageContextTime" units="ms">
+ <owner>mvanouwerkerk@chromium.org</owner>
+ <summary>
+ Time to create the package context for a custom tabs dynamic module. Android
+ only.
+ </summary>
+</histogram>
+
+<histogram name="CustomTabs.DynamicModule.EntryPointLoadClassTime" units="ms">
+ <owner>mvanouwerkerk@chromium.org</owner>
+ <summary>
+ Time to load the entry point class for a custom tabs dynamic module. Android
+ only.
+ </summary>
+</histogram>
+
+<histogram name="CustomTabs.DynamicModule.EntryPointNewInstanceTime" units="ms">
+ <owner>mvanouwerkerk@chromium.org</owner>
+ <summary>
+ Time to instantiate the entry point class for a custom tabs dynamic module.
+ Android only.
+ </summary>
+</histogram>
+
+<histogram name="CustomTabs.DynamicModule.LoadResult"
+ enum="CustomTabsDynamicModuleLoadResult">
+ <owner>mvanouwerkerk@chromium.org</owner>
+ <summary>
+ Possible results when loading a custom tabs dynamic module. Android only.
+ </summary>
+</histogram>
+
<histogram name="CustomTabs.IntentToFirstCommitNavigationTime" units="ms">
<obsolete>
Deprecated 10/2016 in favor of .IntentToFirstCommitNavigationTime2.*.
@@ -15084,6 +15883,35 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="DataReductionProxy.LastWeekAggregateKB.Services"
+ enum="DataUseServicesHash">
+ <owner>rajendrant@chromium.org</owner>
+ <owner>bengr@chromium.org</owner>
+ <summary>
+ Records the aggregate data use of services for the last week. Different
+ conditions are added as suffixes to this histogram. Recorded when Chrome is
+ started, so this does not include the current session. The aggregation
+ happens when requests complete. The current week calculation is based on
+ week starting from the Epoch day(Thursday, January 1, 1970), and every 7
+ days is treated as a week.
+ </summary>
+</histogram>
+
+<histogram
+ name="DataReductionProxy.LastWeekAggregateKB.UserTraffic.Downstream.ContentType"
+ enum="DataUseContentType">
+ <owner>rajendrant@chromium.org</owner>
+ <owner>bengr@chromium.org</owner>
+ <summary>
+ Records the aggregate data use for the last week. This is the downstream
+ data use of all user-initiated traffic. Recorded when Chrome is started, so
+ this does not include the current session. The aggregation happens when
+ requests complete. The current week calculation is based on week starting
+ from the Epoch day(Thursday, January 1, 1970), and every 7 days is treated
+ as a week.
+ </summary>
+</histogram>
+
<histogram name="DataReductionProxy.LevelDBOpenStatus"
enum="DataReductionProxyStoreStatus">
<owner>kundaji@chromium.org</owner>
@@ -15404,9 +16232,6 @@ uploading your change for review.
<histogram name="DataReductionProxy.ResponseProxyServerStatus"
enum="DataReductionProxyResponseProxyServerStatus">
- <obsolete>
- Deprecated 2018/05.
- </obsolete>
<owner>sclittle@chromium.org</owner>
<owner>bengr@chromium.org</owner>
<summary>
@@ -15528,6 +16353,35 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="DataReductionProxy.ThisWeekAggregateKB.Services"
+ enum="DataUseServicesHash">
+ <owner>rajendrant@chromium.org</owner>
+ <owner>bengr@chromium.org</owner>
+ <summary>
+ Records the aggregate data use of services for the current week. Different
+ conditions are added as suffixes to this histogram. Recorded when Chrome is
+ started, so this does not include the current session. The aggregation
+ happens when requests complete. The current week calculation is based on
+ week starting from the Epoch day(Thursday, January 1, 1970), and every 7
+ days is treated as a week.
+ </summary>
+</histogram>
+
+<histogram
+ name="DataReductionProxy.ThisWeekAggregateKB.UserTraffic.Downstream.ContentType"
+ enum="DataUseContentType">
+ <owner>rajendrant@chromium.org</owner>
+ <owner>bengr@chromium.org</owner>
+ <summary>
+ Records the aggregate data use for the current week. This is the downstream
+ data use of all user-initiated traffic. Recorded when Chrome is started, so
+ this does not include the current session. The aggregation happens when
+ requests complete. The current week calculation is based on week starting
+ from the Epoch day(Thursday, January 1, 1970), and every 7 days is treated
+ as a week.
+ </summary>
+</histogram>
+
<histogram name="DataReductionProxy.TimeToFirstDataSaverRequest" units="ms">
<obsolete>
Deprecated 2018/04.
@@ -15594,6 +16448,19 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="DataReductionProxy.UserViewedSavingsDifferenceWithBreakdown"
+ units="%">
+ <owner>robertogden@chromium.org</owner>
+ <owner>bengr@chromium.org</owner>
+ <summary>
+ The difference between the total data savings as displayed to the user and
+ the sum of the data savings for all hosts in the data use breakdown.
+ Calculated as a percentage of `abs(summedSavingsTotal -
+ displayedSavingsTotal) / (summedSavingsTotal + displayedSavingsTotal)`.
+ Recorded when the user views the data savings in the UI.
+ </summary>
+</histogram>
+
<histogram name="DataReductionProxy.UserViewedSavingsPercent" units="%">
<owner>tbansal@chromium.org</owner>
<summary>
@@ -15613,6 +16480,19 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="DataReductionProxy.UserViewedUsageDifferenceWithBreakdown"
+ units="%">
+ <owner>robertogden@chromium.org</owner>
+ <owner>bengr@chromium.org</owner>
+ <summary>
+ The difference between the total data usage as displayed to the user and the
+ sum of the data usage for all hosts in the data use breakdown. Calculated as
+ a percentage of `abs(summedUsageTotal - displayedUsageTotal) /
+ (summedUsageTotal + displayedUsageTotal)`. Recorded when the user views the
+ data savings in the UI.
+ </summary>
+</histogram>
+
<histogram name="DataReductionProxy.WarmupURL.FetchAttemptEvent"
enum="DataReductionProxyWarmupURLFetchAttemptEvent">
<owner>tbansal@chromium.org</owner>
@@ -15686,6 +16566,9 @@ uploading your change for review.
</histogram>
<histogram name="DataUsage.MatchingRulesCount.Invalid" units="count">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>bengr@chromium.org</owner>
<owner>rajendrant@chromium.org</owner>
<summary>
@@ -15695,6 +16578,9 @@ uploading your change for review.
</histogram>
<histogram name="DataUsage.MatchingRulesCount.Valid" units="count">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>bengr@chromium.org</owner>
<owner>rajendrant@chromium.org</owner>
<summary>
@@ -15704,6 +16590,9 @@ uploading your change for review.
</histogram>
<histogram name="DataUsage.PageLoadSequence" units="Count">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>rajendrant@chromium.org</owner>
<owner>bengr@chromium.org</owner>
<summary>
@@ -15713,6 +16602,9 @@ uploading your change for review.
</histogram>
<histogram name="DataUsage.Perf.MatchingRuleFirstFetchDuration" units="ms">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>bengr@chromium.org</owner>
<owner>rajendrant@chromium.org</owner>
<summary>
@@ -15725,6 +16617,9 @@ uploading your change for review.
</histogram>
<histogram name="DataUsage.Perf.ReportSubmissionDuration" units="ms">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>bengr@chromium.org</owner>
<owner>rajendrant@chromium.org</owner>
<summary>
@@ -15737,6 +16632,9 @@ uploading your change for review.
</histogram>
<histogram name="DataUsage.Perf.URLRegexMatchDuration" units="ms">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>bengr@chromium.org</owner>
<owner>rajendrant@chromium.org</owner>
<summary>
@@ -15746,6 +16644,9 @@ uploading your change for review.
</histogram>
<histogram name="DataUsage.ReportSubmission.Bytes" units="bytes">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>bengr@chromium.org</owner>
<owner>tbansal@chromium.org</owner>
<summary>
@@ -15756,6 +16657,9 @@ uploading your change for review.
<histogram name="DataUsage.ReportSubmissionResult"
enum="DataUsageReportSubmissionResult">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>bengr@chromium.org</owner>
<owner>tbansal@chromium.org</owner>
<summary>Result of data usage report submission.</summary>
@@ -15763,6 +16667,9 @@ uploading your change for review.
<histogram name="DataUsage.TabModel.ExpiredActiveTabEntryRemovalDuration"
units="ms">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>bengr@chromium.org</owner>
<owner>rajendrant@chromium.org</owner>
<summary>
@@ -15781,6 +16688,9 @@ uploading your change for review.
<histogram name="DataUsage.TabModel.ExpiredInactiveTabEntryRemovalDuration"
units="ms">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>bengr@chromium.org</owner>
<owner>rajendrant@chromium.org</owner>
<summary>
@@ -15798,6 +16708,9 @@ uploading your change for review.
<histogram name="DataUsage.TabModel.OldInactiveSessionRemovalDuration"
units="ms">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>bengr@chromium.org</owner>
<owner>rajendrant@chromium.org</owner>
<summary>
@@ -15813,6 +16726,9 @@ uploading your change for review.
</histogram>
<histogram name="DataUsage.TabModel.TrackingSessionLifetime" units="ms">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>bengr@chromium.org</owner>
<owner>rajendrant@chromium.org</owner>
<summary>
@@ -15825,6 +16741,9 @@ uploading your change for review.
<histogram name="DataUsage.TabModel.UnexpiredTabEntryRemovalDuration"
units="ms">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>bengr@chromium.org</owner>
<owner>rajendrant@chromium.org</owner>
<summary>
@@ -15843,6 +16762,9 @@ uploading your change for review.
<histogram name="DataUsage.TrackingSessionEndReason"
enum="DataUsageTrackingSessionEndReason">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>rajendrant@chromium.org</owner>
<owner>bengr@chromium.org</owner>
<summary>
@@ -15853,6 +16775,9 @@ uploading your change for review.
<histogram name="DataUsage.TrackingSessionStartReason"
enum="DataUsageTrackingSessionStartReason">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>rajendrant@chromium.org</owner>
<owner>bengr@chromium.org</owner>
<summary>
@@ -15862,6 +16787,9 @@ uploading your change for review.
</histogram>
<histogram name="DataUsage.UIAction" enum="DataUsageUIAction">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>bengr@chromium.org</owner>
<owner>megjablon@chromium.org</owner>
<summary>
@@ -16560,7 +17488,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Recovery.DiskSpace" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.DiskSpace" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of the DiskSpace recovery step that runs
@@ -16571,7 +17500,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Recovery.InstallType" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.InstallType" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
TBD - Not run automatically yet, so this is just a placeholder for future
@@ -16580,7 +17510,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Recovery.JSONBookmarks" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.JSONBookmarks" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of the JSONBookmarks recovery step that
@@ -16590,7 +17521,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Recovery.JSONLocalState" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.JSONLocalState" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of the JSONLocalState recovery step that
@@ -16600,7 +17532,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Recovery.JSONPreferences" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.JSONPreferences" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of the JSONPreferences recovery step
@@ -16623,7 +17556,7 @@ uploading your change for review.
</histogram>
<histogram name="Diagnostics.Recovery.PathDictionaries"
- enum="DiagnosticsResult">
+ enum="DiagnosticsResult" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of the PathDictionaries recovery step
@@ -16634,7 +17567,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Recovery.PathLocalState" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.PathLocalState" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of the PathLocalState recovery step that
@@ -16644,7 +17578,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Recovery.PathResources" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.PathResources" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of the PathResources recovery step that
@@ -16655,7 +17590,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Recovery.PathUserData" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.PathUserData" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of the PathUserData recovery step that
@@ -16738,7 +17674,7 @@ uploading your change for review.
</histogram>
<histogram name="Diagnostics.Recovery.SQLiteIntegrityNSSCert"
- enum="DiagnosticsResult">
+ enum="DiagnosticsResult" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of the SQLiteIntegrityNSSCert recovery
@@ -16749,7 +17685,7 @@ uploading your change for review.
</histogram>
<histogram name="Diagnostics.Recovery.SQLiteIntegrityNSSKey"
- enum="DiagnosticsResult">
+ enum="DiagnosticsResult" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of the SQLiteIntegrityNSSKey recovery
@@ -16795,7 +17731,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Recovery.Version" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.Version" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
TBD - Not run automatically yet, so this is just a placeholder for future
@@ -16825,7 +17762,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Test.DiskSpace" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.DiskSpace" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of diagnostics for the DiskSpace test
@@ -16835,7 +17773,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Test.InstallType" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.InstallType" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
TBD - Not run automatically yet, so this is just a placeholder for future
@@ -16844,7 +17783,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Test.JSONBookmarks" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.JSONBookmarks" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of diagnostics for the JSONBookmarks
@@ -16853,7 +17793,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Test.JSONLocalState" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.JSONLocalState" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of diagnostics for the JSONLocalState
@@ -16862,7 +17803,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Test.JSONPreferences" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.JSONPreferences" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of diagnostics for the JSONPreferences
@@ -16883,7 +17825,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Test.PathDictionaries" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.PathDictionaries" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of diagnostics for the PathDictionaries
@@ -16893,7 +17836,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Test.PathLocalState" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.PathLocalState" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of diagnostics for the PathLocalState
@@ -16903,7 +17847,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Test.PathResources" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.PathResources" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of diagnostics for the PathResources
@@ -16913,7 +17858,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Test.PathUserData" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.PathUserData" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of diagnostics for the PathUserData test
@@ -16989,7 +17935,7 @@ uploading your change for review.
</histogram>
<histogram name="Diagnostics.Test.SQLiteIntegrityNSSCert"
- enum="DiagnosticsResult">
+ enum="DiagnosticsResult" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of the SQLiteIntegrityNSSCert test that
@@ -16999,7 +17945,7 @@ uploading your change for review.
</histogram>
<histogram name="Diagnostics.Test.SQLiteIntegrityNSSKey"
- enum="DiagnosticsResult">
+ enum="DiagnosticsResult" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Shows the success and failure rates of the SQLiteIntegrityNSSKey test that
@@ -17041,7 +17987,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Diagnostics.Test.Version" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.Version" enum="DiagnosticsResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
TBD - Not run automatically yet, so this is just a placeholder for future
@@ -17289,6 +18236,15 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Discarding.OnlineOnReload" enum="Boolean">
+<!-- Name completed by histogram_suffixes name="DiscardReason" -->
+
+ <owner>fdoray@chromium.org</owner>
+ <summary>
+ Whether the machine was online when a discarded tab was reloaded.
+ </summary>
+</histogram>
+
<histogram name="Discarding.Urgent.NumAliveTabs" units="tabs">
<owner>fdoray@chromium.org</owner>
<summary>
@@ -17404,12 +18360,12 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="DiskCache.3.FilesAge" units="hours">
+<histogram name="DiskCache.3.FilesAge" units="hours" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>The age of the cache's files (wall time). AppCache.</summary>
</histogram>
-<histogram name="DiskCache.4.FilesAge" units="hours">
+<histogram name="DiskCache.4.FilesAge" units="hours" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>The age of the cache's files (wall time). ShaderCache.</summary>
</histogram>
@@ -17480,6 +18436,9 @@ uploading your change for review.
</histogram>
<histogram name="DNS.AttemptCancelled">
+ <obsolete>
+ Deprecated as of 6/2018.
+ </obsolete>
<owner>mgersh@chromium.org</owner>
<summary>
The attempt which completed after the job was already cancelled.
@@ -17542,6 +18501,9 @@ uploading your change for review.
</histogram>
<histogram name="DNS.AttemptTimeSavedByRetry" units="ms">
+ <obsolete>
+ Deprecated as of 6/2018.
+ </obsolete>
<owner>mgersh@chromium.org</owner>
<summary>
This histogram shows the time saved by having spawned an extra attempt, when
@@ -18484,35 +19446,83 @@ uploading your change for review.
<histogram name="DocumentEventTiming.BeforeUnloadDuration" units="microseconds">
<owner>panicker@chromium.org</owner>
- <summary>Microseconds spent in beforeunload.</summary>
+ <summary>
+ Microseconds spent in beforeunload.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="DocumentEventTiming.FreezeDuration" units="microseconds">
<owner>panicker@chromium.org</owner>
<owner>fmeawad@chromium.org</owner>
- <summary>Microseconds spent in onfreeze.</summary>
+ <summary>
+ Microseconds spent in onfreeze.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="DocumentEventTiming.PageHideDuration" units="microseconds">
<owner>panicker@chromium.org</owner>
- <summary>Microseconds spent in pagehide.</summary>
+ <summary>
+ Microseconds spent in pagehide.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="DocumentEventTiming.PageVibilityHiddenDuration"
units="microseconds">
<owner>panicker@chromium.org</owner>
- <summary>Microseconds spent in vibilitychange (hidden).</summary>
+ <summary>
+ Microseconds spent in vibilitychange (hidden).
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="DocumentEventTiming.ResumeDuration" units="microseconds">
<owner>panicker@chromium.org</owner>
<owner>fmeawad@chromium.org</owner>
- <summary>Microseconds spent in onresume.</summary>
+ <summary>
+ Microseconds spent in onresume.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="DocumentEventTiming.UnloadDuration" units="microseconds">
<owner>panicker@chromium.org</owner>
- <summary>Microseconds spent in unload.</summary>
+ <summary>
+ Microseconds spent in unload.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="DocumentScan.ConverterResult" enum="BooleanSuccess">
@@ -19204,7 +20214,8 @@ uploading your change for review.
<summary>The length of downloads for serves that accept byte ranges.</summary>
</histogram>
-<histogram name="Download.AcceptRangesMissingOrInvalid.KBytes" units="KB">
+<histogram name="Download.AcceptRangesMissingOrInvalid.KBytes" units="KB"
+ expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
The length of downloads for serves that do not specify whether the accept
@@ -19212,7 +20223,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Download.AcceptRangesNone.KBytes" units="KB">
+<histogram name="Download.AcceptRangesNone.KBytes" units="KB"
+ expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
The length of downloads for serves that do not accept ranges.
@@ -19241,7 +20253,7 @@ uploading your change for review.
</histogram>
<histogram name="Download.AttachmentServices.Result"
- enum="AttachmentServicesResult">
+ enum="AttachmentServicesResult" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
Result of invoking (or attempting to invoke) Windows Attachment Services API
@@ -19249,7 +20261,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Download.BandwidthDiskBytesPerSecond">
+<histogram name="Download.BandwidthDiskBytesPerSecond"
+ expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
Disk bandwidth (defined as total bytes divided by the amount of time blocked
@@ -19435,7 +20448,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Download.Database.CreateDownloadDuration" units="ms">
+<histogram name="Download.Database.CreateDownloadDuration" units="ms"
+ expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>Time taken to create a single download in the history DB.</summary>
</histogram>
@@ -19450,12 +20464,14 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Download.Database.QueryDownloadDuration" units="ms">
+<histogram name="Download.Database.QueryDownloadDuration" units="ms"
+ expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>Time taken to query all downloads from history DB.</summary>
</histogram>
-<histogram name="Download.Database.UpdateDownloadDuration" units="ms">
+<histogram name="Download.Database.UpdateDownloadDuration" units="ms"
+ expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>Time taken to update a single download in the history DB.</summary>
</histogram>
@@ -19471,12 +20487,13 @@ uploading your change for review.
</histogram>
<histogram name="Download.DatabaseRecordDropped"
- enum="DownloadDatabaseRecordDroppedType">
+ enum="DownloadDatabaseRecordDroppedType" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>Reason for dropping a record read in from the DB.</summary>
</histogram>
-<histogram name="Download.DatabaseRemoveDownloadsCount">
+<histogram name="Download.DatabaseRemoveDownloadsCount"
+ expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>Number of downloads removed from the history at once.</summary>
</histogram>
@@ -19603,7 +20620,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Download.FilePickerResult" enum="DownloadFilePickerResult">
+<histogram name="Download.FilePickerResult" enum="DownloadFilePickerResult"
+ expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
How the user interacts with the file chooser when doing a &quot;Save
@@ -19611,7 +20629,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Download.FileThreadBlockedTime">
+<histogram name="Download.FileThreadBlockedTime" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
The amount of time in milliseconds the file thread blocks for each set of
@@ -19619,14 +20637,14 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Download.FileThreadReceiveBuffers">
+<histogram name="Download.FileThreadReceiveBuffers" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
The number of buffers in a call to DownloadManager::UpdateDownload.
</summary>
</histogram>
-<histogram name="Download.FirstOpenTime" units="ms">
+<histogram name="Download.FirstOpenTime" units="ms" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
The time between a download completing and the file being opened for the
@@ -19729,7 +20747,7 @@ uploading your change for review.
</histogram>
<histogram name="Download.InterruptedUnknownSize"
- enum="DownloadInterruptedUnknownSizeType">
+ enum="DownloadInterruptedUnknownSizeType" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
True if the size of an interrupted download is unknown, false if it is
@@ -19838,7 +20856,7 @@ uploading your change for review.
</histogram>
<histogram name="Download.MapWinShErrorAccessDenied"
- enum="SpecialShFileOperationCodes">
+ enum="SpecialShFileOperationCodes" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
Windows error that produced a DOWNLOAD_INTERRUPT_REASON_ACCESS_DENIED result
@@ -19847,7 +20865,7 @@ uploading your change for review.
</histogram>
<histogram name="Download.MapWinShErrorFileFailed"
- enum="SpecialShFileOperationCodes">
+ enum="SpecialShFileOperationCodes" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
Windows error that produced a DOWNLOAD_INTERRUPT_REASON_FILE_FAILED result
@@ -19856,7 +20874,7 @@ uploading your change for review.
</histogram>
<histogram name="Download.MapWinShErrorTransientError"
- enum="SpecialShFileOperationCodes">
+ enum="SpecialShFileOperationCodes" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
Windows error that produced a DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR
@@ -19864,7 +20882,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Download.OnChanged">
+<histogram name="Download.OnChanged" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
Percentage of DownloadItem::Observer::OnDownloadUpdated events that
@@ -19894,7 +20912,7 @@ uploading your change for review.
</histogram>
<histogram name="Download.OriginStateOnFullResumption"
- enum="DownloadOriginStateOnResumption">
+ enum="DownloadOriginStateOnResumption" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
Changes observed when a response is received for a full download resumption
@@ -19903,7 +20921,7 @@ uploading your change for review.
</histogram>
<histogram name="Download.OriginStateOnPartialResumption"
- enum="DownloadOriginStateOnResumption">
+ enum="DownloadOriginStateOnResumption" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
Changes observed when a response is received for a partial (byte-range)
@@ -20030,7 +21048,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Download.ResourceHandlerBlockedPercentage" units="%">
+<histogram name="Download.ResourceHandlerBlockedPercentage" units="%"
+ expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
The percentage of the lifetime of the DownloadResourceHandler for which it
@@ -20344,7 +21363,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Download.ShelfInProgressSizeOnAutoClose">
+<histogram name="Download.ShelfInProgressSizeOnAutoClose"
+ expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
The number of download items in progress on the shelf when it closes
@@ -20352,7 +21372,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Download.ShelfInProgressSizeOnUserClose">
+<histogram name="Download.ShelfInProgressSizeOnUserClose"
+ expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
The number of download items in progress on the shelf when the user closes
@@ -20360,14 +21381,14 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Download.ShelfSizeOnAutoClose">
+<histogram name="Download.ShelfSizeOnAutoClose" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
The number of download items on the shelf when it closes automatically.
</summary>
</histogram>
-<histogram name="Download.ShelfSizeOnUserClose">
+<histogram name="Download.ShelfSizeOnUserClose" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
The number of download items on the shelf when the user closes it.
@@ -20452,12 +21473,13 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Download.Time" units="ms">
+<histogram name="Download.Time" units="ms" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>Time between the start of a download and its completion.</summary>
</histogram>
-<histogram name="Download.TimeToRenameFailureAfterInitialFailure" units="ms">
+<histogram name="Download.TimeToRenameFailureAfterInitialFailure" units="ms"
+ expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
Time elapsed until a retried download file rename operation failed for the
@@ -20465,7 +21487,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Download.TimeToRenameSuccessAfterInitialFailure" units="ms">
+<histogram name="Download.TimeToRenameSuccessAfterInitialFailure" units="ms"
+ expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
Time elapsed until a retried download file rename operation succeeded after
@@ -20561,8 +21584,18 @@ uploading your change for review.
<summary>Status of drive cache metadata database open.</summary>
</histogram>
-<histogram name="Drive.DirectoryFeedLoadTime" units="ms">
- <owner>joshwoodward@google.com</owner>
+<histogram name="Drive.DeltaFeedLoadTime" units="ms" expires_after="2019-01-01">
+ <owner>weifangsun@chromium.org</owner>
+ <owner>sashab@chromium.org</owner>
+ <summary>
+ Time spent to load the delta change list information from the server.
+ </summary>
+</histogram>
+
+<histogram name="Drive.DirectoryFeedLoadTime" units="ms"
+ expires_after="2019-01-01">
+ <owner>weifangsun@chromium.org</owner>
+ <owner>sashab@chromium.org</owner>
<summary>
Time spent to load the list of files in a single directory from Google Drive
server.
@@ -20626,8 +21659,9 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Drive.FullFeedLoadTime" units="ms">
- <owner>joshwoodward@google.com</owner>
+<histogram name="Drive.FullFeedLoadTime" units="ms" expires_after="2019-01-01">
+ <owner>weifangsun@chromium.org</owner>
+ <owner>sashab@chromium.org</owner>
<summary>
Time spent to load the entire file system information from the server
</summary>
@@ -20737,9 +21771,11 @@ uploading your change for review.
incremental searches are performed for &quot;f&quot;, &quot;fa&quot;, and
&quot;faq&quot; respectively.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -21265,6 +22301,10 @@ uploading your change for review.
</histogram>
<histogram name="EmbeddedWorkerInstance.Start.StartMessageLatency" units="ms">
+ <obsolete>
+ Removed June 2018 (M69). Replaced with
+ ServiceWorker.StartTiming.SentStartWorkerToReceivedStartWorker.
+ </obsolete>
<owner>falken@chromium.org</owner>
<summary>
The time between the browser sending a &quot;start a service worker&quot;
@@ -21278,6 +22318,10 @@ uploading your change for review.
<histogram name="EmbeddedWorkerInstance.Start.StartMessageLatency.Type"
enum="CrossProcessTimeDelta">
+ <obsolete>
+ Removed June 2018 (M69). Replaced with
+ ServiceWorker.StartTiming.ClockConsistency.
+ </obsolete>
<owner>falken@chromium.org</owner>
<summary>
See EmbeddedWorkerInstance.Start.StartMessageLatency. Describes the outcome
@@ -21286,6 +22330,10 @@ uploading your change for review.
</histogram>
<histogram name="EmbeddedWorkerInstance.Start.TimeToEvaluateScript" units="ms">
+ <obsolete>
+ Removed July 2018 (M69). Replaced with
+ ServiceWorker.StartTiming.ScriptEvaluationStartToScriptEvaluationEnd.
+ </obsolete>
<owner>falken@chromium.org</owner>
<summary>
The time taken for initial evaluation of the service worker script.
@@ -21296,6 +22344,12 @@ uploading your change for review.
</histogram>
<histogram name="EmbeddedWorkerInstance.Start.TimeToLoad.HttpCache" units="ms">
+ <obsolete>
+ Removed June 2018 (M69). This depended on the URLRequestJob code path, which
+ won't be taken with S13nServiceWorker/NetworkService. If we want this again,
+ it can be logged from ServiceWorkerScriptLoader or in Blink directly using
+ Resource Timing.
+ </obsolete>
<owner>falken@chromium.org</owner>
<summary>
The time taken to load a new (not installed) service worker, when it came
@@ -21305,11 +22359,19 @@ uploading your change for review.
<histogram name="EmbeddedWorkerInstance.Start.TimeToLoad.InstalledScript"
units="ms">
+ <obsolete>
+ Removed June 2018 (M69). This path is no longer taken since service worker
+ installed script manager is used for installed scripts.
+ </obsolete>
<owner>falken@chromium.org</owner>
<summary>The time taken to load an installed service worker.</summary>
</histogram>
<histogram name="EmbeddedWorkerInstance.Start.TimeToLoad.Network" units="ms">
+ <obsolete>
+ Removed June 2018 (M69), see note in
+ EmbeddedWorkerInstance.Start.TimeToLoad.HttpCache.
+ </obsolete>
<owner>falken@chromium.org</owner>
<summary>
The time taken to load a new (not installed) service worker, when it came
@@ -21318,6 +22380,10 @@ uploading your change for review.
</histogram>
<histogram name="EmbeddedWorkerInstance.Start.TimeToSendStartWorker" units="ms">
+ <obsolete>
+ Removed July 2018 (M69). Replaced with
+ ServiceWorker.StartTiming.StartToSentStartWorker.
+ </obsolete>
<owner>falken@chromium.org</owner>
<summary>
The time taken between deciding to start a worker and sending the start
@@ -21326,6 +22392,10 @@ uploading your change for review.
</histogram>
<histogram name="EmbeddedWorkerInstance.Start.TimeToStartThread" units="ms">
+ <obsolete>
+ Removed July 2018 (M69). Replaced with
+ ServiceWorker.StartTiming.ReceivedStartWorkerToScriptEvaluationStart.
+ </obsolete>
<owner>falken@chromium.org</owner>
<summary>
The time taken to start the service worker thread. Specifically, the time
@@ -21336,6 +22406,10 @@ uploading your change for review.
</histogram>
<histogram name="EmbeddedWorkerInstance.Start.TimeToURLJob" units="ms">
+ <obsolete>
+ Removed June 2018 (M69). This path is no longer taken since service worker
+ installed script manager is used for installed scripts.
+ </obsolete>
<owner>falken@chromium.org</owner>
<summary>
The round-trip time between asking the renderer process to start a worker
@@ -21346,6 +22420,9 @@ uploading your change for review.
<histogram name="EmbeddedWorkerInstance.Start.WaitedForRendererSetup"
enum="BooleanWaited">
+ <obsolete>
+ Removed June 2018 (M69).
+ </obsolete>
<owner>falken@chromium.org</owner>
<summary>
Indicates if Blink was not initialized by the time the browser sent a
@@ -21360,6 +22437,9 @@ uploading your change for review.
<histogram name="EmbeddedWorkerInstance.Start.WaitedForRendererSetup.Time"
units="ms">
+ <obsolete>
+ Removed June 2018 (M69).
+ </obsolete>
<owner>falken@chromium.org</owner>
<summary>
Recorded when EmbeddedWorkerInstance.Start.WaitedForRendererSetup is true.
@@ -21404,6 +22484,15 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Enterprise.ActiveDirectoryJoin"
+ enum="ActiveDirectoryDomainJoinType">
+ <owner>rsorokin@chromium.org</owner>
+ <summary>
+ The way device is joined to the Active Directory domain. This will be
+ recorded during successful enterprise enrollment and domain join.
+ </summary>
+</histogram>
+
<histogram name="Enterprise.AppRestrictionLoadTime" units="ms">
<owner>aberent@chromium.org</owner>
<summary>
@@ -21651,12 +22740,52 @@ uploading your change for review.
</summary>
</histogram>
+<histogram
+ name="Enterprise.MachineLevelUserCloudPolicyEnrollment.RequestFailureTime"
+ units="ms">
+ <owner>rogerta@chromium.org</owner>
+ <summary>
+ Time since the enrollment request was made until an error is returned from
+ the server.
+ </summary>
+</histogram>
+
+<histogram
+ name="Enterprise.MachineLevelUserCloudPolicyEnrollment.RequestSuccessTime"
+ units="ms">
+ <owner>rogerta@chromium.org</owner>
+ <summary>
+ Time since the enrollment request was made until a successful enrollment
+ response is returned from the server.
+ </summary>
+</histogram>
+
<histogram name="Enterprise.MachineLevelUserCloudPolicyEnrollment.Result"
enum="MachineLevelUserCloudPolicyEnrollmentResult">
<owner>zmin@chromium.org</owner>
<summary>The result of machine level user cloud policy enrollment.</summary>
</histogram>
+<histogram
+ name="Enterprise.MachineLevelUserCloudPolicyEnrollment.StartupDialog"
+ enum="MachineLevelUserCloudPolicyEnrollmentStartupDialog">
+ <owner>rogerta@chromium.org</owner>
+ <summary>
+ Records whether the machine level user cloud policy enrollment dialog is
+ shown to the user and the action they took.
+ </summary>
+</histogram>
+
+<histogram
+ name="Enterprise.MachineLevelUserCloudPolicyEnrollment.StartupDialogTime"
+ units="ms">
+ <owner>rogerta@chromium.org</owner>
+ <summary>
+ The length of time the machine level user cloud policy enrollment dialog was
+ visible to the user.
+ </summary>
+</histogram>
+
<histogram name="Enterprise.ONC.PolicyValidation" enum="BooleanSuccess">
<owner>mnissler@chromium.org</owner>
<summary>Result of the OpenNetworkConfiguration policy validation.</summary>
@@ -22010,6 +23139,15 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="EnterpriseCheck.InvalidJsonPolicies" enum="EnterprisePolicies">
+ <owner>olsen@chromium.org</owner>
+ <summary>
+ A set of policy rules that failed validation due to unparsable JSON, or JSON
+ that did not match the schema. This validation happens on start-up and when
+ the policy has changed.
+ </summary>
+</histogram>
+
<histogram name="EnterpriseCheck.InvalidPolicies" enum="EnterprisePolicies">
<owner>mnissler@chromium.org</owner>
<summary>
@@ -22126,6 +23264,12 @@ uploading your change for review.
starting to process it.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -22236,6 +23380,12 @@ uploading your change for review.
compositor thread.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -22248,6 +23398,12 @@ uploading your change for review.
compositor thread.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -22260,6 +23416,12 @@ uploading your change for review.
on the compositor thread.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23078,9 +24240,11 @@ uploading your change for review.
swap. If no swap was induced by the event, no recording is made. Only
recorded for key presses.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23090,9 +24254,11 @@ uploading your change for review.
Time between the OS receiving a mouse event and the resulting GPU frame
swap. If no swap was induced by the event, no recording is made.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23104,6 +24270,12 @@ uploading your change for review.
Event.Latency.HitTestRecusrive.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23114,13 +24286,27 @@ uploading your change for review.
the AllowChildFrameContent flag is set. See also Event.Latency.HitTest.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
<histogram name="Event.Latency.OS" units="microseconds">
<owner>tdresser@chromium.org</owner>
Team: input-dev@chromium.org.
- <summary>Time between input event received by OS and sent to Chrome.</summary>
+ <summary>
+ Time between input event received by OS and sent to Chrome.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="Event.Latency.QueueingTime.KeyPressDefaultAllowed" units="ms">
@@ -23302,6 +24488,12 @@ uploading your change for review.
this metric includes the first GSU of every scrolling sequence as well.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23316,6 +24508,12 @@ uploading your change for review.
includes the first GSU of every scrolling sequence as well.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23371,6 +24569,12 @@ uploading your change for review.
swap finishes.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23383,6 +24587,12 @@ uploading your change for review.
by suffix) and before renderer starts to swap.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23409,6 +24619,12 @@ uploading your change for review.
the ScrollUpdate gesture event, no recording is made.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23429,8 +24645,8 @@ uploading your change for review.
Warning: This metric may include reports from clients with low-resolution
clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
will cause this metric to have an abnormal distribution. When considering
- revising this histogram, see UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for
- the solution.
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23451,8 +24667,8 @@ uploading your change for review.
Warning: This metric may include reports from clients with low-resolution
clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
will cause this metric to have an abnormal distribution. When considering
- revising this histogram, see UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for
- the solution.
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23466,6 +24682,12 @@ uploading your change for review.
sequence. If no swap was induced by the event, no recording is made.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23490,6 +24712,12 @@ uploading your change for review.
swap finishes.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23502,6 +24730,12 @@ uploading your change for review.
by suffix) and before renderer starts to swap.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23528,6 +24762,12 @@ uploading your change for review.
the ScrollBegin gesture event, no recording is made.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23548,8 +24788,8 @@ uploading your change for review.
Warning: This metric may include reports from clients with low-resolution
clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
will cause this metric to have an abnormal distribution. When considering
- revising this histogram, see UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for
- the solution.
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23570,8 +24810,8 @@ uploading your change for review.
Warning: This metric may include reports from clients with low-resolution
clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
will cause this metric to have an abnormal distribution. When considering
- revising this histogram, see UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for
- the solution.
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23585,6 +24825,12 @@ uploading your change for review.
sequence. If no swap was induced by the event, no recording is made.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23801,6 +25047,12 @@ uploading your change for review.
source induced frame and the swap finishes.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23812,6 +25064,12 @@ uploading your change for review.
main/impl thread (specified by suffix) and before renderer starts to swap.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23858,6 +25116,12 @@ uploading your change for review.
recording is made.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23877,8 +25141,8 @@ uploading your change for review.
Warning: This metric may include reports from clients with low-resolution
clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
will cause this metric to have an abnormal distribution. When considering
- revising this histogram, see UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for
- the solution.
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23899,8 +25163,8 @@ uploading your change for review.
Warning: This metric may include reports from clients with low-resolution
clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
will cause this metric to have an abnormal distribution. When considering
- revising this histogram, see UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for
- the solution.
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23914,6 +25178,12 @@ uploading your change for review.
scrolling sequence is excluded from this metric.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23952,6 +25222,12 @@ uploading your change for review.
source induced frame and the swap finishes.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -23963,6 +25239,12 @@ uploading your change for review.
main/impl thread (specified by suffix) and before renderer starts to swap.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -24010,6 +25292,12 @@ uploading your change for review.
from this metric.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -24029,8 +25317,8 @@ uploading your change for review.
Warning: This metric may include reports from clients with low-resolution
clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
will cause this metric to have an abnormal distribution. When considering
- revising this histogram, see UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for
- the solution.
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -24051,8 +25339,8 @@ uploading your change for review.
Warning: This metric may include reports from clients with low-resolution
clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
will cause this metric to have an abnormal distribution. When considering
- revising this histogram, see UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for
- the solution.
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -24066,6 +25354,12 @@ uploading your change for review.
scrolling sequence is excluded from this metric.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -24302,6 +25596,12 @@ uploading your change for review.
forcing events non-blocking during fling.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -24331,6 +25631,12 @@ uploading your change for review.
potential benefit of using passive events listeners.
Team: input-dev@chromium.org.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -24405,6 +25711,17 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Event.Touch.GestureTarget" enum="BrowserGestureActionType">
+ <owner>kuscher@google.com</owner>
+ <owner>rbyers@chromium.org</owner>
+ <summary>
+ The gesture-events recognized and dispatched for UI components owned by the
+ browser. This histogram was created as part of separating gesture events
+ between the browser and Ash (crbug.com/826476). The enums are extracted from
+ Ash.GestureTarget.
+ </summary>
+</histogram>
+
<histogram name="Event.Touch.TargetAndDispatchResult"
enum="TouchTargetAndDispatchResultType">
<obsolete>
@@ -24762,6 +26079,9 @@ uploading your change for review.
</histogram>
<histogram name="Event.VizHitTest.AggregateTime" units="ms">
+ <obsolete>
+ Deprecated as of 07/2018. Replaced with Event.VizHitTest.AggregateTimeUs.
+ </obsolete>
<owner>riajiang@chromium.org</owner>
<owner>event-targeting@chromium.org</owner>
<summary>
@@ -24770,6 +26090,15 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Event.VizHitTest.AggregateTimeUs" units="microseconds">
+ <owner>riajiang@chromium.org</owner>
+ <owner>event-targeting@chromium.org</owner>
+ <summary>
+ Tracks how long it takes for HitTestAggregator to aggregate hit-test data
+ received from all clients, in microseconds.
+ </summary>
+</histogram>
+
<histogram name="Event.VizHitTest.HitTestRegions" units="regions">
<owner>riajiang@chromium.org</owner>
<owner>event-targeting@chromium.org</owner>
@@ -24779,6 +26108,9 @@ uploading your change for review.
</histogram>
<histogram name="Event.VizHitTest.TargetTime" units="ms">
+ <obsolete>
+ Deprecated as of 07/2018. Replaced with Event.VizHitTest.TargetTimeUs.
+ </obsolete>
<owner>riajiang@chromium.org</owner>
<owner>event-targeting@chromium.org</owner>
<summary>
@@ -24787,7 +26119,19 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Event.VizHitTest.TargetTimeUs" units="microseconds">
+ <owner>riajiang@chromium.org</owner>
+ <owner>event-targeting@chromium.org</owner>
+ <summary>
+ Tracks how long it takes for HitTestQuery to find a target on a given
+ location, in microseconds.
+ </summary>
+</histogram>
+
<histogram name="Event.VizHitTest.TransformTime" units="ms">
+ <obsolete>
+ Deprecated as of 07/2018. Replaced with Event.VizHitTest.TransformTimeUs.
+ </obsolete>
<owner>riajiang@chromium.org</owner>
<owner>event-targeting@chromium.org</owner>
<summary>
@@ -24796,6 +26140,15 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Event.VizHitTest.TransformTimeUs" units="microseconds">
+ <owner>riajiang@chromium.org</owner>
+ <owner>event-targeting@chromium.org</owner>
+ <summary>
+ Tracks how long it takes for HitTestQuery to transform a location to a given
+ target's coordinate space, in microseconds.
+ </summary>
+</histogram>
+
<histogram name="ExclusiveAccess.BubbleReshowsPerSession.Fullscreen"
units="reshows">
<owner>mgiuca@chromium.org</owner>
@@ -25286,9 +26639,11 @@ uploading your change for review.
The time taken in computation (hashing actual bytes read and comparing
against expected computed hashes values) during an extension resource load.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -25524,9 +26879,11 @@ uploading your change for review.
the binding.js module. This is a strict subset of
Extensions.ApiBindingGenerationTime, which includes this work and more.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -25691,9 +27048,11 @@ uploading your change for review.
The elapsed time to create a new full instance of an extension API's
bindings using native bindings.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -25704,9 +27063,11 @@ uploading your change for review.
The elapsed time to update the bindings for a new or existing v8::Context.
The suffix indicates which type of context the bindings are for.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -25855,6 +27216,69 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Extensions.ContentVerification.ComputedHashesInitTime"
+ units="ms" expires_after="2019-11-30">
+ <owner>lazyboy@chromium.org</owner>
+ <owner>rdevlin.cronin@chromium.org</owner>
+ <summary>
+ How long a successful initialization of computed_hashes.json file takes.
+ Recorded when content verification needs to retrieve block hashes.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ContentVerification.ComputedHashesReadResult"
+ enum="BooleanSuccess" expires_after="2019-11-30">
+ <owner>lazyboy@chromium.org</owner>
+ <owner>rdevlin.cronin@chromium.org</owner>
+ <summary>
+ Whether or not computed_hashes.json file read and parse succeeded. Recorded
+ when content verification needs to retrieve block hashes.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ContentVerification.FetchResult"
+ enum="BooleanSuccess" expires_after="2019-11-30">
+ <owner>lazyboy@chromium.org</owner>
+ <owner>rdevlin.cronin@chromium.org</owner>
+ <summary>
+ Whether or not fetching verified_contents.json succeeded. Recorded when the
+ file wasn't available locally and we needed to fetch it from network.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ContentVerification.ReadContentHashTime" units="ms"
+ expires_after="2019-11-30">
+ <owner>lazyboy@chromium.org</owner>
+ <owner>rdevlin.cronin@chromium.org</owner>
+ <summary>
+ Time spent by ContentVerifier for a request to create a ContentHash
+ instance. Recorded during an extension load completion or during an on
+ demand content verification that was triggered by ContentVerifyJob.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ContentVerification.VerifiedContentsInitResult"
+ enum="BooleanSuccess" expires_after="2019-11-30">
+ <owner>lazyboy@chromium.org</owner>
+ <owner>rdevlin.cronin@chromium.org</owner>
+ <summary>
+ Whether or not initializing verified_contents.json succeeded. Recorded
+ during an extension load completion or during an on demand content
+ verification that was triggered by ContentVerifyJob.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ContentVerification.VerifiedContentsInitTime"
+ units="ms" expires_after="2019-11-30">
+ <owner>lazyboy@chromium.org</owner>
+ <owner>rdevlin.cronin@chromium.org</owner>
+ <summary>
+ How long a successful initialization of verified_contents.json file takes.
+ Recorded if Extensions.ContentVerification.VerifiedContentsInitResult = true
+ was recorded.
+ </summary>
+</histogram>
+
<histogram name="Extensions.CorruptExtensionBecameDisabled">
<owner>asargent@chromium.org</owner>
<summary>
@@ -26084,6 +27508,29 @@ uploading your change for review.
</histogram>
<histogram
+ name="Extensions.DeclarativeNetRequest.PageWhitelistingInitiatorCheck"
+ enum="PageWhitelistingInitiatorCheck" expires_after="2019-06-30">
+ <owner>karandeepb@chromium.org</owner>
+ <owner>lazyboy@chromium.org</owner>
+ <summary>
+ Describes the different cases pertaining to initiator checks used by the
+ Declarative Net Request Page Whitelisting API. Emitted whenever an extension
+ ruleset is evaluated for a main frame sub-resource request.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.DeclarativeNetRequest.RulesetReindexSuccessful"
+ enum="BooleanSuccess" expires_after="2019-06-30">
+ <owner>karandeepb@chromium.org</owner>
+ <owner>lazyboy@chromium.org</owner>
+ <summary>
+ Indicates whether reindexing of the Declarative Net Request ruleset was
+ successful. Called whenever the JSON ruleset for an extension is reindexed,
+ e.g. on ruleset corruption.
+ </summary>
+</histogram>
+
+<histogram
name="Extensions.DeclarativeNetRequest.ShouldBlockRequestTime.AllExtensions"
units="ms">
<obsolete>
@@ -26509,9 +27956,11 @@ uploading your change for review.
parsing all the different extension manifest keys and initializating the
associated manifest data.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -26630,6 +28079,15 @@ uploading your change for review.
<summary>An extension has been uninstalled.</summary>
</histogram>
+<histogram name="Extensions.ExtensionUpdaterRawUpdateCalls" units="extensions">
+ <owner>mxnguyen@chromium.org</owner>
+ <summary>
+ The number of extensions that are checked for update. This number is emitted
+ right before the extensions are split between the current extension updater
+ and the unified extension updater (if used).
+ </summary>
+</histogram>
+
<histogram name="Extensions.ExtensionUpdaterUpdateCalls" units="extensions">
<owner>mxnguyen@chromium.org</owner>
<summary>
@@ -26665,7 +28123,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Extensions.ExternalItemState" enum="ExternalItemState">
+<histogram name="Extensions.ExternalItemState" enum="ExternalItemState"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The number of sideloaded apps/extensions loaded on startup grouped by
@@ -26748,16 +28207,24 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Extensions.ForceInstalledTimedOutCount">
+<histogram name="Extensions.ForceInstalledTimedOutAndNotInstalledCount">
<owner>poromov@chromium.org</owner>
<summary>
Number of enterprise policy forced extensions that are not installed after 5
- minutes timeout.
+ minutes if at least one of policy forced extensions is not yet enabled.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.ForceInstalledTimedOutCount">
+ <owner>poromov@chromium.org</owner>
+ <summary>
+ Number of enterprise policy forced extensions that are not enabled after 5
+ minutes timeout, while might be already installed.
</summary>
</histogram>
<histogram name="Extensions.FromWebstoreInconsistency"
- enum="ExtensionFromWebstoreInconcistencyEnum">
+ enum="ExtensionFromWebstoreInconcistencyEnum" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Number of apps/extensions loaded on startup with an inconsistent &quot;from
@@ -27385,6 +28852,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Extensions.LockedFullscreenStateRequest"
+ enum="LockedFullscreenState" expires_after="2019-07-01">
+ <owner>isandrk@chromium.org</owner>
+ <owner>jhastings@chromium.org</owner>
+ <summary>
+ Records requests to enter or exit locked fullscreen mode through extension
+ APIs. Used only on Chrome OS.
+ </summary>
+</histogram>
+
<histogram base="true" name="Extensions.LongInjectionTaskTime" units="ms">
<owner>ksakamoto@chromium.org</owner>
<summary>
@@ -27410,7 +28887,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Extensions.ManifestFetchFailureRetryCountOtherUrl">
+<histogram name="Extensions.ManifestFetchFailureRetryCountOtherUrl"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Number of times chrome retried to download an extension update manifest with
@@ -27434,7 +28912,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Extensions.ManifestReloadNeedsRelocalization">
+<histogram name="Extensions.ManifestReloadNeedsRelocalization"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Number of extension loads on startup where it is necessary to reload the
@@ -27442,7 +28921,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Extensions.ManifestReloadNotNeeded">
+<histogram name="Extensions.ManifestReloadNotNeeded" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Number of extension loads on startup where it is not necessary to reload the
@@ -27450,7 +28929,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Extensions.ManifestReloadUnpackedDir">
+<histogram name="Extensions.ManifestReloadUnpackedDir"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Number of extension loads on startup where it is necessary to reload the
@@ -27493,6 +28973,17 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Extensions.Messaging.IncludeChannelIdBehavior"
+ enum="ExtensionMessagingIncludeChannelIdBehavior"
+ expires_after="2018-12-01">
+ <owner>rdevlin.cronin@chromium.org</owner>
+ <owner>nharper@hromium.org</owner>
+ <summary>
+ The behavior for including the TLS channel ID in the information sent with
+ extension messaging. Recorded once per opened channel.
+ </summary>
+</histogram>
+
<histogram name="Extensions.Messaging.MessageSize" units="bytes">
<owner>redevlin.cronin@chromium.org</owner>
<summary>
@@ -28335,6 +29826,47 @@ uploading your change for review.
<summary>Time taken to load a toolstrip.</summary>
</histogram>
+<histogram name="Extensions.UnifiedExtensionUpdaterDownloadErrors"
+ enum="CombinedHttpResponseAndNetErrorCode">
+ <owner>mxnguyen@chromium.org</owner>
+ <summary>
+ Records the error codes of the unified extension updater download errors.
+ These events are triggered when the extension updater fails to download the
+ extension update package of an extension, which can happen only after the
+ updater has successfuly determined that there is an update for the
+ extension.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UnifiedExtensionUpdaterUpdateCalls"
+ units="extensions">
+ <owner>mxnguyen@chromium.org</owner>
+ <summary>
+ The number of extensions that are passed over to the unified extension
+ updater for update check. Triggered when the new extension updater starts
+ doing update check.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UnifiedExtensionUpdaterUpdateCheckErrors"
+ enum="CombinedHttpResponseAndNetErrorCode">
+ <owner>mxnguyen@chromium.org</owner>
+ <summary>
+ Records the error codes of the unified extension updater update check
+ errors. These events are triggered only when the new extension updater gets
+ an error in the update check phase.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UnifiedExtensionUpdaterUpdateResults"
+ enum="ExtensionUpdaterUpdateResult">
+ <owner>mxnguyen@chromium.org</owner>
+ <summary>
+ Records the update results of extensions in an unified extension updater
+ session, grouped by ExtensionUpdaterUpdateResult.
+ </summary>
+</histogram>
+
<histogram name="Extensions.UninstallDialogAction"
enum="ExtensionUninstallDialogAction">
<owner>rdevlin.cronin@chromium.org</owner>
@@ -28393,7 +29925,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Extensions.UpdateCheckApp">
+<histogram name="Extensions.UpdateCheckApp" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The number of legacy packaged apps and hosted apps that were checked during
@@ -28436,14 +29968,14 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Extensions.UpdateCheckPackagedApp">
+<histogram name="Extensions.UpdateCheckPackagedApp" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The number of packaged apps that were checked during an update check.
</summary>
</histogram>
-<histogram name="Extensions.UpdateCheckTheme">
+<histogram name="Extensions.UpdateCheckTheme" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The number of themes that were checked during an update check.
@@ -28463,6 +29995,25 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Extensions.UpdateManifestDuplicateEntryCount" units="entries">
+ <owner>mxnguyen@chromium.org</owner>
+ <summary>
+ Counts the number of entries with the same extension ID found in the update
+ manifest of an update check request. When the update manifest does not
+ contain any update entry for an extension ID in the update check request,
+ the count will be 0.
+ </summary>
+</histogram>
+
+<histogram name="Extensions.UpdateManifestHasProdVersionMinCounts"
+ units="extensions">
+ <owner>mxnguyen@chromium.org</owner>
+ <summary>
+ The number of prodversionmin attributes appearing in an update manifest of
+ an update check request.
+ </summary>
+</histogram>
+
<histogram name="Extensions.UpdateOnLoad">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
@@ -28490,6 +30041,17 @@ uploading your change for review.
<summary>Updates grouped by Extension::HistogramType.</summary>
</histogram>
+<histogram name="Extensions.WebRequest.InitiatorAccess" enum="InitiatorAccess"
+ expires_after="2018-12-31">
+ <owner>karandeepb@chromium.org</owner>
+ <owner>rdevlin.cronin@chromium.org</owner>
+ <summary>
+ Describes the different cases pertaining to host permissions check for the
+ initiator URL of a network request. This is emitted whenever an extension is
+ found to have access to a request url, when checked by the WebRequest API.
+ </summary>
+</histogram>
+
<histogram name="Extensions.WebRequest.ModifiedResponseHeaders"
enum="WebRequestResponseHeaderType">
<owner>rockot@chromium.org</owner>
@@ -28637,13 +30199,13 @@ uploading your change for review.
</histogram>
<histogram name="Extensions.WebstoreDownload.InterruptReason"
- enum="InterruptReason">
+ enum="InterruptReason" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>The reason a webstore download was interrupted.</summary>
</histogram>
<histogram name="Extensions.WebstoreDownload.InterruptReceivedKBytes"
- units="KB">
+ units="KB" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The number of KBytes received for a webstore download before it was
@@ -28651,7 +30213,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Extensions.WebstoreDownload.InterruptTotalKBytes" units="KB">
+<histogram name="Extensions.WebstoreDownload.InterruptTotalKBytes" units="KB"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The total expected size in KBytes of an interrupted webstore download.
@@ -28659,7 +30222,7 @@ uploading your change for review.
</histogram>
<histogram name="Extensions.WebstoreDownload.InterruptTotalSizeUnknown"
- enum="Boolean">
+ enum="Boolean" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Tracks whether the total size of an interrupted webstore download was known.
@@ -28685,7 +30248,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="ExtensionService.AddVerified" enum="BooleanSuccess">
+<histogram name="ExtensionService.AddVerified" enum="BooleanSuccess"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Records whether adding a new/updated extension to the install verifier
@@ -28694,7 +30258,7 @@ uploading your change for review.
</histogram>
<histogram name="ExtensionService.VerifyAllSuccess"
- enum="ExtensionServiceVerifyAllSuccess">
+ enum="ExtensionServiceVerifyAllSuccess" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The outcome of a call to ExtensionService::VerifyAllExtensions, whether it
@@ -28714,7 +30278,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="ExtensionSettings.ShouldDoVerificationCheck" enum="Boolean">
+<histogram name="ExtensionSettings.ShouldDoVerificationCheck" enum="Boolean"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
When loading the chrome://extensions page, this records whether we decided
@@ -28898,6 +30463,26 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Feed.Scheduler.RefreshTrigger" enum="RefreshTrigger"
+ expires_after="2019-07-11">
+ <owner>skym@chromium.org</owner>
+ <summary>
+ The scheduler watches for various triggers, which cause it to decide if a
+ refresh is currently warranted or not. This histogram is emitted when a
+ trigger causes a refresh.
+ </summary>
+</histogram>
+
+<histogram name="Feed.Scheduler.RequestBehavior" enum="RequestBehavior"
+ expires_after="2019-07-11">
+ <owner>skym@chromium.org</owner>
+ <summary>
+ When NTP is opened, the scheduler host tells the Feed library how to act, if
+ the existing content should be shown, immediately or with timeout, and if a
+ refresh request should be started.
+ </summary>
+</histogram>
+
<histogram name="Feedback.RequestSource" enum="FeedbackSource">
<owner>afakhry@chromium.org</owner>
<summary>Records the source that requested showing the feedback app.</summary>
@@ -28905,7 +30490,8 @@ uploading your change for review.
<histogram name="FileBrowser.ChangeDirectory.RootType"
enum="FileManagerRootType">
- <owner>yamaguchi@chromium.org</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: Counts the number of directory-changed events,
bucketed by the RootType of the directory newly displayed.
@@ -28914,7 +30500,8 @@ uploading your change for review.
<histogram name="FileBrowser.CloudImport.UserAction"
enum="CloudImportUserAction">
- <owner>smckay@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser - Specific actions taken by user such initiating
cloud import, canceling import, selecting a directory, or opting-in to
@@ -28923,12 +30510,14 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.Create" enum="FileDialogType">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>Chrome OS File Browser opening mode.</summary>
</histogram>
<histogram name="FileBrowser.DirectoryScan" units="ms">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: time to scan a directory. Measured on every File
Browser directory change.
@@ -28937,7 +30526,8 @@ uploading your change for review.
<histogram name="FileBrowser.DownloadDestination.IsGoogleDrive.Changed"
enum="BooleanEnabled">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Tracks whether download destination is set to a Google Drive folder when the
download destination is changed by the user in the settings page.
@@ -28946,7 +30536,8 @@ uploading your change for review.
<histogram name="FileBrowser.DownloadDestination.IsGoogleDrive.Started"
enum="BooleanEnabled">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Tracks whether download destination is set to a Google Drive folder on
startup.
@@ -28954,7 +30545,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.DownloadsCount">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: number of files and directories in the Downloads
directory (not including the contents of nested directories). Computed every
@@ -28963,7 +30555,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.FolderShortcut.Add">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: this is recorded when the user adds a folder
shortcut.
@@ -28971,7 +30564,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.FolderShortcut.Count">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: number of saved folder shorcuts. This is recorded
when the Files app is launched.
@@ -28979,7 +30573,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.FolderShortcut.Navigate">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: this is recorded when the user clicks or selects a
folder shortcut and is navigated to the target folder.
@@ -28987,7 +30582,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.FolderShortcut.Remove">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: this is recorded when the user removes a folder
shortcut.
@@ -28999,7 +30595,8 @@ uploading your change for review.
<obsolete>
The bug which the UMA was investigating got fixed.
</obsolete>
- <owner>hirono@chromium.org</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: time from the SuspendDone event to the DiskRemoved
event. The UMA is added temporarily for crbug.com/433734.
@@ -29011,7 +30608,8 @@ uploading your change for review.
<obsolete>
The bug which the UMA was investigating got fixed.
</obsolete>
- <owner>hirono@chromium.org</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: time from the DiskRemoved event to the Suspend
event. The UMA is added temporarily for crbug.com/433734.
@@ -29019,7 +30617,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.Load" units="ms">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser is an built-in extension without a background page.
Its main.html file is loaded every time the user opens a File Browser tab or
@@ -29030,7 +30629,8 @@ uploading your change for review.
<histogram name="FileBrowser.Location.OnEntryExpandedOrCollapsed.NonTopLevel"
enum="FileManagerRootType">
- <owner>sashab@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Files App: The locations (root types) of non-top-level entries
when they are expanded or collapsed (expand icon clicked) in the directory
@@ -29040,7 +30640,8 @@ uploading your change for review.
<histogram name="FileBrowser.Location.OnEntryExpandedOrCollapsed.TopLevel"
enum="FileManagerRootType">
- <owner>sashab@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Files App: The locations (root types) of top-level entries (root
entries) when they are expanded or collapsed (expand icon clicked) in the
@@ -29050,7 +30651,8 @@ uploading your change for review.
<histogram name="FileBrowser.Location.OnEntrySelected.NonTopLevel"
enum="FileManagerRootType">
- <owner>sashab@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Files App: The locations (root types) of non-top-level entries
when they are clicked in the directory tree.
@@ -29059,7 +30661,8 @@ uploading your change for review.
<histogram name="FileBrowser.Location.OnEntrySelected.TopLevel"
enum="FileManagerRootType">
- <owner>sashab@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Files App: The locations (root types) of top-level entries (root
entries) when they are clicked in the directory tree.
@@ -29068,13 +30671,25 @@ uploading your change for review.
<histogram name="FileBrowser.MenuItemSelected" enum="FileManagerMenuCommands">
<owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Files App: The commands selected in the menu by the files app.
</summary>
</histogram>
+<histogram name="FileBrowser.MountCrostiniContainer" units="ms"
+ expires_after="2019-05-30">
+ <owner>joelhockey@google.com</owner>
+ <owner>sashab@google.com</owner>
+ <summary>
+ Chrome OS File Browser: time to start and mount the crostini container in
+ order to show Linux Files.
+ </summary>
+</histogram>
+
<histogram name="FileBrowser.OpenFiles.RootType" enum="FileManagerRootType">
- <owner>fukino@chromium.org</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: The locations (root types) of files which are opened
by the file picker.
@@ -29085,12 +30700,14 @@ uploading your change for review.
<obsolete>
Deprecated 4/2013, and replaced by FileBrowser.ViewingFileType.
</obsolete>
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>File types that were tried to be opened through browser.</summary>
</histogram>
<histogram name="FileBrowser.PhotoEditor.DisplayTime" units="ms">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Photo Editor: time to display an image. Measured from the moment
the user selected the image till the moment it is displayed (not counting
@@ -29099,35 +30716,41 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.PhotoEditor.FileType" enum="PhotoEditorFileType">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>Chrome OS Photo Editor: the type of the file opened.</summary>
</histogram>
<histogram name="FileBrowser.PhotoEditor.LoadMode" enum="PhotoEditorLoadMode">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>Chrome OS Photo Editor: the way the image has been loaded.</summary>
</histogram>
<histogram name="FileBrowser.PhotoEditor.LoadTime" units="ms">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>Chrome OS Photo Editor: time to load an image from a file.</summary>
</histogram>
<histogram name="FileBrowser.PhotoEditor.SaveResult"
enum="PhotoEditorSaveResult">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Photo Editor: the result of a file save operation.
</summary>
</histogram>
<histogram name="FileBrowser.PhotoEditor.SaveTime" units="ms">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>Chrome OS Photo Editor: time to save an image to a file.</summary>
</histogram>
<histogram name="FileBrowser.PhotoEditor.Size.MB" units="MBytes">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Photo Editor: size of an image file in megabytes. Measured on
every image load.
@@ -29135,7 +30758,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.PhotoEditor.Size.MPix" units="MPixels">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Photo Editor: size of an image in megapixels. Measured on every
image load.
@@ -29143,12 +30767,14 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.PhotoEditor.Tool" enum="PhotoEditorToolType">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>Chrome OS Photo Editor: the button which the user clicked.</summary>
</histogram>
<histogram name="FileBrowser.PhotoImport.Action" enum="ExternalDeviceAction">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Photo Import flow: action chosen in the Action Choice dialog for
the external device.
@@ -29156,7 +30782,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.PhotoImport.ImportCount">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Photo Import flow: the number of photos imported. Measured on
every successfull import operation.
@@ -29164,7 +30791,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.PhotoImport.ImportPercentage" units="%">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Photo Import flow: the percent of photos imported among all the
photos on the device. Measured on every successfull import operation.
@@ -29172,7 +30800,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.PhotoImport.Load" units="ms">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Photo Import flow: time to load the action dialog. Measured
between the moment window appears and the moment user see all available
@@ -29181,42 +30810,49 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.PhotoImport.Scan" units="ms">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Photo Import flow: time to scan the external device.
</summary>
</histogram>
<histogram name="FileBrowser.QuickView.DialogType" enum="FileDialogType">
- <owner>oka@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
File dialog type (e.g. Full page, Save as file) when quick view is launched.
</summary>
</histogram>
<histogram name="FileBrowser.QuickView.FileType" enum="ViewFileType">
- <owner>oka@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>File types that were tried to be opened with quick view.</summary>
</histogram>
<histogram name="FileBrowser.QuickView.FileTypeOnLaunch" enum="ViewFileType">
- <owner>oka@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>File types that were selected when quick view is launched.</summary>
</histogram>
<histogram name="FileBrowser.QuickView.VolumeType" enum="FileManagerVolumeType">
- <owner>oka@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>The volume type where quick view is opened.</summary>
</histogram>
<histogram name="FileBrowser.QuickView.WayToOpen"
enum="FileManagerQuickViewWayToOpen">
- <owner>oka@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>How quick view was opened.</summary>
</histogram>
<histogram name="FileBrowser.Recent.LoadArcMedia" units="ms">
- <owner>nya@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Time to load a recently modified file list from Media Views. It is triggered
when the user opens or reloads Recent view in the Files app.
@@ -29224,7 +30860,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.Recent.LoadDownloads" units="ms">
- <owner>nya@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Time to load a recently modified file list from Downloads. It is triggered
when the user opens or reloads Recent view in the Files app.
@@ -29232,7 +30869,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.Recent.LoadDrive" units="ms">
- <owner>nya@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Time to load a recently modified file list from Drive. It is triggered when
the user opens or reloads Recent view in the Files app.
@@ -29240,7 +30878,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.Recent.LoadTotal" units="ms">
- <owner>nya@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Time to load a recently modified file list from all sources. It is triggered
when the user opens or reloads Recent view in the Files app.
@@ -29249,7 +30888,8 @@ uploading your change for review.
<histogram name="FileBrowser.SuggestApps.CloseDialog"
enum="SuggestAppsDialogCloseReason">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: the reason why the suggest apps dialog was closed.
</summary>
@@ -29257,7 +30897,8 @@ uploading your change for review.
<histogram name="FileBrowser.SuggestApps.Install"
enum="SuggestAppsDialogInstall">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: whether the Webstore item user selected was
successfully installed or not.
@@ -29265,7 +30906,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.SuggestApps.Load" enum="SuggestAppsDialogLoad">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: whether the initialization of the dialog succeeded
or not.
@@ -29273,7 +30915,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.SuggestApps.LoadTime" units="ms">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: time to load the suggest apps dialog. Measured
between the moment window appears and the moment all the contents in the
@@ -29281,8 +30924,21 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="FileBrowser.TeamDrivesCount" units="Team Drives"
+ expires_after="M75">
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
+ <summary>
+ Chrome OS File Browser: number of Team Drives a user has available in the
+ Files app. Computed every time the File Browser is opened (including file
+ picker dialogs). NOTE: This data is biased towards users that use the Files
+ App more often.
+ </summary>
+</histogram>
+
<histogram name="FileBrowser.ToggleFileListType" enum="FileManagerListType">
<owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS Files App: Recorded when the Grid View/List View toggle menu icon
is selected.
@@ -29290,7 +30946,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.ViewingFileType" enum="ViewFileType">
- <owner>joshwoodward@google.com</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
File types that were tried to be viewed through browser. This is recorded
when the user tries to view a file from the Files app.
@@ -29298,7 +30955,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.ViewingRootType" enum="FileManagerRootType">
- <owner>nya@chromium.org</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: The locations (root types) of files which are opened
in stand-alone mode. This does not include files opened in file picker mode.
@@ -29306,14 +30964,16 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.ViewingTaskType" enum="FileManagerTaskType">
- <owner>nya@chromium.org</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: The type of the handler to be used to open files.
</summary>
</histogram>
<histogram name="FileBrowser.VolumeType" enum="FileManagerVolumeType">
- <owner>kinaba@chromium.org</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: counts the number of times volumes are mounted for
each volume type.
@@ -29321,7 +30981,8 @@ uploading your change for review.
</histogram>
<histogram name="FileBrowser.ZipFileTask" enum="FileManagerZipHandlerType">
- <owner>yamaguchi@chromium.org</owner>
+ <owner>sashab@chromium.org</owner>
+ <owner>slangley@chromium.org</owner>
<summary>
Chrome OS File Browser: counts the number of times ZIP file was opened or
created, categorized by component extensions and its operation types.
@@ -29381,7 +31042,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="FileSystem.PersistentOriginsCount">
+<histogram name="FileSystem.PersistentOriginsCount" expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>
Number of origins that have persistent filesystem. Measured when the Quota
@@ -29391,7 +31052,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="FileSystem.TemporaryOriginsCount">
+<histogram name="FileSystem.TemporaryOriginsCount" expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>
Number of origins that have temporary filesystem. Measured when the Quota
@@ -29410,6 +31071,27 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="FirstRun.NewUserExperience.GoogleAppsInteraction"
+ enum="NuxGoogleAppsInteractions">
+ <owner>hcarmona@chromium.org</owner>
+ <summary>
+ This histogram records when a user interacted with the Google Apps new user
+ experience. We record both accept and reject but are not recording when a
+ user ignored the prompt completely. Users can ignore this prompt by closing
+ the tab or navigating away, we record when the prompt is shown.
+ </summary>
+</histogram>
+
+<histogram name="FirstRun.NewUserExperience.GoogleAppsSelection"
+ enum="NuxGoogleAppsSelections">
+ <owner>hcarmona@chromium.org</owner>
+ <summary>
+ This histogram records what Google apps were selected as part of the Google
+ Apps New User Experience. Histogram is only recorded when a user accepts the
+ prompt to add Google Apps.
+ </summary>
+</histogram>
+
<histogram name="FirstRun.Sentinel.Created" enum="FirstRunSentinelResult">
<owner>jlebel@chromium.org</owner>
<summary>Result of sentinel file has been written.</summary>
@@ -29526,13 +31208,14 @@ uploading your change for review.
<summary>URL response and error codes from GCM disconnect events.</summary>
</histogram>
-<histogram name="GCM.ConnectionEndpoint" enum="GCMEndpoints">
+<histogram name="GCM.ConnectionEndpoint" enum="GCMEndpoints"
+ expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>Number of connections made to each specific MCS endpoint.</summary>
</histogram>
<histogram name="GCM.ConnectionFailureErrorCode"
- enum="CombinedHttpResponseAndNetErrorCode">
+ enum="CombinedHttpResponseAndNetErrorCode" expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>URL response and error codes from GCM connection attempts.</summary>
</histogram>
@@ -29545,12 +31228,14 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="GCM.ConnectionResetReason" enum="GCMConnectionResetReason">
+<histogram name="GCM.ConnectionResetReason" enum="GCMConnectionResetReason"
+ expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>Reasons for GCM connection resets.</summary>
</histogram>
-<histogram name="GCM.ConnectionSuccessRate" enum="BooleanSuccess">
+<histogram name="GCM.ConnectionSuccessRate" enum="BooleanSuccess"
+ expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>
GCM connection success rate. Does not take into account login success. See
@@ -29559,7 +31244,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="GCM.ConnectionUpTime" units="ms">
+<histogram name="GCM.ConnectionUpTime" units="ms" expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>
Time (from login until reset) that a GCM connection was active.
@@ -29683,7 +31368,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="GCM.HeartbeatMissedDelta" units="ms">
+<histogram name="GCM.HeartbeatMissedDelta" units="ms"
+ expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>
If a heartbeat was missed, the time delta by which it was missed (in system
@@ -29826,7 +31512,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="GCM.RestoredIncomingMessages">
+<histogram name="GCM.RestoredIncomingMessages" expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>
Number of unacknowledged incoming messages restored from the persistent
@@ -29834,7 +31520,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="GCM.RestoredOutgoingMessages">
+<histogram name="GCM.RestoredOutgoingMessages" expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>
Number of pending outgoing messages restored from the persistent store at
@@ -29867,12 +31553,13 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="GCM.StoreSizeKB" units="KB">
+<histogram name="GCM.StoreSizeKB" units="KB" expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>Size of the GCM persistent store in kilobytes at startup.</summary>
</histogram>
-<histogram name="GCM.StoreUpdateSucceeded" enum="BooleanSuccess">
+<histogram name="GCM.StoreUpdateSucceeded" enum="BooleanSuccess"
+ expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>
Success indicates successfully updating the GCM persistent store on message
@@ -29880,7 +31567,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="GCM.SuspendTime" units="ms">
+<histogram name="GCM.SuspendTime" units="ms" expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>Time elapsed from machine suspend until resume.</summary>
</histogram>
@@ -29936,7 +31623,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="GData.AuthSuccess" enum="GDataAuthResult">
+<histogram name="GData.AuthSuccess" enum="GDataAuthResult"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Result of the authentication for Drive.</summary>
</histogram>
@@ -30327,7 +32015,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="GoogleUpdate.EffectivePolicy" enum="UpdatePolicy">
+<histogram name="GoogleUpdate.EffectivePolicy" enum="UpdatePolicy"
+ expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
The effective update policy for Chrome on Windows. Recorded once per startup
@@ -30427,7 +32116,8 @@ uploading your change for review.
<summary>The error code for a failed on-demand update check.</summary>
</histogram>
-<histogram name="GoogleUpdate.UpdatePolicyIsOverridden" enum="Boolean">
+<histogram name="GoogleUpdate.UpdatePolicyIsOverridden" enum="Boolean"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
True if the effective update policy for Chrome on Windows is the result of
@@ -30521,13 +32211,29 @@ uploading your change for review.
<histogram name="GPU.ANGLE.ProgramCache.BinaryCacheHitTimeUS"
units="microseconds">
<owner>jmadill@chromium.org</owner>
- <summary>The time to load a gpu program from the program cache.</summary>
+ <summary>
+ The time to load a gpu program from the program cache.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="GPU.ANGLE.ProgramCache.BinaryCacheMissTimeUS"
units="microseconds">
<owner>jmadill@chromium.org</owner>
- <summary>The time to link a gpu program.</summary>
+ <summary>
+ The time to link a gpu program.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="GPU.ANGLE.ProgramCache.CacheResult"
@@ -30694,6 +32400,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="GPU.BlockStatusForClient3DAPIs"
+ enum="BlockStatusForClient3DAPIs">
+ <owner>kbr@chromium.org</owner>
+ <summary>
+ Indicates whether WebGL / Pepper3D were blocked, and if so, for all domains,
+ or only a single one. This statistic is gathered every time an attempt is
+ made to create a 3D context.
+ </summary>
+</histogram>
+
<histogram name="GPU.CheckFramebufferValidDuration" units="ms">
<obsolete>
Deprecated 01/2017.
@@ -30710,9 +32426,11 @@ uploading your change for review.
The time that the GPU process spends collecting driver information during
startup.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -30729,15 +32447,20 @@ uploading your change for review.
</histogram>
<histogram name="GPU.CreateBrowserCompositor" units="microseconds">
+ <obsolete>
+ Deprecated 07/2018: not useful anymore.
+ </obsolete>
<owner>vmiura@chromium.org</owner>
<summary>
The time that the browser process takes to create the compositor from its
point of view. One of these is created for each top-level window (browser
frame, menus, etc.).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -30840,7 +32563,10 @@ uploading your change for review.
<histogram name="GPU.DirectComposition.OverlaySupportFlags"
enum="OverlaySupportFlag">
- <owner>jbauman@chromium.org</owner>
+ <obsolete>
+ Replaced by format specific histograms under OverlaySupportFlags2.
+ </obsolete>
+ <owner>sunnyps@chromium.org</owner>
<summary>
These are the flags explaining how well overlays are supported on the
current display. The is recorded for every connected display when creating a
@@ -30848,12 +32574,32 @@ uploading your change for review.
</summary>
</histogram>
+<histogram base="true" name="GPU.DirectComposition.OverlaySupportFlags2"
+ enum="OverlaySupportFlag">
+<!-- Name completed by histogram_suffixes name="GPU.DirectComposition.OverlayFormat" -->
+
+ <owner>sunnyps@chromium.org</owner>
+ <summary>
+ Flags that indicate if overlays are supported, and if additional features
+ such as scaling are supported for some common pixel formats.
+ </summary>
+</histogram>
+
<histogram name="GPU.DirectComposition.OverlaysUsed" enum="BooleanOverlayUsage">
<owner>jbauman@chromium.org</owner>
<summary>Whether or not a frame displays an overlay.</summary>
</histogram>
+<histogram name="GPU.DirectComposition.SwapBuffersFailed" enum="BooleanHit">
+ <owner>sunnyps@chromium.org</owner>
+ <summary>Emitted on direct composition surface swap buffers failure.</summary>
+</histogram>
+
<histogram name="GPU.DirectComposition.SwapBuffersLastError" enum="Hresult">
+ <obsolete>
+ Deprecated 05/2018. GetLastError returns error for last successful or failed
+ win32 call so this doesn't work as expected.
+ </obsolete>
<owner>sunnyps@chromium.org</owner>
<summary>Last error when presentation using DirectComposition fails.</summary>
</histogram>
@@ -30865,6 +32611,9 @@ uploading your change for review.
<histogram name="GPU.DisplayCompositorLifetimeEvents"
enum="GPUProcessLifetimeEvent">
+ <obsolete>
+ Deprecated 05/2018. Moved to GPU.ProcessLifetimeEvents.DisplayCompositor.
+ </obsolete>
<owner>mohsen@chromium.org</owner>
<summary>
Counts of the number of gpu process crashes when it only has display
@@ -30969,6 +32718,9 @@ uploading your change for review.
</histogram>
<histogram name="GPU.GPUProcessLifetimeEvents" enum="GPUProcessLifetimeEvent">
+ <obsolete>
+ Deprecated 05/2018. Moved to GPU.ProcessLifetimeEvents.HardwareAccelerated.
+ </obsolete>
<owner>vmiura@chromium.org</owner>
<summary>
Counts of the number of process launches and crashes (when running on h/w).
@@ -31068,6 +32820,18 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="GPU.OopRaster.GlyphCacheMiss"
+ enum="OopRasterGlyphCacheMissType">
+ <owner>khushalsagar@chromium.org</owner>
+ <summary>
+ During OutOfProcess(Oop) raster, the renderer generates and sends the
+ requisite glyph data for rasterizing a tile with the serialized paint
+ commands. If the data for any glyph is missing, the GPU process attempts to
+ use a fallback glyph from the cache. This records each time we encounter a
+ cache miss on the GPU and whether we could use a fallback.
+ </summary>
+</histogram>
+
<histogram name="GPU.Output.ColorSpace" enum="DXGI_COLOR_SPACE_TYPE">
<owner>hubbe@chromium.org</owner>
<owner>media-dev@chromium.org</owner>
@@ -31098,14 +32862,63 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="GPU.ProcessLifetimeEvents.DisplayCompositor"
+ enum="GPUProcessLifetimeEvent">
+ <owner>vmiura@chromium.org</owner>
+ <summary>
+ Recorded once for every GPU process launch and crash when GPU process is
+ started for the display compositor with software compositing. Crash buckets
+ are based on crash count for disabling features. No hardware acceleration
+ and no SwiftShader WebGL will be run.
+ </summary>
+</histogram>
+
+<histogram name="GPU.ProcessLifetimeEvents.HardwareAccelerated"
+ enum="GPUProcessLifetimeEvent">
+ <owner>vmiura@chromium.org</owner>
+ <summary>
+ Recorded once for every GPU process launch and crash when GPU process is
+ started for hardware accelerated GPU compositing and/or WebGL. Crash buckets
+ are based on crash count for disabling features. With OOP-D enabled the
+ display compositor also runs in the GPU process.
+ </summary>
+</histogram>
+
+<histogram name="GPU.ProcessLifetimeEvents.SwiftShader"
+ enum="GPUProcessLifetimeEvent">
+ <owner>vmiura@chromium.org</owner>
+ <summary>
+ Recorded once for every GPU process launch and crash when GPU process is
+ started for SwiftShader WebGL. Crash buckets are based on crash count for
+ disabling features. With OOP-D enabled the display compositor with software
+ compositing will also run as part of the GPU process.
+ </summary>
+</histogram>
+
<histogram name="GPU.ProgramCache.BinaryCacheHitTime" units="microseconds">
<owner>vmiura@chromium.org</owner>
- <summary>The time to load a gpu program from the program cache.</summary>
+ <summary>
+ The time to load a gpu program from the program cache.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="GPU.ProgramCache.BinaryCacheMissTime" units="microseconds">
<owner>vmiura@chromium.org</owner>
- <summary>The time to link a gpu program.</summary>
+ <summary>
+ The time to link a gpu program.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="GPU.ProgramCache.CacheHit" enum="BooleanSuccess">
@@ -31121,16 +32934,26 @@ uploading your change for review.
<summary>
The time to check the program cache that we've already compiled the shader.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
<histogram name="GPU.ProgramCache.CompilationCacheMissTime"
units="microseconds">
<owner>vmiura@chromium.org</owner>
- <summary>The time to compile a shader.</summary>
+ <summary>
+ The time to compile a shader.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="GPU.ProgramCache.CompressDataSuccess" units="BooleanSuccess">
@@ -31147,9 +32970,11 @@ uploading your change for review.
The time to compress a program's binary data during insertion into the
program cache.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -31174,9 +32999,11 @@ uploading your change for review.
The time to decompress a program's binary data during retrieval from the
program cache.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -31248,6 +33075,9 @@ uploading your change for review.
<histogram name="GPU.SoftwareRendererLifetimeEvents"
enum="GPUProcessLifetimeEvent">
+ <obsolete>
+ Never used.
+ </obsolete>
<owner>vmiura@chromium.org</owner>
<summary>
Counts of the number of gpu process crashes when the software rasterizer is
@@ -31294,6 +33124,9 @@ uploading your change for review.
</histogram>
<histogram name="GPU.SwiftShaderLifetimeEvents" enum="GPUProcessLifetimeEvent">
+ <obsolete>
+ Deprecated 05/2018. Moved to GPU.ProcessLifetimeEvents.SwiftShader.
+ </obsolete>
<owner>capn@chromium.org</owner>
<summary>
Counts of the number of process launches and crashes (when running on s/w).
@@ -31460,9 +33293,11 @@ uploading your change for review.
The amount of time it takes to read the WinSAT results. This is collected
each time Chrome is launched.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -31523,6 +33358,39 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="HeavyPageCapping.BlacklistReason" enum="OptOutBlacklistReason"
+ expires_after="M75">
+ <owner>ryansturm@chromium.org</owner>
+ <owner>bengr@chromium.org</owner>
+ <summary>
+ Records that the capping heavy pages InfoBar was allowed or the specific
+ reason that the feature was blacklisted from heavy page capping. Recorded
+ when the triggering threshold is met for users with capping heavy pages
+ enabled. Reasons are ordered in the same order they are checked.
+ </summary>
+</histogram>
+
+<histogram name="HeavyPageCapping.InfoBarInteraction"
+ enum="HeavyPageCappingInfoBarInteraction" expires_after="M75">
+ <owner>ryansturm@chromium.org</owner>
+ <owner>bengr@chromium.org</owner>
+ <summary>
+ Records the details of user interaction with the heavy page capping InfoBar.
+ </summary>
+</histogram>
+
+<histogram name="HeavyPageCapping.RecordedDataSavings" units="KB"
+ expires_after="M75">
+ <owner>ryansturm@chromium.org</owner>
+ <summary>
+ Records the data savings due to heavy page capping. This is recorded when
+ the page is being terminated. This is not recorded when the tab is
+ backgrounded, so android fast shutdown may result in this metric not being
+ recorded. This is only recorded for page loads that were still paused when
+ the page was terminated.
+ </summary>
+</histogram>
+
<histogram name="HIDDetection.OOBEDevicesDetectedOnContinuePressed"
enum="HIDContinueScenarioType">
<owner>merkulova@chromium.org</owner>
@@ -31896,7 +33764,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="History.DeleteFTSIndexDatabases">
+<histogram name="History.DeleteFTSIndexDatabases" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Count of &quot;History Index *&quot; databases deleted. These databases
@@ -32054,7 +33922,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="History.InMemoryDBKeywordTermsPopulate" units="ms">
+<histogram name="History.InMemoryDBKeywordTermsPopulate" units="ms"
+ expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
Time to load in-memory keyword_search_terms table from disk. Recorded on
@@ -32069,7 +33938,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="History.InMemoryDBKeywordURLPopulate" units="ms">
+<histogram name="History.InMemoryDBKeywordURLPopulate" units="ms"
+ expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
Time to load in-memory urls table from disk urls table. Recorded on profile
@@ -32125,7 +33995,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="History.InMemoryURLIndexingTime" units="ms">
+<histogram name="History.InMemoryURLIndexingTime" units="ms"
+ expires_after="2018-08-30">
<owner>mpearson@chromium.org</owner>
<summary>
Time to rebuild in-memory url index from main history database. Recorded
@@ -32141,7 +34012,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="History.InMemoryURLIndexSaveCacheTime" units="ms">
+<histogram name="History.InMemoryURLIndexSaveCacheTime" units="ms"
+ expires_after="2018-08-30">
<owner>mpearson@chromium.org</owner>
<summary>
Time to write in-memory url index to disk cache. Recorded once shortly after
@@ -32302,7 +34174,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="History.TopSitesRecovery" enum="HistoryTopSitesRecoveryEnum">
+<histogram name="History.TopSitesRecovery" enum="HistoryTopSitesRecoveryEnum"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The TopSites recovery code is written conservatively, with successful
@@ -32763,7 +34636,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Import.ImporterType.AutoImport" enum="ImporterType">
+<histogram name="Import.ImporterType.AutoImport" enum="ImporterType"
+ expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>The importer used on first run Auto Import.</summary>
</histogram>
@@ -32773,7 +34647,8 @@ uploading your change for review.
<summary>The importer used on import from the bookmarks file API.</summary>
</histogram>
-<histogram name="Import.ImporterType.ImportDataHandler" enum="ImporterType">
+<histogram name="Import.ImporterType.ImportDataHandler" enum="ImporterType"
+ expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
The importer used on import from the chrome://settings/importData UI.
@@ -32802,7 +34677,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Import.ShowDialog.FromBookmarkBarView" units="seconds">
+<histogram name="Import.ShowDialog.FromBookmarkBarView" units="seconds"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The amount of time from install time to time that user opens import dialog
@@ -32810,7 +34686,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Import.ShowDialog.FromFloatingBookmarkBarView" units="seconds">
+<histogram name="Import.ShowDialog.FromFloatingBookmarkBarView" units="seconds"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The amount of time from install time to time that user opens import dialog
@@ -34925,6 +36802,17 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="interstitial.ssl_nonoverridable.is_recurrent_error.ct_error"
+ enum="BooleanRecurrentError" expires_after="M71">
+ <owner>estark@chromium.org</owner>
+ <summary>
+ Recorded when a non-overridable SSL interstitial is shown for a Certificate
+ Transparency error. The value is true if the user has seen the same error
+ multiple times (in which case a special message is added to the
+ interstitial).
+ </summary>
+</histogram>
+
<histogram name="interstitial.ssl_overridable.is_recurrent_error"
enum="BooleanRecurrentError" expires_after="M71">
<owner>estark@chromium.org</owner>
@@ -34935,6 +36823,17 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="interstitial.ssl_overridable.is_recurrent_error.ct_error"
+ enum="BooleanRecurrentError" expires_after="M71">
+ <owner>estark@chromium.org</owner>
+ <summary>
+ Recorded when an overridable SSL interstitial is shown for a Certificate
+ Transparency error. The value is true if the user has seen the same error
+ multiple times (in which case a special message is added to the
+ interstitial).
+ </summary>
+</histogram>
+
<histogram name="interstitial.ssl_recurrent_error.action"
enum="RecurrentErrorAction" expires_after="M71">
<owner>estark@chromium.org</owner>
@@ -34945,6 +36844,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="interstitial.ssl_recurrent_error.ct_error.action"
+ enum="RecurrentErrorAction" expires_after="M71">
+ <owner>estark@chromium.org</owner>
+ <summary>
+ Recorded whenever the user sees or proceeds through an SSL interstitial for
+ a Certificate Transparency error that the user has seen multiple times (in
+ which case a special message is added to the interstitial).
+ </summary>
+</histogram>
+
<histogram name="interstitial.ssl_reject_time" units="ms">
<obsolete>
Removed on 8/1/13.
@@ -35154,6 +37063,15 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="IOS.ShowTabSwitcherSnapshotResult"
+ enum="ShowTabSwitcherSnapshotResult" expires_after="2019-08-01">
+ <owner>edchin@chromium.org</owner>
+ <summary>
+ Tracks the result of snapshotting when the user enters the tab switcher.
+ Recorded whenever the user enters the tab switcher.
+ </summary>
+</histogram>
+
<histogram name="IOS.Spotlight.Action" enum="IOSSpotlightAction">
<owner>olivierrobin@chromium.org</owner>
<summary>The Spotlight Action pressed by the user.</summary>
@@ -35241,6 +37159,9 @@ uploading your change for review.
</histogram>
<histogram name="JSDialogs.CharacterCountUserSuppressed" units="characters">
+ <obsolete>
+ Deprecated 2018-06.
+ </obsolete>
<owner>avi@chromium.org</owner>
<summary>
The count of the number of characters in JavaScript dialog messages that
@@ -35250,6 +37171,9 @@ uploading your change for review.
</histogram>
<histogram name="JSDialogs.CountOfJSDialogMessageCharacters" units="characters">
+ <obsolete>
+ Deprecated 2018-06.
+ </obsolete>
<owner>avi@chromium.org</owner>
<summary>
The count of the number of characters in JavaScript dialog messages.
@@ -35257,6 +37181,9 @@ uploading your change for review.
</histogram>
<histogram name="JSDialogs.CountOfJSDialogMessageNewlines">
+ <obsolete>
+ Deprecated 2018-06.
+ </obsolete>
<owner>avi@chromium.org</owner>
<summary>
The count of the number of newlines in JavaScript dialog messages. (This
@@ -35397,6 +37324,72 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Keyboard.ShortcutViewer.StartupTime" units="ms">
+ <owner>jamescook@chromium.org</owner>
+ <owner>msw@chromium.org</owner>
+ <owner>wutao@chromium.org</owner>
+ <summary>
+ Time delay between the user gesture that triggered the keyboard shortcut
+ viewer dialog (e.g. pressing Ctrl-Alt-/) and the dialog widget being shown,
+ including layout time for the views::Views.
+ </summary>
+</histogram>
+
+<histogram name="KeyboardAccessory.AccessoryActionImpression"
+ enum="AccessoryAction">
+ <owner>fhorschig@chromium.org</owner>
+ <summary>
+ Android only. Records whenever users faces an action in the accessory bar or
+ one of its sheets.
+ </summary>
+</histogram>
+
+<histogram name="KeyboardAccessory.AccessoryActionSelected"
+ enum="AccessoryAction">
+ <owner>fhorschig@chromium.org</owner>
+ <summary>
+ Android only. Records whenever users select an action in the accessory bar
+ or one of its sheets.
+ </summary>
+</histogram>
+
+<histogram name="KeyboardAccessory.AccessoryBarShown"
+ enum="AccessoryBarContents">
+ <owner>fhorschig@chromium.org</owner>
+ <summary>
+ Android only. Records how often users encounter the keyboard accessory bar.
+ Its buckets show the contents when it came up. Every bucket may be logged up
+ to one time per impression.
+ </summary>
+</histogram>
+
+<histogram name="KeyboardAccessory.AccessorySheetSuggestionCount" units="count">
+ <owner>fhorschig@chromium.org</owner>
+ <summary>
+ Android only. Records how many suggestions a user faced when opening a
+ sheet. The base histogram counts impressions across all sheets.
+ </summary>
+</histogram>
+
+<histogram name="KeyboardAccessory.AccessorySheetSuggestionsSelected"
+ enum="AccessorySuggestionType">
+ <owner>fhorschig@chromium.org</owner>
+ <summary>
+ Android only. Records which type of suggestion was selected from an open
+ sheet.
+ </summary>
+</histogram>
+
+<histogram name="KeyboardAccessory.AccessorySheetTriggered"
+ enum="AccessorySheetTrigger">
+ <owner>fhorschig@chromium.org</owner>
+ <summary>
+ Android only. Records how often the bottom sheet was opened or closed by a
+ user and the overall count of closures. Closing buckets may be logged up to
+ one time per trigger. There are suffixes for each specific sheet type.
+ </summary>
+</histogram>
+
<histogram name="Kiosk.Launch.CryptohomeFailure" enum="LoginFailureReason">
<owner>xiyuan@chromium.org</owner>
<summary>Tracks cryptohome failure during kiosk launch.</summary>
@@ -35430,12 +37423,14 @@ uploading your change for review.
<summary>The type of panes which language settings loads.</summary>
</histogram>
-<histogram name="LanguageUsage.AcceptLanguage" enum="LanguageCode">
+<histogram name="LanguageUsage.AcceptLanguage" enum="LanguageCode"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Accept languages.</summary>
</histogram>
-<histogram name="LanguageUsage.ApplicationLanguage" enum="LanguageCode">
+<histogram name="LanguageUsage.ApplicationLanguage" enum="LanguageCode"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Application languages used for UI.</summary>
</histogram>
@@ -35496,6 +37491,14 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Launch.MashService" enum="MashService">
+ <owner>jamescook@chromium.org</owner>
+ <summary>
+ Records when a mojo ash UI service is started, for example the mojo app
+ version of the keyboard shortcut viewer.
+ </summary>
+</histogram>
+
<histogram name="Launch.Modes" enum="LaunchMode">
<owner>calamity@chromium.org</owner>
<summary>The different ways Chrome is launched.</summary>
@@ -35516,9 +37519,11 @@ uploading your change for review.
complex text fragments, the average number of microseconds spent laying out
each node.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -35528,9 +37533,11 @@ uploading your change for review.
For layouts that considered at least 100 nodes, at least half of which were
floats, the average number of microseconds spent laying out each node.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -35540,9 +37547,11 @@ uploading your change for review.
For layouts that considered at least 100 nodes, the average number of
microseconds spent laying out each node.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -35553,9 +37562,11 @@ uploading your change for review.
fixed or absolute positioned, the average number of microseconds spent
laying out each node.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -35566,9 +37577,11 @@ uploading your change for review.
simple text fragments, the average number of microseconds spent laying out
each node.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -35578,9 +37591,11 @@ uploading your change for review.
For layouts that considered at least 100 nodes, at least half of which were
table cells, the average number of microseconds spent laying out each node.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -35622,15 +37637,25 @@ uploading your change for review.
<summary>
The time it took to compute the selector of a serialized anchor element.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
<histogram name="Layout.ScrollAnchor.TimeToFindAnchor" units="microseconds">
<owner>ymalik@chromium.org</owner>
- <summary>The time it took to find a suitable anchor element.</summary>
+ <summary>
+ The time it took to find a suitable anchor element.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="Layout.ScrollAnchor.TimeToRestoreAnchor" units="microseconds">
@@ -35639,9 +37664,11 @@ uploading your change for review.
The time it took to restore the scroll anchor using the serialized anchor
element.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -35894,6 +37921,7 @@ uploading your change for review.
<histogram name="Linux.Distro" enum="LinuxDistro">
<owner>timbrown@chromium.org</owner>
+ <owner>thomasanderson@chromium.org</owner>
<summary>The Linux distro used. Logged on each start up.</summary>
</histogram>
@@ -35926,9 +37954,11 @@ uploading your change for review.
RTT between Chrome and the X11 server. Tracked in X11EventSource by
measuring the latency to receive a property event after changing a property.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -36580,6 +38610,12 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Media.AImageReaderGLOwner.AcquireImageResult"
+ enum="MediaStatus" expires_after="2018-11-25">
+ <owner>vikassoni@chromium.org</owner>
+ <summary>Error codes to handle AImage and AImageReader api calls.</summary>
+</histogram>
+
<histogram name="Media.Android.BackgroundVideoTime" units="ms">
<owner>avayvod@chromium.org</owner>
<owner>mlamouri@chromium.org</owner>
@@ -36705,7 +38741,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Media.Audio.AutomaticGainControlMac" enum="BooleanEnabled">
+<histogram name="Media.Audio.AutomaticGainControlMac" enum="BooleanEnabled"
+ expires_after="2018-08-30">
<owner>henrika@chromium.org</owner>
<summary>
Indicates if the Automatic Gain Control (AGC) is enabled or not. Only
@@ -36851,6 +38888,9 @@ uploading your change for review.
</histogram>
<histogram name="Media.Audio.Capture.StreamCallbackError" enum="BooleanError">
+ <obsolete>
+ Replaced by Media.Audio.Capture.StreamCallbackError2
+ </obsolete>
<owner>maxmorin@chromium.org</owner>
<summary>
When AudioInputDevice is stopped, this stat is recorded with whether an
@@ -36858,6 +38898,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Media.Audio.Capture.StreamCallbackError2"
+ enum="AudioCaptureDeviceError" expires_after="2019-06-01">
+ <owner>maxmorin@chromium.org</owner>
+ <summary>
+ When AudioInputDevice is stopped, this stat is recorded with whether an
+ error callback was ever received over IPC, and in that case whether the
+ error occurred during or after stream creation.
+ </summary>
+</histogram>
+
<histogram name="Media.Audio.Capture.VirtualCallbackError" enum="BooleanError">
<owner>maxmorin@chromium.org</owner>
<summary>
@@ -36867,7 +38917,7 @@ uploading your change for review.
</histogram>
<histogram name="Media.Audio.Capture.Win.ConcurrentGlitchAndDiscontinuities"
- units="occurences">
+ units="occurrences">
<owner>grunell@chromium.org</owner>
<summary>
The number of times a glitch was detected by detecting skipped frames (as
@@ -36889,7 +38939,7 @@ uploading your change for review.
</histogram>
<histogram name="Media.Audio.Capture.Win.DevicePositionLessThanExpected"
- units="occurences">
+ units="occurrences">
<owner>grunell@chromium.org</owner>
<summary>
The number of times the device position was less than expected during the
@@ -36973,7 +39023,7 @@ uploading your change for review.
</histogram>
<histogram name="Media.Audio.InputBufferSizeWasChangedAudioWorkedMac"
- enum="BooleanChanged">
+ enum="BooleanChanged" expires_after="2018-08-30">
<owner>henrika@chromium.org</owner>
<summary>
Indicates if the size of the audio unit's IO buffer was changed when
@@ -37045,7 +39095,7 @@ uploading your change for review.
</histogram>
<histogram name="Media.Audio.InputStartWasDeferredAudioWorkedMac"
- enum="BooleanDeferred">
+ enum="BooleanDeferred" expires_after="2018-08-30">
<owner>henrika@chromium.org</owner>
<summary>
Indicates if audio capturing started with a small delay or not. Sampled each
@@ -37056,7 +39106,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Media.Audio.InputStartWasDeferredMac" enum="BooleanDeferred">
+<histogram name="Media.Audio.InputStartWasDeferredMac" enum="BooleanDeferred"
+ expires_after="2018-08-30">
<owner>henrika@chromium.org</owner>
<summary>
Indicates if audio capturing started with a small delay or not. Only sampled
@@ -37064,7 +39115,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Media.Audio.IsOnBatteryPowerMac" enum="BooleanOnBattery">
+<histogram name="Media.Audio.IsOnBatteryPowerMac" enum="BooleanOnBattery"
+ expires_after="2018-08-30">
<owner>henrika@chromium.org</owner>
<summary>
Indicates if the Mac OSX device is on battery power or not. Only sampled
@@ -37080,7 +39132,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Media.Audio.NumberOfBasicInputStreamsMac">
+<histogram name="Media.Audio.NumberOfBasicInputStreamsMac"
+ expires_after="2018-08-30">
<owner>henrika@chromium.org</owner>
<summary>
Number of created default input audio streams. Only sampled when
@@ -37088,7 +39141,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Media.Audio.NumberOfLowLatencyInputStreamsMac">
+<histogram name="Media.Audio.NumberOfLowLatencyInputStreamsMac"
+ expires_after="2018-08-30">
<owner>henrika@chromium.org</owner>
<summary>
Number of created low-latency input audio streams. Only sampled when
@@ -37096,7 +39150,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Media.Audio.NumberOfOutputStreamsMac">
+<histogram name="Media.Audio.NumberOfOutputStreamsMac"
+ expires_after="2018-08-30">
<owner>henrika@chromium.org</owner>
<summary>
Number of created output audio streams. Only sampled when
@@ -37233,9 +39288,11 @@ uploading your change for review.
spent in WebRtcAudioRenderer::SourceCallback. Logged every function call,
which is every 10 ms.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -37247,9 +39304,11 @@ uploading your change for review.
For WebRTC, it's the time spent in WebRtcAudioRenderer::SourceCallback. A
session is between Start() and Stop() of WebRtcAudioRenderer.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -37348,7 +39407,7 @@ uploading your change for review.
<owner>maxmorin@chromium.org</owner>
<owner>olka@chromium.org</owner>
<summary>
- The time delta between the moment a MojoAudioInputIPC instance on the
+ The time delta between the moment a MojoAudioOutputIPC instance on the
renderer process requests a new stream from the browser to the moment it
receives a response.
</summary>
@@ -37404,6 +39463,9 @@ uploading your change for review.
</histogram>
<histogram name="Media.Audio.Render.StreamCallbackError" enum="BooleanError">
+ <obsolete>
+ Replaced by Media.Audio.Render.StreamCallbackError2
+ </obsolete>
<owner>maxmorin@chromium.org</owner>
<summary>
When AudioOutputDevice is stopped, this stat is recorded with whether an
@@ -37411,6 +39473,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Media.Audio.Render.StreamCallbackError2"
+ enum="AudioRenderDeviceError" expires_after="2019-06-01">
+ <owner>maxmorin@chromium.org</owner>
+ <summary>
+ When AudioOutputDevice is stopped, this stat is recorded with whether an
+ error callback was ever received over IPC, and in that case whether the
+ error occurred during or after stream creation.
+ </summary>
+</histogram>
+
<histogram name="Media.Audio.RenderFailsWhenBufferSizeChangesMac"
enum="BooleanChanged">
<owner>henrika@chromium.org</owner>
@@ -37432,7 +39504,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Media.Audio.ResumeEventsMac">
+<histogram name="Media.Audio.ResumeEventsMac" expires_after="2018-08-30">
<owner>henrika@chromium.org</owner>
<summary>
Counts the number of times the system has resumed from power suspension.
@@ -37441,7 +39513,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Media.Audio.UptimeMac" units="hours">
+<histogram name="Media.Audio.UptimeMac" units="hours"
+ expires_after="2018-08-30">
<owner>henrika@chromium.org</owner>
<summary>
Reports the system uptime in hours for Mac OS X devices. Only sampled when
@@ -37990,6 +40063,11 @@ uploading your change for review.
</histogram>
<histogram name="Media.AvdaCodecImage.WaitTimeForFrame" units="ms">
+ <obsolete>
+ Deprecated 06/2018. This has been renamed to
+ Media.CodecImage.SurfaceTextureGLOwner.WaitTimeForFrame and
+ Media.CodecImage.ImageReaderGLOwner.WaitTimeForFrame.
+ </obsolete>
<owner>liberato@chromium.org</owner>
<summary>
Time spent waiting for a frame to become available in a Non Overlay after
@@ -38073,6 +40151,26 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Media.CodecImage.ImageReaderGLOwner.WaitTimeForFrame"
+ units="ms">
+ <owner>vikassoni@chromium.org</owner>
+ <summary>
+ Time spent waiting for a frame to become available in a Non Overlay
+ (AImageReader mode) so that MediaCodec can render it. This time is recorded
+ before the frame is rendered.
+ </summary>
+</histogram>
+
+<histogram name="Media.CodecImage.SurfaceTextureGLOwner.WaitTimeForFrame"
+ units="ms">
+ <owner>liberato@chromium.org</owner>
+ <summary>
+ Time spent waiting for a frame to become available in a Non Overlay
+ (SurfaceTexture mode) so that MediaCodec can render it. This time is
+ recorded before the frame is rendered.
+ </summary>
+</histogram>
+
<histogram name="Media.Controls.CTR" enum="MediaControlsCTREvent">
<owner>mlamouri@chromium.org</owner>
<owner>media-dev@chromium.org</owner>
@@ -38167,6 +40265,17 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Media.D3D11.WasVideoSupported"
+ enum="D3D11VideoNotSupportedReason" expires_after="M70">
+ <owner>liberato@chromium.org</owner>
+ <owner>sandersd@chromium.org</owner>
+ <owner>tmathmeyer@chromium.org</owner>
+ <summary>
+ This enum measures whether or not d3d11 is supported and if not, what the
+ reason is.
+ </summary>
+</histogram>
+
<histogram name="Media.DetectedAudioCodec" enum="FFmpegCodecs">
<obsolete>
Deprecated Sep 15 2015 in favor of Media.DetectedAudioCodecHash
@@ -38417,7 +40526,7 @@ uploading your change for review.
</histogram>
<histogram name="Media.EME.EncryptionScheme.Initial.Audio"
- units="MediaEncryptionScheme">
+ enum="MediaEncryptionScheme">
<owner>jrummell@chromium.org</owner>
<owner>media-dev@chromium.org</owner>
<summary>
@@ -38427,7 +40536,7 @@ uploading your change for review.
</histogram>
<histogram name="Media.EME.EncryptionScheme.Initial.Video"
- units="MediaEncryptionScheme">
+ enum="MediaEncryptionScheme">
<owner>jrummell@chromium.org</owner>
<owner>media-dev@chromium.org</owner>
<summary>
@@ -38853,6 +40962,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Media.GpuMemoryBufferVideoFramePool.UnsupportedFormat"
+ enum="VideoPixelFormatUnion">
+ <owner>dcastagna@chromium.org</owner>
+ <owner>mcasas@chromium.org</owner>
+ <summary>
+ GpuMemoryBufferVideoFramePool is called with an unsupported VideoFrame pixel
+ format. Emitted on VideoFrame arrival.
+ </summary>
+</histogram>
+
<histogram name="Media.GpuVideoDecoderError" enum="VideoDecodeAcceleratorError">
<owner>sandersd@chromium.org</owner>
<summary>Counts of video decode errors reported to GpuVideoDecoder.</summary>
@@ -38987,7 +41106,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Media.LocalRendererSinkStates" enum="LocalRendererSinkStates">
+<histogram name="Media.LocalRendererSinkStates" enum="LocalRendererSinkStates"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
State of the WebRtc local renderer, sampled once during the lifetime of a
@@ -39021,6 +41141,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Media.MediaElement.PlaybackPositionIsInfinity"
+ enum="BooleanInfinity" expires_after="2019-01-01">
+ <owner>ossu@chromium.org</owner>
+ <owner>grunell@chromium.org</owner>
+ <summary>
+ Whether or not the MediaElement is at a playback position of infinity when
+ checking if playback has ended.
+ </summary>
+</histogram>
+
<histogram name="Media.MediaElement.PlayPromiseReject"
enum="PlayPromiseRejectReason">
<owner>mlamouri@chromium.org</owner>
@@ -39044,7 +41174,8 @@ uploading your change for review.
<summary>Whether HW video encode is used in MediaRecorder.</summary>
</histogram>
-<histogram name="Media.MicrophoneMuted" enum="MicrophoneMuteResult">
+<histogram name="Media.MicrophoneMuted" enum="MicrophoneMuteResult"
+ expires_after="2018-08-30">
<owner>henrika@chromium.org</owner>
<summary>
Heuristically detects if the user has muted the microphone or not. Measured
@@ -39052,7 +41183,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Media.MicrophoneVolume" units="%">
+<histogram name="Media.MicrophoneVolume" units="%" expires_after="2018-08-30">
<owner>henrika@chromium.org</owner>
<summary>
Level of the microphone volume measured in percent. This value can be larger
@@ -39123,6 +41254,10 @@ uploading your change for review.
<histogram name="Media.MSE.AudioSpliceDurationType"
enum="StreamParserBufferDurationType">
+ <obsolete>
+ Deprecated 05/2018. Splicing no longer performed on buffers with estimated
+ duration. See https://crbug.com/396634.
+ </obsolete>
<owner>chcunningham@chromium.org</owner>
<summary>
Categorizes MSE audio splicing by the type of duration used in the
@@ -40856,6 +42991,15 @@ uploading your change for review.
<summary>Various usage counts for media galleries.</summary>
</histogram>
+<histogram name="MediaLauncherActivity.MediaType"
+ enum="MediaLauncherActivityMediaType">
+ <owner>steimel@chromium.org</owner>
+ <owner>media-dev@chromium.org</owner>
+ <summary>
+ The type of media that a user is opening via the MediaLauncherActivity.
+ </summary>
+</histogram>
+
<histogram base="true" name="MediaRouter.Cast.App.Availability" units="ms">
<!-- Name completed by histogram_suffixes name="MediaRouterSuccess" -->
@@ -40867,7 +43011,7 @@ uploading your change for review.
</histogram>
<histogram name="MediaRouter.Cast.Channel.ConnectResult" enum="BooleanSuccess">
- <owner>zhaobin@chromium.org</owner>
+ <owner>mfoltz@chromium.org</owner>
<summary>
Whether opening Cast channel succeeds or not. Recorded when all opening
channel attempts (including retry attempts) finish.
@@ -40876,7 +43020,7 @@ uploading your change for review.
<histogram name="MediaRouter.Cast.Channel.Error"
enum="MediaRouterCastChannelError">
- <owner>zhaobin@chromium.org</owner>
+ <owner>mfoltz@chromium.org</owner>
<summary>
Errors encountered on a Cast channel. Recorded when a Cast channel fails to
open, or when an opened channel fails to respond to keepalive ping request
@@ -40895,7 +43039,7 @@ uploading your change for review.
<histogram name="MediaRouter.Cast.Discovery.ConnectedDevicesCount"
units="devices">
- <owner>zhaobin@chromium.org</owner>
+ <owner>mfoltz@chromium.org</owner>
<summary>
The number of connected Cast devices. Recorded when browser finishes
discovering Cast devices. Recording happens roughly once per hour.
@@ -40903,7 +43047,7 @@ uploading your change for review.
</histogram>
<histogram name="MediaRouter.Cast.Discovery.KnownDevicesCount" units="devices">
- <owner>zhaobin@chromium.org</owner>
+ <owner>mfoltz@chromium.org</owner>
<summary>
The number of known Cast devices. Recorded when browser finishes discovering
Cast devices. Recording happens roughly once per hour.
@@ -40917,7 +43061,7 @@ uploading your change for review.
</histogram>
<histogram name="MediaRouter.Cast.Mdns.Channel.Open_Failure" units="ms">
- <owner>zhaobin@chromium.org</owner>
+ <owner>mfoltz@chromium.org</owner>
<summary>
Duration in milliseconds taken to fail to open a cast channel. Recorded when
one opening channel attempt fails.
@@ -40925,7 +43069,7 @@ uploading your change for review.
</histogram>
<histogram name="MediaRouter.Cast.Mdns.Channel.Open_Success" units="ms">
- <owner>zhaobin@chromium.org</owner>
+ <owner>mfoltz@chromium.org</owner>
<summary>
Duration in milliseconds taken to successfully open a cast channel. Recorded
when one opening channel attempt succeeds.
@@ -40933,7 +43077,7 @@ uploading your change for review.
</histogram>
<histogram name="MediaRouter.Dial.AvailableDevicesCount" units="devices">
- <owner>zhaobin@chromium.org</owner>
+ <owner>mfoltz@chromium.org</owner>
<summary>
The number of available DIAL devices. Recorded when browser finishes
discovering DIAL devices. Recording happens roughly once per hour.
@@ -40941,7 +43085,7 @@ uploading your change for review.
</histogram>
<histogram name="MediaRouter.Dial.KnownDevicesCount" units="devices">
- <owner>zhaobin@chromium.org</owner>
+ <owner>mfoltz@chromium.org</owner>
<summary>
The number of known DIAL devices. Recorded when browser finishes discovering
DIAL devices. Recording happens roughly once per hour.
@@ -40950,7 +43094,7 @@ uploading your change for review.
<histogram name="MediaRouter.Dial.ParsingError"
enum="MediaRouterDialParsingError">
- <owner>zhaobin@chromium.org</owner>
+ <owner>mfoltz@chromium.org</owner>
<summary>
Error encountered while parsing DIAL device description XML text. Recorded
when utility process returns an invalid DIAL device description object to
@@ -40960,7 +43104,7 @@ uploading your change for review.
<histogram name="MediaRouter.Icon.Click.Location"
enum="MediaRouterDialogOpenOrigin">
- <owner>apacible@chromium.org</owner>
+ <owner>takumif@chromium.org</owner>
<summary>Location the user clicked to open the Media Router dialog.</summary>
</histogram>
@@ -41075,14 +43219,23 @@ uploading your change for review.
</histogram>
<histogram name="MediaRouter.Route.CreationOutcome"
- units="MediaRouterCreateRouteOutcome">
- <owner>apacible@chromium.org</owner>
+ enum="MediaRouterCreateRouteOutcome">
+ <owner>takumif@chromium.org</owner>
<summary>
The number of times a Media Router create route response succeeds or fails.
This breaks down the different failure types in to separate buckets.
</summary>
</histogram>
+<histogram name="MediaRouter.Sink.SearchOutcome" enum="BooleanSuccess">
+ <owner>takumif@chromium.org</owner>
+ <summary>
+ The outcome of querying Media Route Providers for a sink by ID.
+ &quot;Success&quot; indicates that a sink was found. This is recorded when
+ the user attempts to cast to a sink with a manually entered ID.
+ </summary>
+</histogram>
+
<histogram name="MediaRouter.Sink.SelectedType" enum="MediaSinkType">
<owner>takumif@chromium.org</owner>
<summary>
@@ -41093,7 +43246,7 @@ uploading your change for review.
<histogram name="MediaRouter.Source.CastingSource"
enum="MediaRouterSourceTypes">
- <owner>amp@chromium.org</owner>
+ <owner>takumif@chromium.org</owner>
<summary>
The source of a Media Router session. This is recorded to keep track of what
kind of media is being streamed.
@@ -41101,7 +43254,7 @@ uploading your change for review.
</histogram>
<histogram name="MediaRouter.Source.LocalFileFormat" enum="MediaContainers">
- <owner>amp@chromium.org</owner>
+ <owner>takumif@chromium.org</owner>
<summary>
The file format of a local media Media Router session. This is recorded when
a casting session begins to keep track of what kind of media is being
@@ -41110,7 +43263,7 @@ uploading your change for review.
</histogram>
<histogram name="MediaRouter.Source.LocalFileSize" units="MB">
- <owner>amp@chromium.org</owner>
+ <owner>takumif@chromium.org</owner>
<summary>
The file size of a local media Media Router session. This is recorded when a
casting session begins to keep track of what kind of media is being
@@ -41120,7 +43273,7 @@ uploading your change for review.
</histogram>
<histogram name="MediaRouter.Ui.Action.CloseLatency" units="ms">
- <owner>apacible@chromium.org</owner>
+ <owner>takumif@chromium.org</owner>
<summary>
Duration in milliseconds taken from the user opening the Media Router dialog
to the user closing the dialog. This is only recorded if closing the dialog
@@ -41129,7 +43282,7 @@ uploading your change for review.
</histogram>
<histogram name="MediaRouter.Ui.Action.StartLocal.Latency" units="ms">
- <owner>apacible@chromium.org</owner>
+ <owner>takumif@chromium.org</owner>
<summary>
Duration in milliseconds taken from the Media Router dialog showing the sink
list and being populated with at least one device to the user selecting a
@@ -41139,25 +43292,25 @@ uploading your change for review.
<histogram name="MediaRouter.Ui.Action.StartLocalPosition"
enum="MediaRouterSinkPositionLabel">
- <owner>apacible@chromium.org</owner>
+ <owner>takumif@chromium.org</owner>
<summary>The index of the sink that was selected in the sink list.</summary>
</histogram>
<histogram name="MediaRouter.Ui.Action.StartLocalSessionSuccessful"
enum="BooleanSuccess">
- <owner>apacible@chromium.org</owner>
+ <owner>takumif@chromium.org</owner>
<summary>
The number of times a session was successfully started versus failed.
</summary>
</histogram>
<histogram name="MediaRouter.Ui.Action.StopRoute" enum="MediaRouteType">
- <owner>apacible@chromium.org</owner>
+ <owner>takumif@chromium.org</owner>
<summary>The number of times a user stops different types of routes.</summary>
</histogram>
<histogram name="MediaRouter.Ui.Device.Count">
- <owner>apacible@chromium.org</owner>
+ <owner>takumif@chromium.org</owner>
<summary>
Counts the number of devices known and populated to the Media Router dialog
three seconds after the dialog loads. Always expected to be non-negative.
@@ -41173,7 +43326,7 @@ uploading your change for review.
</histogram>
<histogram name="MediaRouter.Ui.Dialog.LoadedWithData" units="ms">
- <owner>apacible@chromium.org</owner>
+ <owner>takumif@chromium.org</owner>
<summary>
Duration in milliseconds taken from the user click to open the Media Router
dialog to initializing the dialog with data.
@@ -41181,22 +43334,22 @@ uploading your change for review.
</histogram>
<histogram name="MediaRouter.Ui.Dialog.Paint" units="ms">
- <owner>apacible@chromium.org</owner>
+ <owner>takumif@chromium.org</owner>
<summary>
Duration in milliseconds taken from a user click to open the Media Router
dialog to the initial paint.
</summary>
</histogram>
-<histogram name="MediaRouter.Ui.FirstAction" units="MediaRouterUserAction">
- <owner>apacible@chromium.org</owner>
+<histogram name="MediaRouter.Ui.FirstAction" enum="MediaRouterUserAction">
+ <owner>takumif@chromium.org</owner>
<summary>
The first action taken by the user after opening the Media Router dialog.
</summary>
</histogram>
<histogram name="MediaRouter.Ui.InitialState" enum="MediaRouterInitialViews">
- <owner>apacible@chromium.org</owner>
+ <owner>takumif@chromium.org</owner>
<summary>
The view that was shown when the Media Router dialog is initially opened.
</summary>
@@ -41204,7 +43357,7 @@ uploading your change for review.
<histogram name="MediaRouter.Ui.Navigate.SourceSelection"
enum="MediaRouterSourceTypes">
- <owner>apacible@chromium.org</owner>
+ <owner>takumif@chromium.org</owner>
<summary>
The number of times the user selects a specific cast source type.
</summary>
@@ -41321,7 +43474,8 @@ uploading your change for review.
</histogram>
<histogram name="Memory.Browser.PrivateSwapFootprint" units="MB">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>erikchen@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
An amount of private memory of the browser process placed in swap (VmSwap).
Available only on Android and Linux.
@@ -41516,6 +43670,7 @@ uploading your change for review.
<!-- Name completed by histogram_suffixes name="ProcessMemoryAllocator2" -->
<owner>erikchen@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
The browser process's memory usage reported by the memory instrumentation
service in MB.
@@ -41525,6 +43680,7 @@ uploading your change for review.
<histogram base="true" name="Memory.Experimental.Browser2.Small" units="KB">
<!-- Name completed by histogram_suffixes name="ProcessMemoryAllocatorSmall2" -->
+ <owner>erikchen@chromium.org</owner>
<owner>ssid@chromium.org</owner>
<summary>
The browser process's memory usage reported by the memory instrumentation
@@ -41606,6 +43762,7 @@ uploading your change for review.
<!-- Name completed by histogram_suffixes name="ProcessMemoryAllocator2" -->
<owner>erikchen@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
The extension process's memory usage reported by the memory instrumentation
service in MB.
@@ -41615,6 +43772,7 @@ uploading your change for review.
<histogram base="true" name="Memory.Experimental.Extension2.Small" units="KB">
<!-- Name completed by histogram_suffixes name="ProcessMemoryAllocatorSmall2" -->
+ <owner>erikchen@chromium.org</owner>
<owner>ssid@chromium.org</owner>
<summary>
The extension process's memory usage reported by the memory instrumentation
@@ -41647,6 +43805,7 @@ uploading your change for review.
<!-- Name completed by histogram_suffixes name="ProcessMemoryAllocator2" -->
<owner>erikchen@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
The gpu process's memory usage reported by the memory instrumentation
service in MB.
@@ -41656,6 +43815,7 @@ uploading your change for review.
<histogram base="true" name="Memory.Experimental.Gpu2.Small" units="KB">
<!-- Name completed by histogram_suffixes name="ProcessMemoryAllocatorSmall2" -->
+ <owner>erikchen@chromium.org</owner>
<owner>ssid@chromium.org</owner>
<summary>
The gpu process's memory usage reported by the memory instrumentation
@@ -41663,6 +43823,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Memory.Experimental.OomIntervention.BrowserMonitorStatus"
+ enum="OomInterventionBrowserMonitorStatus" expires_after="M70">
+ <owner>ssid@chromium.org</owner>
+ <summary>
+ Records the status of OOM intervention if the feature is turned on, with
+ various reasons for failure, in the browser process. Recorded once at
+ browser startup.
+ </summary>
+</histogram>
+
<histogram name="Memory.Experimental.OomIntervention.InterventionStateOnCrash"
enum="OomInterventionUserDecision">
<owner>bashi@chromium.org</owner>
@@ -41711,6 +43881,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Memory.Experimental.OomIntervention.RendererEnabledStatus"
+ enum="OomInterventionRendererStatus" expires_after="M70">
+ <owner>ssid@chromium.org</owner>
+ <summary>
+ Records the status of OOM intervention in renderer process if the feature is
+ turned on, with various reasons for failure. Recorded at each navigation or
+ reload.
+ </summary>
+</histogram>
+
<histogram
name="Memory.Experimental.OomIntervention.RendererGoneAfterDetectionTime"
units="ms">
@@ -41726,6 +43906,7 @@ uploading your change for review.
name="Memory.Experimental.OomIntervention.RendererPrivateMemoryFootprintAtOOM"
units="MB">
<owner>ssid@chromium.org</owner>
+ <owner>bashi@chromium.org</owner>
<summary>
The renderer process' private memory footprint when a foreground OOM occurs.
This was last recorded metric by renderer a few seconds before getting
@@ -41737,12 +43918,48 @@ uploading your change for review.
name="Memory.Experimental.OomIntervention.RendererSwapFootprintAtOOM"
units="MB">
<owner>ssid@chromium.org</owner>
+ <owner>bashi@chromium.org</owner>
<summary>
The renderer process' swap size when a foreground OOM occurs. This was last
recorded metric by renderer a few seconds before getting killed.
</summary>
</histogram>
+<histogram
+ name="Memory.Experimental.OomIntervention.RendererTimeSinceLastNavigationAtOOM"
+ units="seconds">
+ <owner>ssid@chromium.org,haraken@chromium.org</owner>
+ <summary>
+ Records the time since last main frame navigation start on the renderer
+ process when it OOMs in foreground visible state. Record 0 if no navigation
+ was started.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Experimental.OomIntervention.RendererVmSizeAtOOM"
+ units="MB" expires_after="2018-06-12">
+ <obsolete>
+ Replaced by Memory.Experimental.OomIntervention.RendererVmSizeAtOOMLarge.
+ </obsolete>
+ <owner>ssid@chromium.org</owner>
+ <summary>
+ The renderer process' virtual memory usage, when a foreground OOM occurs.
+ This was last recorded metric by renderer a few seconds before getting
+ killed.
+ </summary>
+</histogram>
+
+<histogram name="Memory.Experimental.OomIntervention.RendererVmSizeAtOOMLarge"
+ units="MB">
+ <owner>ssid@chromium.org</owner>
+ <owner>bashi@chromium.org</owner>
+ <summary>
+ The renderer process' virtual memory usage, when a foreground OOM occurs.
+ This was last recorded metric by renderer a few seconds before getting
+ killed.
+ </summary>
+</histogram>
+
<histogram name="Memory.Experimental.OomIntervention.UserDecision"
enum="OomInterventionUserDecision">
<owner>bashi@chromium.org</owner>
@@ -41800,6 +44017,7 @@ uploading your change for review.
<!-- Name completed by histogram_suffixes name="ProcessMemoryAllocator2" -->
<owner>erikchen@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
The renderer process's memory usage reported by the memory instrumentation
service in MB.
@@ -41809,6 +44027,7 @@ uploading your change for review.
<histogram base="true" name="Memory.Experimental.Renderer2.Small" units="KB">
<!-- Name completed by histogram_suffixes name="ProcessMemoryAllocatorSmall2" -->
+ <owner>erikchen@chromium.org</owner>
<owner>ssid@chromium.org</owner>
<summary>
The renderer process's memory usage reported by the memory instrumentation
@@ -41851,6 +44070,7 @@ uploading your change for review.
<histogram name="Memory.Experimental.Total2.PrivateMemoryFootprint" units="MB">
<owner>erikchen@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
A rough estimate of the private memory footprint of all processes.
</summary>
@@ -41871,6 +44091,7 @@ uploading your change for review.
<histogram name="Memory.Extension.PrivateMemoryFootprint" units="MB">
<owner>erikchen@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
A rough estimate of the private memory footprint of the extension process.
Recorded once per process per UMA ping.
@@ -41879,6 +44100,7 @@ uploading your change for review.
<histogram name="Memory.Extension.SharedMemoryFootprint" units="MB">
<owner>erikchen@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
A rough estimate of the shared memory footprint of the extension process.
Recorded once per process per UMA ping.
@@ -41929,6 +44151,7 @@ uploading your change for review.
<histogram name="Memory.Gpu.PrivateMemoryFootprint" units="MB">
<owner>erikchen@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
A rough estimate of the private memory footprint of the gpu process.
Recorded once per UMA ping.
@@ -41936,7 +44159,8 @@ uploading your change for review.
</histogram>
<histogram name="Memory.Gpu.PrivateSwapFootprint" units="MB">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>erikchen@chromium.org</owner>
+ <owner>ssid@chormium.org</owner>
<summary>
An amount of private memory of the GPU process placed in swap (VmSwap).
Available only on Android and Linux.
@@ -41945,6 +44169,7 @@ uploading your change for review.
<histogram name="Memory.Gpu.SharedMemoryFootprint" units="MB">
<owner>erikchen@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
A rough estimate of the shared memory footprint of the gpu process. Recorded
once per UMA ping.
@@ -41971,6 +44196,32 @@ uploading your change for review.
<summary>Size of messages received by IPC::ChannelReader.</summary>
</histogram>
+<histogram name="Memory.MovableStringParkingAction" enum="ParkingAction">
+ <owner>lizeb@chromium.org</owner>
+ <summary>
+ Recorded each time a Movable String is (un)parked, with the context:
+ foreground/background.
+ </summary>
+</histogram>
+
+<histogram name="Memory.MovableStringsCount" units="count">
+ <owner>lizeb@chromium.org</owner>
+ <summary>
+ This records the number of movable Javascript source string resources in a
+ given renderer, at the time page is backgrounded. Recorded alongside
+ Memory.MovableStringsTotalSizeKb.
+ </summary>
+</histogram>
+
+<histogram name="Memory.MovableStringsTotalSizeKb" units="KB">
+ <owner>lizeb@chromium.org</owner>
+ <summary>
+ This records the total size of movable Javascript source string resources in
+ a given renderer, at the time page is backgrounded. Recorded alongside
+ Memory.MovableStringsCount.
+ </summary>
+</histogram>
+
<histogram name="Memory.NativeClient" units="KB">
<obsolete>
Deprecated 11/2017. No direct replacement.
@@ -42278,6 +44529,7 @@ uploading your change for review.
<histogram name="Memory.Renderer.PrivateMemoryFootprint" units="MB">
<owner>erikchen@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
A rough estimate of the private memory footprint of the renderer process.
Recorded once per process per UMA ping.
@@ -42286,6 +44538,7 @@ uploading your change for review.
<histogram name="Memory.Renderer.SharedMemoryFootprint" units="MB">
<owner>erikchen@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
A rough estimate of the shared memory footprint of the renderer process.
Recorded once per process per UMA ping.
@@ -42851,6 +45104,7 @@ uploading your change for review.
<histogram name="Memory.Total.PrivateMemoryFootprint" units="MB">
<owner>erikchen@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
A rough estimate of the private memory footprint of all processes. Recorded
once per UMA ping.
@@ -42859,6 +45113,7 @@ uploading your change for review.
<histogram name="Memory.Total.SharedMemoryFootprint" units="MB">
<owner>erikchen@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
A rough estimate of the shared memory footprint of all processes. Recorded
once per UMA ping.
@@ -42972,7 +45227,7 @@ uploading your change for review.
</histogram>
<histogram name="MemoryAndroid.LowRamDevice" enum="Boolean">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
<summary>
Whether Chrome is running in low ram mode. This histogram is reported on
every upload by Android devices. A device is considered low-RAM if it has
@@ -43047,6 +45302,62 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="MessageLoop.DelayedTaskQueue.PendingTasksCountOnIdle">
+ <obsolete>
+ Deprecated as of 07/2018.
+ </obsolete>
+ <owner>gab@chromium.org</owner>
+ <summary>
+ The size of the delayed task queue when the loop becomes idle. Diagnosis
+ metric for https://crbug.com/850450#c4.
+ </summary>
+</histogram>
+
+<histogram name="MessageLoop.DelayedTaskQueue.PostedDelay" units="ms">
+ <obsolete>
+ Deprecated as of 07/2018.
+ </obsolete>
+ <owner>gab@chromium.org</owner>
+ <summary>
+ Reports the delay of a delayed task posted to a MessageLoop. Reported once
+ per delayed task. Diagnosis metric for https://crbug.com/850450#c4.
+ </summary>
+</histogram>
+
+<histogram name="MessageLoop.DelayedTaskQueueForUI.PendingTasksCountOnIdle">
+ <owner>gab@chromium.org</owner>
+ <summary>
+ The size of the delayed task queue when the loop becomes idle on a UI
+ thread. Diagnosis metric for https://crbug.com/850450#c4. Note: this metric
+ is a bit broken on Mac OSX as CFRunLoop doesn't deterministically invoke
+ MessageLoop::DoIdleWork().
+ </summary>
+</histogram>
+
+<histogram name="MessageLoop.ScheduledSleep.Completed" units="ms">
+ <obsolete>
+ Deprecated as of 07/2018.
+ </obsolete>
+ <owner>gab@chromium.org</owner>
+ <summary>
+ Reports the delay for which the MessageLoop successfully slept until an
+ upcoming delayed task. Reported each time a MessageLoop successfully sleeps
+ until the next delayed task.
+ </summary>
+</histogram>
+
+<histogram name="MessageLoop.ScheduledSleep.Interrupted" units="ms">
+ <obsolete>
+ Deprecated as of 07/2018.
+ </obsolete>
+ <owner>gab@chromium.org</owner>
+ <summary>
+ Reports the delay for which the MessageLoop had planned to sleep (next
+ delayed task) before it was woken up early. Reported each time a MessageLoop
+ is woken up early.
+ </summary>
+</histogram>
+
<histogram name="Mist.SwitchResult" enum="MistSwitchResult">
<owner>benchan@chromium.org</owner>
<summary>
@@ -43218,7 +45529,9 @@ uploading your change for review.
<owner>xingliu@chromium.org</owner>
<summary>
Records the directory type when the user selects the download directory
- through download location dialog.
+ through download location dialog or selects the download directory in
+ download preference. May be recorded even when the user didn't download
+ anything.
</summary>
</histogram>
@@ -43355,6 +45668,13 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="MobileIntent.PageLoadDueToExternalApp" enum="ClientAppId">
+ <owner>tedchoc@chromium.org</owner>
+ <summary>
+ Android: Count of page loads started by intents from external apps.
+ </summary>
+</histogram>
+
<histogram name="MobileOmnibox.PressedClipboardSuggestionAge" units="ms">
<owner>jif@chromium.org</owner>
<owner>mpearson@chromium.org</owner>
@@ -43428,6 +45748,20 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="MobileStartup.ColdStartupIntent" enum="MobileStartupIntent">
+ <owner>tedchoc@chromium.org</owner>
+ <summary>
+ For cold starts of Chrome (native not initialized at the time of intent),
+ record in ChromeTabbedActivity whether the intent had the effect of opening
+ a new page or was a restore of last session.
+ </summary>
+</histogram>
+
+<histogram name="MobileStartup.DailyLaunchCount">
+ <owner>charliema@chromium.org</owner>
+ <summary>The count of launching Chrome mobile app within a day.</summary>
+</histogram>
+
<histogram name="MobileStartup.IntentToCreationTime" units="ms">
<owner>twellington@chromium.org</owner>
<summary>
@@ -43437,6 +45771,13 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="MobileStartup.LaunchType" enum="LaunchType">
+ <owner>charliema@chromium.org</owner>
+ <summary>
+ The type of launching Chrome mobile app, e.g launch by hitting icon.
+ </summary>
+</histogram>
+
<histogram name="MobileStartup.LoadedHomepageOnColdStart" enum="BooleanIsNtp"
expires_after="M72">
<owner>tedchoc@chromium.org</owner>
@@ -43517,6 +45858,10 @@ uploading your change for review.
</histogram>
<histogram base="true" name="MobileStartup.ToolbarFirstDrawTime" units="ms">
+ <obsolete>
+ Deprecated and renamed to MobileStartup.ToolbarFirstDrawTime2 due to double
+ reporting bug (see https://crbug.com/857508).
+ </obsolete>
<owner>yusufo@chromium.org</owner>
<summary>
Android: The time it takes from launch to the completion of first draw for
@@ -43524,8 +45869,39 @@ uploading your change for review.
</summary>
</histogram>
+<histogram base="true" name="MobileStartup.ToolbarFirstDrawTime2" units="ms">
+ <owner>yusufo@chromium.org</owner>
+ <summary>
+ Android: The time it takes from launch to the completion of first draw for
+ Toolbar. This excludes activity creation time spent in framework.
+ </summary>
+</histogram>
+
+<histogram base="true" name="MobileStartup.ToolbarFirstFocusStartupState"
+ enum="MobileStartupToolbarFirstFocusStartupState">
+ <owner>mheikal@chromium.org</owner>
+ <summary>
+ Android: The state of chrome startup at the first time the user focuses the
+ omnibox, if the user does so within the first 30s of the launch (excluding
+ activity creation time spent in the framework).
+ </summary>
+</histogram>
+
<histogram base="true" name="MobileStartup.ToolbarFirstFocusTime" units="ms">
- <owner>mariakhomenko@chromium.org</owner>
+ <obsolete>
+ Deprecated and renamed to MobileStartup.ToolbarFirstFocusTime2 due to double
+ reporting bug (see https://crbug.com/857508).
+ </obsolete>
+ <owner>pasko@chromium.org</owner>
+ <summary>
+ Android: The time it takes from launch to the first time the user focuses
+ the omnibox if the user does so within first 30s of the launch. This
+ excludes activity creation time spent in framework.
+ </summary>
+</histogram>
+
+<histogram base="true" name="MobileStartup.ToolbarFirstFocusTime2" units="ms">
+ <owner>pasko@chromium.org</owner>
<summary>
Android: The time it takes from launch to the first time the user focuses
the omnibox if the user does so within first 30s of the launch. This
@@ -43534,12 +45910,71 @@ uploading your change for review.
</histogram>
<histogram base="true" name="MobileStartup.ToolbarInflationTime" units="ms">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>pasko@chromium.org</owner>
<summary>
Android: The time spent performing toolbar layout inflation.
</summary>
</histogram>
+<histogram name="ModuleBlacklistCache.BlacklistPathUpdated"
+ enum="BooleanSuccess">
+ <owner>pmonette@chromium.org</owner>
+ <summary>
+ Records the result of writing the path of the module blacklist cache to the
+ registry so that chrome_elf.dll can use it. A value is emitted every time
+ the cache is updated because another instance of Chrome with a different
+ User Data directory could have overwritten the path to point to their own
+ version of the cache.
+ </summary>
+</histogram>
+
+<histogram name="ModuleBlacklistCache.BlacklistStatus"
+ enum="ModuleBlacklistStatus">
+ <owner>pmonette@chromium.org</owner>
+ <summary>
+ The status of a blacklisted module in the process. Recorded when the cache
+ is updated.
+ </summary>
+</histogram>
+
+<histogram name="ModuleBlacklistCache.DeleteResult" enum="BooleanSuccess">
+ <owner>pmonette@chromium.org</owner>
+ <summary>
+ The result of deleting the module blacklist cache when third-party module
+ blocking is disabled. Attempting to delete an empty file is considered a
+ success.
+ </summary>
+</histogram>
+
+<histogram name="ModuleBlacklistCache.ExpectedMD5Digest" enum="Boolean">
+ <owner>pmonette@chromium.org</owner>
+ <summary>
+ Records whether the MD5 digest of the module blacklist cache matched the one
+ recorded in the Local State file.
+ </summary>
+</histogram>
+
+<histogram name="ModuleBlacklistCache.ModuleCount" units="modules">
+ <owner>pmonette@chromium.org</owner>
+ <summary>
+ Records the number of modules in the module blacklist cache at the time it
+ was written to disk.
+ </summary>
+</histogram>
+
+<histogram name="ModuleBlacklistCache.ReadResult"
+ enum="ModuleBlacklistCacheReadResult">
+ <owner>pmonette@chromium.org</owner>
+ <summary>
+ The result of reading the current module blacklist cache while updating it.
+ </summary>
+</histogram>
+
+<histogram name="ModuleBlacklistCache.WriteResult" enum="BooleanSuccess">
+ <owner>pmonette@chromium.org</owner>
+ <summary>The result of writing the updated module blacklist cache.</summary>
+</histogram>
+
<histogram name="ModuleIntegrityVerification.BytesModified" units="bytes">
<owner>anthonyvd@chromium.org</owner>
<summary>
@@ -43694,7 +46129,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Mouse.PointerSensitivity.Changed" enum="PointerSensitivity">
+<histogram name="Mouse.PointerSensitivity.Changed" enum="PointerSensitivity"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Tracks mouse sensitivity setting changes by the user. This replaces the old
@@ -43702,7 +46138,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Mouse.PointerSensitivity.Started" enum="PointerSensitivity">
+<histogram name="Mouse.PointerSensitivity.Started" enum="PointerSensitivity"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Tracks mouse sensitivity setting on startup. This replaces the old
@@ -43968,7 +46405,7 @@ uploading your change for review.
<summary>TBD</summary>
</histogram>
-<histogram name="MPArch.RWH_RepaintDelta">
+<histogram name="MPArch.RWH_RepaintDelta" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>TBD</summary>
</histogram>
@@ -44563,6 +47000,48 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="NativeSmbFileShare.MountCount">
+ <owner>zentaro@chromium.org</owner>
+ <summary>
+ The number of active mounts that a user has. This is recorded after a share
+ has been successfully mounted.
+ </summary>
+</histogram>
+
+<histogram name="NativeSmbFileShare.MountResult"
+ enum="NativeSmbFileShare_MountResult">
+ <owner>zentaro@chromium.org</owner>
+ <summary>
+ The result of the mount operation for Native SMB File Share. This is
+ recorded after the D-Bus call to Mount returns.
+ </summary>
+</histogram>
+
+<histogram name="NativeSmbFileShare.ReadDirectoryCount">
+ <owner>zentaro@chromium.org</owner>
+ <summary>
+ The number of entries read when calling ReadDirectory. This is recorded
+ after the D-Bus call to ReadDirectory returns.
+ </summary>
+</histogram>
+
+<histogram name="NativeSmbFileShare.ReadDirectoryDuration" units="ms">
+ <owner>zentaro@chromium.org</owner>
+ <summary>
+ The duration of ReadDirectory call to SmbProvider in milliseconds. This is
+ recorded after the D-Bus call returns.
+ </summary>
+</histogram>
+
+<histogram name="NativeSmbFileShare.RemountResult"
+ enum="NativeSmbFileShare_MountResult">
+ <owner>zentaro@chromium.org</owner>
+ <summary>
+ The result of the Remount operation during startup. This is recorded after
+ the D-Bus call to Remount returns.
+ </summary>
+</histogram>
+
<histogram name="Navigation.BackForward.CacheFlags" enum="NavigationCacheEnum">
<owner>clamy@chromium.org</owner>
<summary>The cache flags set on back-forward navigations.</summary>
@@ -44712,15 +47191,25 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Navigation.Intercept.Ignored" enum="Boolean">
+ <owner>csharrison@chromium.org</owner>
+ <summary>
+ Records whether the InterceptNavigationThrottle ignored the navigation. This
+ is recorded at the end of every navigation the throttle observes.
+ </summary>
+</histogram>
+
<histogram name="Navigation.Intercept.WillStart" units="microseconds">
<owner>csharrison@chromium.org</owner>
<summary>
The microseconds it takes for the InterceptNavigationThrottle to determine
if the navigation should be ignored, at WillStartRequest time.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -44873,6 +47362,9 @@ uploading your change for review.
<histogram
name="Navigation.ResourceHandler.ProceedWithResponseUntilFirstReadCompleted"
units="ms">
+ <obsolete>
+ Obsolete as of 06/2018.
+ </obsolete>
<owner>arthursonzogni@chromium.org</owner>
<owner>clamy@chromium.org</owner>
<owner>nasko@chromium.org</owner>
@@ -44885,6 +47377,9 @@ uploading your change for review.
<histogram
name="Navigation.ResourceHandler.ResponseStartedUntilProceedWithResponse"
units="ms">
+ <obsolete>
+ Obsolete as of 06/2018.
+ </obsolete>
<owner>arthursonzogni@chromium.org</owner>
<owner>clamy@chromium.org</owner>
<owner>nasko@chromium.org</owner>
@@ -44895,7 +47390,7 @@ uploading your change for review.
</histogram>
<histogram name="Navigation.Scheduled.MaybeCausedAbort"
- enum="ScheduledNavigationType">
+ enum="ScheduledNavigationType" expires_after="2018-08-30">
<owner>csharrison@chromium.org</owner>
<summary>
window.location and other scheduled navigation changes can cause the current
@@ -44904,7 +47399,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Navigation.Scheduled.MaybeCausedAbort.Time" units="ms">
+<histogram name="Navigation.Scheduled.MaybeCausedAbort.Time" units="ms"
+ expires_after="2018-08-30">
<owner>csharrison@chromium.org</owner>
<summary>
window.location and other scheduled navigation changes can cause the current
@@ -45018,30 +47514,45 @@ uploading your change for review.
</histogram>
<histogram name="Navigation.UI_OnCommitProvisionalLoad.Intent" units="ms">
+ <obsolete>
+ Deprecated 06/2018 in favor of PageLoad metrics.
+ </obsolete>
<owner>clamy@chromium.org</owner>
<summary>
- Time between receiving an Android Intent and the navigation commit.
+ Obsolete. Time between receiving an Android Intent and the navigation
+ commit.
</summary>
</histogram>
<histogram name="Navigation.UI_OnCommitProvisionalLoad.Link" units="ms">
+ <obsolete>
+ Deprecated 06/2018 in favor of PageLoad metrics.
+ </obsolete>
<owner>clamy@chromium.org</owner>
- <summary>Time between clicking on a link and the navigation commit.</summary>
+ <summary>
+ Obsolete. Time between clicking on a link and the navigation commit.
+ </summary>
</histogram>
<histogram name="Navigation.UI_OnLoadComplete.Intent" units="ms">
+ <obsolete>
+ Deprecated 06/2018 in favor of PageLoad metrics.
+ </obsolete>
<owner>clamy@chromium.org</owner>
<summary>
- Time between receiving an Android intent and the document load complete
- event for a navigation in the main frame.
+ Obsolete. Time between receiving an Android intent and the document load
+ complete event for a navigation in the main frame.
</summary>
</histogram>
<histogram name="Navigation.UI_OnLoadComplete.Link" units="ms">
+ <obsolete>
+ Deprecated 06/2018 in favor of PageLoad metrics.
+ </obsolete>
<owner>clamy@chromium.org</owner>
<summary>
- Time between clicking on a link and the document load complete event for a
- navigation in the main frame.
+ Obsolete. Time between clicking on a link and the document load complete
+ event for a navigation in the main frame.
</summary>
</histogram>
@@ -45080,6 +47591,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FastestRTTOn2G" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of the fastest round-trip-time seen on a 2G connection,
@@ -45093,6 +47607,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FastestRTTOn3G" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of the fastest round-trip-time seen on a 3G connection,
@@ -45106,6 +47623,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FastestRTTOn4G" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of the fastest round-trip-time seen on a 4G connection,
@@ -45119,6 +47639,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FastestRTTOnBluetooth" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of the fastest round-trip-time seen on a Bluetooth
@@ -45132,6 +47655,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FastestRTTOnEthernet" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of the fastest round-trip-time seen on an Ethernet
@@ -45145,6 +47671,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FastestRTTOnNone" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of the fastest round-trip-time seen while the
@@ -45159,6 +47688,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FastestRTTOnUnknown" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of the fastest round-trip-time seen on an unknown connection
@@ -45172,6 +47704,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FastestRTTOnWifi" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of the fastest round-trip-time seen on a Wifi connection,
@@ -45185,6 +47720,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FirstReadOn2G" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between switching to a 2G connection and receiving the first network
@@ -45198,6 +47736,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FirstReadOn3G" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between switching to a 3G connection and receiving the first network
@@ -45211,6 +47752,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FirstReadOn4G" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between switching to a 4G connection and receiving the first network
@@ -45224,6 +47768,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FirstReadOnBluetooth" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between switching to a Bluetooth connection and receiving the first
@@ -45237,6 +47784,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FirstReadOnEthernet" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between switching to an Ethernet connection and receiving the first
@@ -45250,6 +47800,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FirstReadOnNone" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between disconnecting and receiving the first network data.
@@ -45262,6 +47815,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FirstReadOnUnknown" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between switching to an unknown connection type and receiving the first
@@ -45275,6 +47831,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.FirstReadOnWifi" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between switching to a Wifi connection and receiving the first network
@@ -45288,6 +47847,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.KBTransferedOn2G" units="KB">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How much data was transfered while connected via a 2G connection, before the
@@ -45301,6 +47863,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.KBTransferedOn3G" units="KB">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How much data was transfered while connected via a 3G connection, before the
@@ -45314,6 +47879,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.KBTransferedOn4G" units="KB">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How much data was transfered while connected via a 4G connection, before the
@@ -45327,6 +47895,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.KBTransferedOnBluetooth" units="KB">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How much data was transfered while connected via a Bluetooth connection,
@@ -45340,6 +47911,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.KBTransferedOnEthernet" units="KB">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How much data was transfered while connected via an Ethernet connection,
@@ -45353,6 +47927,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.KBTransferedOnNone" units="KB">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How much data was transfered while the NetworkChangeNotifier thought there
@@ -45367,6 +47944,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.KBTransferedOnUnknown" units="KB">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How much data was transfered while connected via an unknown connection type,
@@ -45380,6 +47960,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.KBTransferedOnWifi" units="KB">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How much data was transfered while connected via a Wifi connection, before
@@ -45393,6 +47976,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.PeakKbpsOn2G" units="Kbps">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of peak throughput seen on a 2G connection, before the
@@ -45406,6 +47992,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.PeakKbpsOn3G" units="Kbps">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of peak throughput seen on a 3G connection, before the
@@ -45419,6 +48008,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.PeakKbpsOn4G" units="Kbps">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of peak throughput seen on a 4G connection, before the
@@ -45432,6 +48024,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.PeakKbpsOnBluetooth" units="Kbps">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of peak throughput seen on a Bluetooth connection, before the
@@ -45445,6 +48040,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.PeakKbpsOnEthernet" units="Kbps">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of peak throughput seen on an Ethernet connection, before the
@@ -45458,6 +48056,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.PeakKbpsOnNone" units="Kbps">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of peak throughput seen while the NetworkChangeNotifier
@@ -45472,6 +48073,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.PeakKbpsOnUnknown" units="Kbps">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of peak throughput seen on an unknown connection type, before
@@ -45485,6 +48089,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.PeakKbpsOnWifi" units="Kbps">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Rough estimate of peak throughput seen on a Wifi connection, before the
@@ -45498,6 +48105,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.TimeOn2G" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How long was spent connected via a 2G connection, before the
@@ -45511,6 +48121,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.TimeOn3G" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How long was spent connected via a 3G connection, before the
@@ -45524,6 +48137,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.TimeOn4G" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How long was spent connected via a 4G connection, before the
@@ -45537,6 +48153,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.TimeOnBluetooth" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How long was spent connected via a Bluetooth connection, before the
@@ -45550,6 +48169,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.TimeOnEthernet" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How long was spent connected via an Ethernet connection, before the
@@ -45563,6 +48185,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.TimeOnNone" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How long was spent disconnected, before the NetworkChangeNotifier detected a
@@ -45576,6 +48201,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.TimeOnUnknown" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How long was spent connected via an unknown connection type, before the
@@ -45589,6 +48217,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.CM.TimeOnWifi" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
How long was spent connected via a Wifi connection, before the
@@ -45602,6 +48233,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.ConnectionTypeChangeToIPAddressChange" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time from ConnectionTypeChanged message until IPAddressChanged message.
@@ -45609,6 +48243,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.DNSConfigChange" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>Time between DNS configuration change messages.</summary>
</histogram>
@@ -45691,11 +48328,17 @@ uploading your change for review.
</histogram>
<histogram name="NCN.IPAddressChange" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>Time between IP address change messages.</summary>
</histogram>
<histogram name="NCN.IPAddressChangeToConnectionTypeChange" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time from IPAddressChanged message until ConnectionTypeChanged message.
@@ -45703,6 +48346,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.NetworkOfflineChange" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between going online until we go offline change messages, using new
@@ -45711,6 +48357,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.NetworkOnlineChange" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between going offline until we go online change messages, using new
@@ -45731,6 +48380,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.OfflineChange" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between going online until we go offline change messages.
@@ -45738,6 +48390,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.OfflineDataRecv" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between when we thought we went offline and when we received some
@@ -45746,6 +48401,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.OfflineDataRecvAny5sBeforeOnline">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Count of how many times we received network data (a URLRequest read
@@ -45755,6 +48413,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.OfflineDataRecvUntilOnline" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between when we received the last network data (a URLRequest read
@@ -45763,6 +48424,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.OfflinePolls">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Count of how many times we polled the online/offline status before detecting
@@ -45771,6 +48435,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.OnlineChange" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between going offline until we go online change messages.
@@ -45778,6 +48445,9 @@ uploading your change for review.
</histogram>
<histogram name="NCN.PollingOfflineDataRecv" units="ms">
+ <obsolete>
+ Deprecated 6/2018.
+ </obsolete>
<owner>pauljensen@chromium.org</owner>
<summary>
Time between when we thought we went offline and when we received some
@@ -45848,7 +48518,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.AlternativeServiceServers.MoreOrEqualCacheEntries">
+<histogram name="Net.AlternativeServiceServers.MoreOrEqualCacheEntries"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The difference between the size of alternative service mappings in cache and
@@ -46544,6 +49215,30 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Net.CertificateTransparency.SCT.SingleVerificationTime"
+ units="microseconds" expires_after="M70">
+ <owner>estark@chromium.org</owner>
+ <owner>rsleevi@chromium.org</owner>
+ <summary>
+ Time to verify a single SCT (Signed Certificate Timestamps) when setting up
+ a TLS connection. Recorded each time a single SCT is verified. Includes not
+ just the signature verification but also other operations that are involved
+ in verifying an SCT, such as notifying observers and looking up the log that
+ issued the SCT.
+ </summary>
+</histogram>
+
+<histogram name="Net.CertificateTransparency.SCT.VerificationTime"
+ units="microseconds" expires_after="M70">
+ <owner>estark@chromium.org</owner>
+ <owner>rsleevi@chromium.org</owner>
+ <summary>
+ Time to verify the SCTs (Signed Certificate Timestamps) when setting up a
+ TLS connection. Recorded on each connection setup where at least one SCT is
+ verified.
+ </summary>
+</histogram>
+
<histogram name="Net.CertificateTransparency.SCTOrigin" enum="SCTOrigin">
<owner>eranm@chromium.org</owner>
<summary>
@@ -47900,6 +50595,9 @@ uploading your change for review.
</histogram>
<histogram name="Net.ErrAborted.ReceivedBytes" units="bytes">
+ <obsolete>
+ Removed from Chromium as of 2018/7/2.
+ </obsolete>
<owner>csharrison@chromium.org</owner>
<summary>
The TotalReceivedBytes() at the time the request finishes with ERR_ABORTED.
@@ -47907,6 +50605,9 @@ uploading your change for review.
</histogram>
<histogram name="Net.ErrAborted.SentBytes" units="bytes">
+ <obsolete>
+ Removed from Chromium as of 2018/7/2.
+ </obsolete>
<owner>csharrison@chromium.org</owner>
<summary>
The TotalSentBytes() at the time the request finishes with ERR_ABORTED.
@@ -47930,6 +50631,9 @@ uploading your change for review.
</histogram>
<histogram name="Net.ErrorCodesForHTTPSGoogleMainFrame2" enum="NetErrorCodes">
+ <obsolete>
+ Deprecated as of 7/2018, replaced by Net.ErrorCodesForHTTPSGoogleMainFrame3.
+ </obsolete>
<owner>mmenke@chromium.org</owner>
<summary>
Positive net error codes that requests for pages end with, including net::OK
@@ -47939,7 +50643,33 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Net.ErrorCodesForHTTPSGoogleMainFrame3" enum="NetErrorCodes">
+ <owner>mmenke@chromium.org</owner>
+ <summary>
+ Positive net error codes that requests for pages end with, including net::OK
+ and net::ERR_ABORTED. This only counts loads in &quot;main frames&quot; for
+ https://www.google.com (it does not for example count the error codes for
+ subresoures on a page). It excludes main frame navigations that are
+ converted to downloads (unless they fail / are aborted before it's known
+ that they would be a download), and requests handled externally (like mailto
+ links).
+ </summary>
+</histogram>
+
<histogram name="Net.ErrorCodesForImages" enum="NetErrorCodes">
+ <obsolete>
+ Deprecated as of 7/2018, replaced by Net.ErrorCodesForImages2, which is
+ recorded in a net-service friendly way.
+ </obsolete>
+ <owner>skonig@chromium.org</owner>
+ <owner>hbengali@chromium.org</owner>
+ <summary>
+ Net error codes that requests for images end with, including net::OK and
+ net:ERR_ABORTED.
+ </summary>
+</histogram>
+
+<histogram name="Net.ErrorCodesForImages2" enum="NetErrorCodes">
<owner>skonig@chromium.org</owner>
<owner>hbengali@chromium.org</owner>
<summary>
@@ -47978,6 +50708,10 @@ uploading your change for review.
</histogram>
<histogram name="Net.ErrorCodesForMainFrame3" enum="NetErrorCodes">
+ <obsolete>
+ Deprecated as of 7/2018, replaced by Net.ErrorCodesForMainFrame4, which is
+ recorded in a net-service friendly way.
+ </obsolete>
<owner>mmenke@chromium.org</owner>
<summary>
Positive net error codes that requests for pages end with, including net::OK
@@ -47986,6 +50720,18 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Net.ErrorCodesForMainFrame4" enum="NetErrorCodes">
+ <owner>mmenke@chromium.org</owner>
+ <summary>
+ Positive net error codes that requests for pages end with, including net::OK
+ and net::ERR_ABORTED. This only counts loads in &quot;main frames&quot; (it
+ does not for example count the error codes for subresoures on a page). It
+ excludes main frame navigations that are converted to downloads (unless they
+ fail / are aborted before it's known that they would be a download), and
+ requests handled externally (like mailto links).
+ </summary>
+</histogram>
+
<histogram name="Net.ErrorCodesForSubresources" enum="NetErrorCodes">
<obsolete>
Deprecated as of 2012/5/16, replaced by Net.ErrorCodesForSubresources2,
@@ -47999,6 +50745,18 @@ uploading your change for review.
</histogram>
<histogram name="Net.ErrorCodesForSubresources2" enum="NetErrorCodes">
+ <obsolete>
+ Deprecated as of 7/2018, replaced by Net.ErrorCodesForSubresources3, which
+ is recorded in a net-service friendly way.
+ </obsolete>
+ <owner>mmenke@chromium.org</owner>
+ <summary>
+ Net error codes that requests for &quot;subresources&quot; end with,
+ including net::OK and net::ERR_ABORTED.
+ </summary>
+</histogram>
+
+<histogram name="Net.ErrorCodesForSubresources3" enum="NetErrorCodes">
<owner>mmenke@chromium.org</owner>
<summary>
Net error codes that requests for &quot;subresources&quot; end with,
@@ -48008,6 +50766,22 @@ uploading your change for review.
<histogram name="Net.ErrorCodesForTLS13ExperimentMainFrame"
enum="NetErrorCodes">
+ <obsolete>
+ Deprecated as of 7/2018, replaced by
+ Net.ErrorCodesForTLS13ExperimentMainFrame2, which is recorded in a
+ net-service friendly way.
+ </obsolete>
+ <owner>svaldez@chromium.org</owner>
+ <summary>
+ Positive net error codes that requests for pages end with, including net::OK
+ and net::ERR_ABORTED. This only counts loads in &quot;main frames&quot; for
+ endpoints used in the initial TLS 1.3 deployment. Subresources or main frame
+ navigations to other origins are not included.
+ </summary>
+</histogram>
+
+<histogram name="Net.ErrorCodesForTLS13ExperimentMainFrame2"
+ enum="NetErrorCodes">
<owner>svaldez@chromium.org</owner>
<summary>
Positive net error codes that requests for pages end with, including net::OK
@@ -48328,7 +51102,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.FoundSystemTrustRootsAndroid" enum="Boolean">
+<histogram name="Net.FoundSystemTrustRootsAndroid" enum="Boolean"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Whether or not system installed trust anchors could be distinguished from
@@ -48668,6 +51443,9 @@ uploading your change for review.
</histogram>
<histogram name="Net.HttpContentLengthDifference" units="bytes">
+ <obsolete>
+ Deprecated 06/2018.
+ </obsolete>
<owner>bengr@chromium.org</owner>
<summary>
The difference between the size specified in the X-Original-Content-Length
@@ -48778,8 +51556,7 @@ uploading your change for review.
<histogram name="Net.HttpOriginalContentLength" units="bytes">
<obsolete>
- Should be removed once consumers have been updated to use
- Net.HttpOriginalContentLengthV2
+ Replaced by Net.HttpOriginalContentLengthV2.
</obsolete>
<owner>bengr@chromium.org</owner>
<summary>
@@ -48891,6 +51668,9 @@ uploading your change for review.
<histogram name="Net.HttpResponseInfo.ConnectionInfo.MainFrame"
enum="ConnectionInfo">
+ <obsolete>
+ Deprecated as of July 2018.
+ </obsolete>
<owner>mmenke@chromium.org</owner>
<summary>
Application protocol used in HTTP responses to requests for main frames.
@@ -48900,6 +51680,9 @@ uploading your change for review.
<histogram name="Net.HttpResponseInfo.ConnectionInfo.SubResource"
enum="ConnectionInfo">
+ <obsolete>
+ Deprecated as of July 2018.
+ </obsolete>
<owner>mmenke@chromium.org</owner>
<summary>
Application protocol used in HTTP responses to requests for resources other
@@ -48909,7 +51692,7 @@ uploading your change for review.
</histogram>
<histogram name="Net.HttpServerProperties.UpdatePrefs"
- enum="HttpServerPropertiesUpdatePrefsLocation">
+ enum="HttpServerPropertiesUpdatePrefsLocation" expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The location in http_server_properties_manager.cc where UpdatePrefs was
@@ -49248,6 +52031,9 @@ uploading your change for review.
</histogram>
<histogram name="Net.LoadPrefetch.Pattern" enum="PrefetchStatus">
+ <obsolete>
+ Deprecated July 2018
+ </obsolete>
<owner>droger@chromium.org</owner>
<owner>mattcary@chromium.org</owner>
<owner>pasko@chromium.org</owner>
@@ -49421,7 +52207,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.NotifyAddrChangeFailures">
+<histogram name="Net.NotifyAddrChangeFailures" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
On Windows, NetworkChangeNotifierWin calls NotifyAddrChange, which can fail
@@ -49749,6 +52535,9 @@ uploading your change for review.
</histogram>
<histogram name="Net.Prefetch.Pattern" enum="PrefetchStatus">
+ <obsolete>
+ Deprecated July 2018
+ </obsolete>
<owner>jkarlin@chromium.org</owner>
<summary>
The completion status of prefetches that have finished loading.
@@ -49780,6 +52569,9 @@ uploading your change for review.
</histogram>
<histogram name="Net.Prefetch.TimeBeforeCancel" units="ms">
+ <obsolete>
+ Deprecated July 2018
+ </obsolete>
<owner>jkarlin@chromium.org</owner>
<summary>
Time spent on prefetch requests before the request was canceled.
@@ -49790,6 +52582,9 @@ uploading your change for review.
</histogram>
<histogram name="Net.Prefetch.TimeSpentOnPrefetchHit" units="ms">
+ <obsolete>
+ Deprecated July 2018
+ </obsolete>
<owner>jkarlin@chromium.org</owner>
<summary>
Time spent on requests that were served from a cache entry whose
@@ -49798,6 +52593,9 @@ uploading your change for review.
</histogram>
<histogram name="Net.Prefetch.TimeSpentPrefetchingFromCache" units="ms">
+ <obsolete>
+ Deprecated July 2018
+ </obsolete>
<owner>jkarlin@chromium.org</owner>
<summary>Time spent on prefetch requests when fetched from cache.</summary>
<details>
@@ -49806,6 +52604,9 @@ uploading your change for review.
</histogram>
<histogram name="Net.Prefetch.TimeSpentPrefetchingFromNetwork" units="ms">
+ <obsolete>
+ Deprecated July 2018
+ </obsolete>
<owner>jkarlin@chromium.org</owner>
<summary>
Time spent on prefetch requests when fetched from the network, including
@@ -50342,7 +53143,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.QuicClientHelloServerConfig.InvalidDuration" units="ms">
+<histogram name="Net.QuicClientHelloServerConfig.InvalidDuration" units="ms"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The time since expiration of server config when we sent inchoate ClientHello
@@ -50373,8 +53175,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Net.QuicConnection.WritePacketStatus" enum="QuicWriteStatus">
+ <owner>wub@chromium.org</owner>
+ <summary>
+ The write result returned by the packet writer when the connection attempts
+ to write a packet.
+ </summary>
+</histogram>
+
<histogram name="Net.QuicCryptoClientConfig.PopulatedFromCanonicalConfig"
- enum="BooleanPopulated">
+ enum="BooleanPopulated" expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The number of times CryptoClientConfig's CachedState is populated from
@@ -50486,7 +53296,7 @@ uploading your change for review.
</histogram>
<histogram name="Net.QuicInchoateClientHelloReason"
- enum="QuicServerConfigState">
+ enum="QuicServerConfigState" expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The reason (the state of the server config) for sending inchoate ClientHello
@@ -50541,14 +53351,15 @@ uploading your change for review.
<summary>The number of times ServerConfigUpdateMessages ignored.</summary>
</histogram>
-<histogram name="Net.QuicNumStreamFramesInPacket">
+<histogram name="Net.QuicNumStreamFramesInPacket" expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The number of stream frames bundled within a received packet.
</summary>
</histogram>
-<histogram name="Net.QuicNumStreamFramesPerStreamInPacket">
+<histogram name="Net.QuicNumStreamFramesPerStreamInPacket"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The number of stream frames per stream ID within a received packet.
@@ -50727,7 +53538,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.QuicSession.ClientSideMtu" units="bytes">
+<histogram name="Net.QuicSession.ClientSideMtu" units="bytes"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The final maximum packet size of the connection used by the client before
@@ -50742,7 +53554,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.QuicSession.ClosedDuringInitializeSession" enum="Boolean">
+<histogram name="Net.QuicSession.ClosedDuringInitializeSession" enum="Boolean"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
True if the QUIC session is closed during the call to InitializeSession,
@@ -50776,7 +53589,7 @@ uploading your change for review.
<histogram
name="Net.QuicSession.ConnectionClose.HandshakeFailureBlackHole.QuicError"
- enum="QuicErrorCodes">
+ enum="QuicErrorCodes" expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The QUIC error which caused a QUIC connection to be closed before the
@@ -50906,7 +53719,7 @@ uploading your change for review.
</histogram>
<histogram name="Net.QuicSession.CookieSentToAccountsOverChannelId"
- enum="BooleanUsage">
+ enum="BooleanUsage" expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
Logs whether channel ID was used when a cookie is sent over QUIC to
@@ -50979,8 +53792,8 @@ uploading your change for review.
enum="BooleanConfirmed">
<owner>zhongyi@chromium.org</owner>
<summary>
- Whether hanshake has been confirmed when the session attempts to migrate the
- connection.
+ The handshake status when when the session attempts to migrate the
+ connection according to different migration causes.
</summary>
</histogram>
@@ -51026,7 +53839,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.QuicSession.IncorrectConnectionIDsReceived">
+<histogram name="Net.QuicSession.IncorrectConnectionIDsReceived"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The number packets recevied by a QuicSession with an incorrect connection id
@@ -51092,7 +53906,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.QuicSession.MtuProbesSent">
+<histogram name="Net.QuicSession.MtuProbesSent" expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The number of MTU probes sent by the client during the session. Logged when
@@ -51151,7 +53965,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.QuicSession.OutOfOrderLargePacketsReceived">
+<histogram name="Net.QuicSession.OutOfOrderLargePacketsReceived"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The number of times the current received packet had a lower sequence number
@@ -51349,14 +54164,15 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.QuicSession.RejectHasProof" enum="Boolean">
+<histogram name="Net.QuicSession.RejectHasProof" enum="Boolean"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
True if the QUIC REJ message received from the server contains a proof.
</summary>
</histogram>
-<histogram name="Net.QuicSession.RejectLength">
+<histogram name="Net.QuicSession.RejectLength" expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The length in bytes of a QUIC REJ message received from the server.
@@ -51415,7 +54231,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.QuicSession.ServerSideMtu" units="bytes">
+<histogram name="Net.QuicSession.ServerSideMtu" units="bytes"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The largest packet which the client received from the server during the
@@ -51493,7 +54310,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.QuicSession.TimedOutWithOpenStreams.ConsecutiveRTOCount">
+<histogram name="Net.QuicSession.TimedOutWithOpenStreams.ConsecutiveRTOCount"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
If a QUIC connection timed out with open streams, this contains a count of
@@ -51501,7 +54319,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.QuicSession.TimedOutWithOpenStreams.ConsecutiveTLPCount">
+<histogram name="Net.QuicSession.TimedOutWithOpenStreams.ConsecutiveTLPCount"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
If a QUIC connection timed out with open streams, this contains a count of
@@ -51509,7 +54328,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.QuicSession.TimedOutWithOpenStreams.HasUnackedPackets">
+<histogram name="Net.QuicSession.TimedOutWithOpenStreams.HasUnackedPackets"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
If a QUIC connection timed out with open streams, this will be true when the
@@ -51517,7 +54337,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.QuicSession.TimedOutWithOpenStreams.LocalPort">
+<histogram name="Net.QuicSession.TimedOutWithOpenStreams.LocalPort"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
If a QUIC connection timed out locally with open streams, this contains the
@@ -51535,7 +54356,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.QuicSession.TooManyOpenStreams" enum="BooleanTooMany">
+<histogram name="Net.QuicSession.TooManyOpenStreams" enum="BooleanTooMany"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
True if more than 100 streams are open when a new stream is activated.
@@ -51558,7 +54380,8 @@ uploading your change for review.
<summary>The number of truncated ACK frames sent.</summary>
</histogram>
-<histogram name="Net.QuicSession.UndecryptablePacketsReceived">
+<histogram name="Net.QuicSession.UndecryptablePacketsReceived"
+ expires_after="2018-08-30">
<owner>rch@chromium.org</owner>
<summary>
The number of undecryptable packets recevied by a QuicSession when the
@@ -51630,6 +54453,9 @@ uploading your change for review.
<histogram name="Net.QuicSession.WriteOutOfOrderQueuedPacketAfterClose"
enum="Boolean">
+ <obsolete>
+ Deprecated 06/2018 after https://crbug.com/818040 is fixed.
+ </obsolete>
<owner>wub@chromium.org</owner>
<summary>
Temporary histogram being used to investigate https://crbug.com/818040.
@@ -51918,6 +54744,9 @@ uploading your change for review.
</histogram>
<histogram name="Net.RequestTime2Success.MainFrame" units="ms">
+ <obsolete>
+ Removed from Chromium as of 2018/7/2.
+ </obsolete>
<owner>csharrison@chromium.org</owner>
<summary>
The amount of time between request initiation and request completion for
@@ -51926,6 +54755,9 @@ uploading your change for review.
</histogram>
<histogram name="Net.RequestTime2Success.Subresource" units="ms">
+ <obsolete>
+ Removed from Chromium as of 2018/7/2.
+ </obsolete>
<owner>csharrison@chromium.org</owner>
<summary>
The amount of time between request initiation and request completion for
@@ -51935,6 +54767,9 @@ uploading your change for review.
<histogram name="Net.ResourceDispatcherHost.OutstandingRequests.PerProcess"
units="requests">
+ <obsolete>
+ Removed from Chromium as of 2018/7.
+ </obsolete>
<owner>xunjieli@chromium.org</owner>
<summary>
The largest number of outstanding requests that are handled by the resource
@@ -51944,6 +54779,9 @@ uploading your change for review.
<histogram name="Net.ResourceDispatcherHost.OutstandingRequests.Total"
units="requests">
+ <obsolete>
+ Removed from Chromium as of 2018/7.
+ </obsolete>
<owner>xunjieli@chromium.org</owner>
<summary>
The largest number of outstanding requests that are handled by the resource
@@ -52034,13 +54872,18 @@ uploading your change for review.
Time from the start to the end of receiving a response body. Recorded for
each resource load.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
<histogram name="Net.ResourceLoader.TimeToURLRequestStart" units="ms">
+ <obsolete>
+ Removed from Chromium as of 2018/7/2.
+ </obsolete>
<owner>csharrison@chromium.org</owner>
<summary>
The time elapsed from URLRequest creation to when a ResourceLoader actually
@@ -52454,6 +55297,15 @@ uploading your change for review.
<summary>The number of bytes recevied per stream.</summary>
</histogram>
+<histogram name="Net.SpdyResponseCode" enum="HttpResponseCode">
+ <owner>bnc@chromium.org</owner>
+ <summary>
+ HTTP status codes received in HTTP/2 HEADERS frames. If a stream contains
+ one or more informational (1xx) response preceeding the main response, each
+ status code is logged separately.
+ </summary>
+</histogram>
+
<histogram name="Net.SpdySendBytes" units="bytes">
<owner>bnc@chromium.org</owner>
<summary>The number of bytes sent per stream.</summary>
@@ -53248,6 +56100,14 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Net.SSLSecureRenegotiation" enum="BooleanSecure">
+ <owner>davidben@chromium.org</owner>
+ <summary>
+ For each attempted SSL renegotiation (non-initial handshake), whether the
+ server supported the renegotiation_info extension (RFC 5746).
+ </summary>
+</histogram>
+
<histogram name="Net.SSLServerKeyExchangeHash" enum="SSLHashAlgorithm">
<obsolete>
Replaced by Net.SSLSignatureAlgorithm.
@@ -53897,7 +56757,8 @@ uploading your change for review.
<summary>The time that a Wi-fi scan takes.</summary>
</histogram>
-<histogram name="Net.WpadQuickCheckFailure" units="ms">
+<histogram name="Net.WpadQuickCheckFailure" units="ms"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Duration of time that a failing WPAD QuickCheck takes. WPAD QuickCheck does
@@ -53906,7 +56767,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Net.WpadQuickCheckSuccess" units="ms">
+<histogram name="Net.WpadQuickCheckSuccess" units="ms"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Duration of time that a successful WPAD QuickCheck takes. WPAD QuickCheck
@@ -56682,7 +59544,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="NewTabPage.AppsPageDragSource" enum="AppsPageDragSource">
+<histogram name="NewTabPage.AppsPageDragSource" enum="AppsPageDragSource"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Histogram for the source of app page drags. For any succesful drop onto an
@@ -56690,22 +59553,43 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="NewTabPage.BackgroundService.Albums.RequestLatency" units="ms"
+ expires_after="M74">
+ <owner>ramyan@chromium.org</owner>
+ <owner>yyushkina@chromium.org</owner>
+ <summary>
+ The time it took until a request from the New Tab Page for Google Photos
+ albums was served.
+ </summary>
+</histogram>
+
<histogram name="NewTabPage.BackgroundService.Collections.RequestLatency"
- units="ms">
+ units="ms" expires_after="M74">
<owner>ramyan@chromium.org</owner>
<owner>yyushkina@chromium.org</owner>
<summary>
- The time it took until a request from the New Tab page for the NTP
- Background Collections script was served. Recorded only on the local NTP.
+ The time it took until a request from the New Tab Page for Backdrop
+ Collections was served.
</summary>
</histogram>
-<histogram name="NewTabPage.BackgroundService.Images.RequestLatency" units="ms">
+<histogram name="NewTabPage.BackgroundService.Images.RequestLatency" units="ms"
+ expires_after="M74">
<owner>ramyan@chromium.org</owner>
<owner>yyushkina@chromium.org</owner>
<summary>
- The time it took until a request from the New Tab page for the NTP
- Background Images script was served. Recorded only on the local NTP.
+ The time it took until a request from the New Tab Page for Backdrop Images
+ was served.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.BackgroundService.Photos.RequestLatency" units="ms"
+ expires_after="M74">
+ <owner>ramyan@chromium.org</owner>
+ <owner>yyushkina@chromium.org</owner>
+ <summary>
+ The time it took until a request from the New Tab Page for Google Photos (in
+ a specific album) was served.
</summary>
</histogram>
@@ -56977,7 +59861,7 @@ uploading your change for review.
<owner>treib@chromium.org</owner>
<summary>
Android: The position of a &quot;More&quot; suggestion card that was clicked
- on the NTP. A card is considered shown when at least 1/3 of its height is
+ on the NTP. A card is considered shown when at least 2/3 of its height is
visible on the screen. We track the position the card had in the list when
it was first seen by the user. This tracked position can be different from
the position observed by the user, e.g. when the user dismissed some
@@ -56990,7 +59874,7 @@ uploading your change for review.
<owner>treib@chromium.org</owner>
<summary>
Android: The position of a &quot;More&quot; suggestion card that was shown
- on the NTP. A card is considered shown when at least 1/3 of its height is
+ on the NTP. A card is considered shown when at least 2/3 of its height is
visible on the screen. For each card, at most one impression is recorded per
NTP instance. We track the position the card had in the list when it was
first seen by the user. This tracked position can be different from the
@@ -57149,7 +60033,7 @@ uploading your change for review.
<owner>treib@chromium.org</owner>
<summary>
Android: The position of a suggestion card that was shown on the NTP. A card
- is considered shown when at least 1/3 of its height is visible on the
+ is considered shown when at least 2/3 of its height is visible on the
screen. For each card, at most one impression is recorded per NTP instance.
We track the position the card had in the list when it was first seen by the
user. This tracked position can be different from the position observed by
@@ -57172,7 +60056,7 @@ uploading your change for review.
<summary>
Android: The position of a prefetched suggestion card that was shown on the
NTP when offline. Analogous to NewTabPage.ContentSuggestions.Shown. That is
- a card is considered shown when at least 1/3 of its height is visible on the
+ a card is considered shown when at least 2/3 of its height is visible on the
screen. For each card, at most one impression is recorded per NTP instance.
We track the position the card had in the list when it was first seen by the
user. This tracked position can be different from the position observed by
@@ -57188,7 +60072,7 @@ uploading your change for review.
<summary>
Android: The position of a prefetched suggestion card that was shown on the
NTP when offline. Analogous to NewTabPage.ContentSuggestions.Shown. That is
- a card is considered shown when at least 1/3 of its height is visible on the
+ a card is considered shown when at least 2/3 of its height is visible on the
screen. For each card, at most one impression is recorded per NTP instance.
We track the position the card had in the list when it was first seen by the
user. This tracked position can be different from the position observed by
@@ -57203,7 +60087,7 @@ uploading your change for review.
<owner>treib@chromium.org</owner>
<summary>
Android: The age of a suggestion card that was shown on the NTP. A card is
- considered shown when at least 1/3 of its height is visible on the screen.
+ considered shown when at least 2/3 of its height is visible on the screen.
For each card, at most one impression is recorded per NTP instance.
</summary>
</histogram>
@@ -57215,7 +60099,7 @@ uploading your change for review.
<owner>treib@chromium.org</owner>
<summary>
Android: The score of a suggestion card that was shown on the NTP. A card is
- considered shown when at least 1/3 of its height is visible on the screen.
+ considered shown when at least 2/3 of its height is visible on the screen.
For each card, at most one impression is recorded per NTP instance.
</summary>
</histogram>
@@ -57225,7 +60109,7 @@ uploading your change for review.
<owner>tschumann@chromium.org</owner>
<summary>
Android: The score of a suggestion card that was shown on the NTP. A card is
- considered shown when at least 1/3 of its height is visible on the screen.
+ considered shown when at least 2/3 of its height is visible on the screen.
For each card, at most one impression is recorded per NTP instance. Scores
(which are typically floats within (0,1]) get reported as discrete integers
within [1,10]. For instance, the discrete value 1 represents score values
@@ -57383,6 +60267,80 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="NewTabPage.CustomizationAvailability.Backgrounds"
+ enum="NTPBackgroundCustomizationAvailability" expires_after="M74">
+ <owner>ramyan@chromium.org</owner>
+ <owner>yyushkina@chromium.org</owner>
+ <summary>
+ The availability of New Tab Page background customization features on
+ Desktop, based on feature flags or other configuration settings; logged per
+ NTP load.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.CustomizationAvailability.Shortcuts"
+ enum="NTPShortcutCustomizationAvailability" expires_after="M74">
+ <owner>ramyan@chromium.org</owner>
+ <owner>yyushkina@chromium.org</owner>
+ <summary>
+ The availability of New Tab Page shortcut customization features on Desktop,
+ based on feature flags or other configuration settings; logged per NTP load.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.CustomizeAction" enum="NTPCustomizeAction"
+ expires_after="M74">
+ <owner>ramyan@chromium.org</owner>
+ <owner>yyushkina@chromium.org</owner>
+ <summary>
+ Customization actions performed by the user on the New Tab Page; logged as
+ each interaction occurs. This may indicate popularity of a particular
+ customization type.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.CustomizeChromeBackgroundAction"
+ enum="NTPCustomizeChromeBackgroundAction" expires_after="M74">
+ <owner>ramyan@chromium.org</owner>
+ <owner>yyushkina@chromium.org</owner>
+ <summary>
+ Captures the actions performed when configuring a 'Chrome background' image
+ on the New Tab Page. Since most actions are sequential, this may indicate
+ steps in the configuration process where users drop off.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.Customized" enum="NTPCustomizedFeatures"
+ expires_after="M74">
+ <owner>ramyan@chromium.org</owner>
+ <owner>yyushkina@chromium.org</owner>
+ <summary>
+ The New Tab Page features that have been customized by the user; logged per
+ NTP load.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.CustomizeLocalImageBackgroundAction"
+ enum="NTPCustomizeLocalImageBackgroundAction" expires_after="M74">
+ <owner>ramyan@chromium.org</owner>
+ <owner>yyushkina@chromium.org</owner>
+ <summary>
+ Captures the actions performed when uploading a local image as the
+ background on the New Tab Page. Since most actions are sequential, this may
+ indicate steps in the configuration process where users drop off.
+ </summary>
+</histogram>
+
+<histogram name="NewTabPage.CustomizeShortcutAction"
+ enum="NTPCustomizeShortcutAction" expires_after="M74">
+ <owner>ramyan@chromium.org</owner>
+ <owner>yyushkina@chromium.org</owner>
+ <summary>
+ Captures the actions performed when configuring shortcuts on the New Tab
+ Page.
+ </summary>
+</histogram>
+
<histogram name="NewTabPage.DefaultPageType" enum="NtpPaneType">
<obsolete>
Deprecated 2016-02.
@@ -58140,7 +61098,7 @@ uploading your change for review.
<owner>knn@chromium.org</owner>
<summary>
Android: The position of the snippets card that is shown on the NTP. Each
- snippet (its position) is recorded whenever at least 1/3 of its height
+ snippet (its position) is recorded whenever at least 2/3 of its height
becomes visible by scrolling through the NTP. Each snippet is recorded at
most once for a given instance of NTP and a given data set of snippets that
is shown. We track the position the snippet had in the list when NTP was
@@ -58160,7 +61118,7 @@ uploading your change for review.
<owner>jkrcal@chromium.org</owner>
<summary>
Android: The age of the snippets card that is shown on the NTP. Each snippet
- (its age) is recorded whenever at least 1/3 of its height becomes visible by
+ (its age) is recorded whenever at least 2/3 of its height becomes visible by
scrolling through the NTP. Each snippet is recorded at most once for a given
instance of NTP and a given data set of snippets that is shown. The age is
measured from the moment the content has been published. In each
@@ -58179,7 +61137,7 @@ uploading your change for review.
<owner>jkrcal@chromium.org</owner>
<summary>
Android: The score of the snippets card that is shown on the NTP. Each
- snippet (its score) is recorded whenever at least 1/3 of its height becomes
+ snippet (its score) is recorded whenever at least 2/3 of its height becomes
visible by scrolling through the NTP. Each snippet is recorded at most once
for a given instance of NTP and a given data set of snippets that is shown.
The recorded score is from the moment the snippet was fetched, it could have
@@ -58199,7 +61157,7 @@ uploading your change for review.
<owner>jkrcal@chromium.org</owner>
<summary>
Android: The score of the snippets card that is shown on the NTP. Each
- snippet (its score) is recorded whenever at least 1/3 of its height becomes
+ snippet (its score) is recorded whenever at least 2/3 of its height becomes
visible by scrolling through the NTP. Each snippet is recorded at most once
for a given instance of NTP and a given data set of snippets that is shown.
The recorded score is from the moment the snippet was fetched, it could have
@@ -58948,6 +61906,41 @@ uploading your change for review.
</summary>
</histogram>
+<histogram
+ name="Notifications.NotificationHelper.NotificationActivatorPrimaryStatus"
+ enum="NotificationHelperNotificationActivatorPrimaryStatus">
+ <owner>chengx@chromium.org</owner>
+ <owner>finnur@chromium.org</owner>
+ <summary>
+ The primary execute status of NotificationActivator::Activate. Logged
+ whenever a notification_helper process is launched by Windows.
+ </summary>
+</histogram>
+
+<histogram
+ name="Notifications.NotificationHelper.NotificationActivatorSecondaryStatus"
+ enum="NotificationHelperNotificationActivatorSecondaryStatus">
+ <owner>chengx@chromium.org</owner>
+ <owner>finnur@chromium.org</owner>
+ <summary>
+ The secondary execute status of NotificationActivator::Activate. Logged
+ whenever a notification_helper process is launched by Windows.
+ </summary>
+</histogram>
+
+<histogram name="Notifications.NotificationHelper.NotificationActivatorStatus"
+ enum="NotificationHelperNotificationActivatorStatus">
+ <obsolete>
+ Deprecated 06/2018. Replaced by NotificationActivatorPrimaryStatus and
+ NotificationActivatorSecondaryStatus.
+ </obsolete>
+ <owner>chengx@chromium.org</owner>
+ <summary>
+ The execute status of NotificationActivator::Activate. Logged whenever a
+ notification_helper process is launched by Windows.
+ </summary>
+</histogram>
+
<histogram name="Notifications.NotificationHelper.ServerRuntime" units="ms">
<owner>chengx@chromium.org</owner>
<summary>
@@ -59158,6 +62151,10 @@ uploading your change for review.
<histogram name="Notifications.Windows.SetReadyCallbackStatus"
enum="WindowsNotificationSetReadyCallbackStatus">
+ <obsolete>
+ Replaced with Notifications.Windows.SetReadyCallbackStatus2 which is not
+ skewed.
+ </obsolete>
<owner>finnur@chromium.org</owner>
<owner>peter@chromium.org</owner>
<summary>
@@ -59166,6 +62163,43 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Notifications.Windows.SetReadyCallbackStatus2"
+ enum="WindowsNotificationSetReadyCallbackStatus2">
+ <owner>chengx@chromium.org</owner>
+ <owner>finnur@chromium.org</owner>
+ <owner>peter@chromium.org</owner>
+ <summary>
+ The status of SetReadyCallback requests in NotificationPlatformBridgeWin
+ (Windows only). Logged once at startup.
+ </summary>
+</histogram>
+
+<histogram name="Notifications.Windows.StartMenuShortcutStatus"
+ enum="WindowsNotificationStartMenuShortcutStatus">
+ <owner>chengx@chromium.org</owner>
+ <owner>finnur@chromium.org</owner>
+ <owner>peter@chromium.org</owner>
+ <summary>
+ Used to indicate the status of start menu shortcut (Windows only). Logged
+ whenever a notification display attempt is made.
+ </summary>
+</histogram>
+
+<histogram name="Notifications.Windows.StartMenuShortStatus"
+ enum="WindowsNotificationStartMenuShortStatus">
+ <obsolete>
+ Deprecated 06/2018. Replaced with
+ Notifications.Windows.StartMenuShortcutStatus where typo is fixed.
+ </obsolete>
+ <owner>chengx@chromium.org</owner>
+ <owner>finnur@chromium.org</owner>
+ <owner>peter@chromium.org</owner>
+ <summary>
+ Used to indicate the status of start menu shortcut (Windows only). Logged
+ whenever a notification display attempt is made.
+ </summary>
+</histogram>
+
<histogram name="Notifications.Windows.UserManagerShowupStatus"
enum="WindowsNotificationUserManagerShowupStatus">
<obsolete>
@@ -60044,6 +63078,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="OfflineIndicator.CTR" enum="OfflineIndicatorCTREvent"
+ expires_after="2019-06-30">
+ <owner>dimich@chromium.org</owner>
+ <owner>jianli@chromium.org</owner>
+ <summary>
+ Records events related to click through rate (CTR) calculation for Offline
+ Indicator UI. The CTR can be calculated by computing Clicked/Displayed.
+ </summary>
+</histogram>
+
<histogram base="true" name="OfflinePages.AccessCount">
<owner>jianli@chromium.org</owner>
<summary>
@@ -60284,6 +63328,30 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="OfflinePages.Background.ResourceCompletion.Css"
+ enum="BooleanEnabled">
+ <owner>petewil@chromium.org</owner>
+ <summary>
+ True if all requested CSS was loaded when a background page loaded.
+ </summary>
+</histogram>
+
+<histogram name="OfflinePages.Background.ResourceCompletion.Image"
+ enum="BooleanEnabled">
+ <owner>petewil@chromium.org</owner>
+ <summary>
+ True if all requested images were loaded when a background page loaded.
+ </summary>
+</histogram>
+
+<histogram name="OfflinePages.Background.ResourceCompletion.Xhr"
+ enum="BooleanEnabled">
+ <owner>petewil@chromium.org</owner>
+ <summary>
+ True if all requested XHRs were completed when a background page loaded.
+ </summary>
+</histogram>
+
<histogram name="OfflinePages.Background.SavePageFromCCT">
<owner>chili@chromium.org</owner>
<summary>Whether the save page result came from chrome custom tabs.</summary>
@@ -60383,7 +63451,9 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="OfflinePages.CanSaveRecentPage" enum="Boolean">
+<histogram name="OfflinePages.CanSaveRecentPage" enum="Boolean"
+ expires_after="2018-12-31">
+ <owner>carlosk@chromium.org</owner>
<owner>fgorski@chromium.org</owner>
<summary>
Can a recent page be saved or not? Logged for all attempts to save
@@ -60798,7 +63868,7 @@ uploading your change for review.
</histogram>
<histogram name="OfflinePages.DownloadUI.PrefetchedItemHasThumbnail"
- units="BooleanAvailable">
+ enum="BooleanAvailable">
<owner>harringtond@chromium.org</owner>
<summary>
Whether or not a thumbnail was provided for a prefetched offline article.
@@ -60898,6 +63968,18 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="OfflinePages.LastN.IsSavingSamePage"
+ enum="OfflinePagesLastNIsSavingSamePageEnum" expires_after="2018-12-31">
+ <owner>carlosk@chromium.org</owner>
+ <summary>
+ Upon starting saving a new last_n offline page snapshot, report if that is
+ being done for a page that is new (a navigation happened) or for one that
+ has been previously saved in the same session (no navigation happened). This
+ metric will assist in determining if there is the need to better track
+ actual content changes in pages saved more than once by last_n.
+ </summary>
+</histogram>
+
<histogram name="OfflinePages.LaunchLocation" enum="StarsLaunchLocation">
<obsolete>
Deprecated 5/2016. Offline pages no longer depend on bookmarks UI.
@@ -61248,6 +64330,49 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="OfflinePages.PublishArchive.CreateDirectoryError"
+ enum="PlatformFileError">
+ <owner>petewil@chromium.org</owner>
+ <summary>
+ When publishing an archive, we create the download directory if it doesn't
+ already exist. If we get an error, we record it here.
+ </summary>
+</histogram>
+
+<histogram name="OfflinePages.PublishArchive.MoveFileError"
+ enum="PopularOSErrno">
+ <owner>petewil@chromium.org</owner>
+ <summary>
+ When publishing an offline page, the move file step can fail. This returns
+ the reason for failure as a linux errno.
+ </summary>
+</histogram>
+
+<histogram name="OfflinePages.PublishArchive.MoveFileFailureReason"
+ enum="OfflinePagesPublishArchiveMoveFileFailureReason">
+ <owner>petewil@chromium.org</owner>
+ <summary>
+ When a move file fails for publishing, what caused the failure.
+ </summary>
+</histogram>
+
+<histogram name="OfflinePages.PublishArchive.PublishSource"
+ enum="OfflinePagesPublishSource">
+ <owner>petewil@chromium.org</owner>
+ <summary>
+ When publishing an offline page, a page might not be found. This returns
+ the publishing path that was used (ex: by Guid or by OfflineId).
+ </summary>
+</histogram>
+
+<histogram name="OfflinePages.PublishPageResult"
+ enum="OfflinePagesSavePageResult">
+ <owner>petewil@chromium.org</owner>
+ <summary>
+ Failure attempting to move a file while publishing downloaded page.
+ </summary>
+</histogram>
+
<histogram name="OfflinePages.RedirectResult" enum="OfflinePagesRedirectResult">
<obsolete>
Deprecated 8/2016. Use OfflinePages.RequestResult instead.
@@ -61807,6 +64932,24 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Omnibox.DocumentSuggest.Requests"
+ enum="OmniboxDocumentSuggestRequests">
+ <owner>skare@chromium.org</owner>
+ <summary>
+ Counts the number of document suggest requests the omnibox sent, were
+ invalidated, and were completed successfully.
+ </summary>
+</histogram>
+
+<histogram name="Omnibox.DocumentSuggest.ResultCount" units="count"
+ expires_after="M72">
+ <owner>skare@chromium.org</owner>
+ <summary>
+ Number of results returned in each document suggestion reply. Logged for
+ successful requests where the provider returned a parseable result set.
+ </summary>
+</histogram>
+
<histogram name="Omnibox.EnteredKeywordMode" enum="OmniboxEnteredKeywordMode">
<owner>mpearson@chromium.org</owner>
<summary>
@@ -61990,7 +65133,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Omnibox.PasteAndGo" units="count">
+<histogram name="Omnibox.PasteAndGo" units="count" expires_after="2018-08-30">
<owner>mpearson@chromium.org</owner>
<summary>
The number of paste-and-go commands on the text in the omnibox. Reported
@@ -62162,7 +65305,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Omnibox.SearchProvider.ConvertResultsTime" units="ms">
+<histogram name="Omnibox.SearchProvider.ConvertResultsTime" units="ms"
+ expires_after="2018-08-30">
<owner>mpearson@chromium.org</owner>
<summary>
Time it takes to convert all the results to matches and add them to a map,
@@ -62172,7 +65316,7 @@ uploading your change for review.
<histogram
name="Omnibox.SearchProvider.GetMostRecentKeywordTermsDefaultProviderTime"
- units="ms">
+ units="ms" expires_after="2018-08-30">
<owner>mpearson@chromium.org</owner>
<summary>
Time it takes for the omnibox to search the previous query history database
@@ -62711,7 +65855,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="OSX.BluetoothAvailability" enum="BluetoothAvailability">
+<histogram name="OSX.BluetoothAvailability" enum="BluetoothAvailability"
+ expires_after="2018-08-30">
<owner>erikchen@chromium.org</owner>
<summary>
The availability and capabilities of the Bluetooth driver on OSX devices.
@@ -62758,7 +65903,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="OSX.Fullscreen.Enter.Style" enum="OSXFullscreenStyle">
+<histogram name="OSX.Fullscreen.Enter.Style" enum="OSXFullscreenStyle"
+ expires_after="2018-08-30">
<owner>erikchen@chromium.org</owner>
<summary>
This event is recorded each time a user triggers fullscreen for a browser
@@ -62768,7 +65914,7 @@ uploading your change for review.
</histogram>
<histogram name="OSX.Fullscreen.Enter.WindowLocation"
- enum="OSXFullscreenWindowLocation">
+ enum="OSXFullscreenWindowLocation" expires_after="2018-08-30">
<owner>erikchen@chromium.org</owner>
<summary>
This event is recorded each time a user triggers fullscreen for a browser
@@ -62785,7 +65931,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="OSX.Handoff.Origin" enum="OSXHandoffOrigin">
+<histogram name="OSX.Handoff.Origin" enum="OSXHandoffOrigin"
+ expires_after="2018-08-30">
<owner>erikchen@chromium.org</owner>
<summary>
This event is recorded each time a Handoff is received by Chrome on OSX. The
@@ -62871,7 +66018,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="OSX.SystemHotkeyMap.LoadSuccess" enum="BooleanSuccess">
+<histogram name="OSX.SystemHotkeyMap.LoadSuccess" enum="BooleanSuccess"
+ expires_after="2018-08-30">
<owner>erikchen@chromium.org</owner>
<summary>
Whether an attempt to load the system hotkeys on a Mac was successful.
@@ -63488,6 +66636,9 @@ uploading your change for review.
<histogram name="PageLoad.Clients.Ads.All.Navigations.AdFrameRenavigatedToAd"
enum="DidNavigateToAd">
+ <obsolete>
+ Deprecated In July 2018, metric was buggy for subresource filter ads.
+ </obsolete>
<owner>jkarlin@chromium.org</owner>
<summary>
When a frame that is (or previously was) an ad frame renavigates, record
@@ -63505,6 +66656,9 @@ uploading your change for review.
<histogram
name="PageLoad.Clients.Ads.All.Navigations.NonAdFrameRenavigatedToAd"
enum="DidNavigateToAd">
+ <obsolete>
+ Deprecated In July 2018.
+ </obsolete>
<owner>jkarlin@chromium.org</owner>
<summary>
When a frame that has never been part of an ad frame renavigates, record
@@ -63880,6 +67034,10 @@ uploading your change for review.
<histogram name="PageLoad.Clients.ServiceWorker.PageTransition"
enum="CorePageTransition">
+ <obsolete>
+ Deprecated June 2018 (M69) in favor of
+ PageLoad.Clients.ServiceWorker2.PageTransition.
+ </obsolete>
<owner>falken@chromium.org</owner>
<summary>
The core transition type for main frame page loads controlled by a service
@@ -63887,6 +67045,15 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="PageLoad.Clients.ServiceWorker2.PageTransition"
+ enum="CorePageTransition">
+ <owner>falken@chromium.org</owner>
+ <summary>
+ The core transition type for main frame page loads controlled by a service
+ worker that has a fetch event handler.
+ </summary>
+</histogram>
+
<histogram name="PageLoad.Clients.SubresourceFilter.ActivationDecision"
enum="SubresourceFilterActivationDecision">
<obsolete>
@@ -63922,6 +67089,9 @@ uploading your change for review.
<histogram name="PageLoad.CSSTiming.Parse.BeforeFirstContentfulPaint"
units="ms">
+ <obsolete>
+ Deprecated in May 2018 (M69).
+ </obsolete>
<owner>csharrison@chromium.org</owner>
<summary>
The time spent parsing author style sheets before the first contentful
@@ -63931,6 +67101,9 @@ uploading your change for review.
<histogram name="PageLoad.CSSTiming.ParseAndUpdate.BeforeFirstContentfulPaint"
units="ms">
+ <obsolete>
+ Deprecated in May 2018 (M69).
+ </obsolete>
<owner>csharrison@chromium.org</owner>
<summary>
The sum of CSSTiming.Update and CSSTiming.Parse variants for this page load.
@@ -63939,6 +67112,9 @@ uploading your change for review.
<histogram name="PageLoad.CSSTiming.Update.BeforeFirstContentfulPaint"
units="ms">
+ <obsolete>
+ Deprecated in May 2018 (M69).
+ </obsolete>
<owner>csharrison@chromium.org</owner>
<summary>
The time spent in Document::updateStyle before the first contentful paint.
@@ -64501,6 +67677,39 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="PageLoad.InteractiveTiming.InputDelay" units="ms">
+ <owner>tdresser@chromium.org</owner>
+ <summary>
+ The duration between the hardware timestamp and the start of event
+ processing on the main thread for a meaningful input. In ms.
+ </summary>
+</histogram>
+
+<histogram name="PageLoad.InteractiveTiming.InputTimestamp" units="ms">
+ <owner>tdresser@chromium.org</owner>
+ <summary>
+ The duration between navigation start and the hardware timestamp of a
+ meaningful input. In ms.
+ </summary>
+</histogram>
+
+<histogram name="PageLoad.InteractiveTiming.LongestInputDelay" units="ms">
+ <owner>tdresser@chromium.org</owner>
+ <summary>
+ Measures longest Input Delay, the longest duration between the hardware
+ timestamp and the start of event processing on the main thread for the
+ meaningful input per navigation. In ms.
+ </summary>
+</histogram>
+
+<histogram name="PageLoad.InteractiveTiming.LongestInputTimestamp" units="ms">
+ <owner>tdresser@chromium.org</owner>
+ <summary>
+ The duration between navigation start and the hardware timestamp of the
+ meaningful input with longest queuing delay per navigation. In ms.
+ </summary>
+</histogram>
+
<histogram name="PageLoad.Internal.ClientRedirect.FirstPaintToNavigation"
units="ms">
<owner>bmcquade@chromium.org</owner>
@@ -64635,7 +67844,7 @@ uploading your change for review.
</histogram>
<histogram name="PageLoad.Internal.ProvisionalAbortChainSize.ForwardBack"
- units="length">
+ units="length" expires_after="2018-08-30">
<owner>csharrison@chromium.org</owner>
<summary>
This histogram counts the number of provisional loads aborted by other
@@ -64653,7 +67862,7 @@ uploading your change for review.
</histogram>
<histogram name="PageLoad.Internal.ProvisionalAbortChainSize.NoCommit"
- units="length">
+ units="length" expires_after="2018-08-30">
<owner>csharrison@chromium.org</owner>
<summary>
This histogram counts the number of provisional loads aborted by new
@@ -64663,7 +67872,7 @@ uploading your change for review.
</histogram>
<histogram name="PageLoad.Internal.ProvisionalAbortChainSize.Reload"
- units="length">
+ units="length" expires_after="2018-08-30">
<owner>csharrison@chromium.org</owner>
<summary>
This histogram counts the number of provisional loads aborted by other
@@ -64672,7 +67881,7 @@ uploading your change for review.
</histogram>
<histogram name="PageLoad.Internal.ProvisionalAbortChainSize.SameURL"
- units="length">
+ units="length" expires_after="2018-08-30">
<owner>csharrison@chromium.org</owner>
<summary>
This histogram counts the number of consecutive provisional loads aborted by
@@ -65222,6 +68431,21 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="PageScheduler.PageLifecycleStateTransition"
+ enum="PageLifecycleStateTransition">
+ <owner>fmeawad@chromium.org</owner>
+ <owner>panicker@chromium.org</owner>
+ <summary>
+ Tracks the transitions of the page between the various PageLifecycleStates:
+ active, hidden/backgrounded, hidden/foregrounded, and frozen. A page is
+ considered active if is visible. A page is considered backgrounded if not
+ visible and not currently providing a useful service, such as playing audio.
+ A page is considered foregrounded if it is not backgrounded. A page can be
+ frozen due to being hidden/backgrounded for a specified amount of time, or
+ frozen due to critical resources.
+ </summary>
+</histogram>
+
<histogram
name="PageSerialization.MhtmlGeneration.BrowserWaitForRendererTime.FrameTree"
units="ms">
@@ -65248,9 +68472,11 @@ uploading your change for review.
<summary>
Time taken to encode into MTHML the fully serialized contents of a frame.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -65361,9 +68587,11 @@ uploading your change for review.
Time spent serializing a CSS element (including embedded &quot;sub&quot;-CSS
and images).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -65373,16 +68601,26 @@ uploading your change for review.
Time taken to generate HTML data from a frame's DOM and serialize it
(without sub-resources like CSS and images).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
<histogram name="PageSerialization.SerializationTime.ImageElement"
units="microseconds">
<owner>carlosk@chromium.org</owner>
- <summary>Time spent serializing an image element.</summary>
+ <summary>
+ Time spent serializing an image element.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="Parser.AppendBytesDelay" units="ms">
@@ -65407,7 +68645,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Parser.DiscardedTokenCount" units="tokens">
+<histogram name="Parser.DiscardedTokenCount" units="tokens"
+ expires_after="2018-08-30">
<owner>csharrison@chromium.org</owner>
<summary>
The number of speculative tokens discarded by the parser when a rewind is
@@ -65585,6 +68824,14 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="PasswordGeneration.IsTriggeredManually"
+ enum="BooleanIsGenerationTriggeredManually">
+ <owner>kolos@chromium.org</owner>
+ <summary>
+ Measures the frequency of manually triggered password generations.
+ </summary>
+</histogram>
+
<histogram name="PasswordGeneration.SubmissionAvailableEvent"
enum="PasswordSubmissionEvent">
<owner>gcasto@chromium.org</owner>
@@ -65953,6 +69200,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="PasswordManager.BlacklistedDuplicates"
+ units="duplicated forms" expires_after="M71">
+ <owner>gemene@google.com</owner>
+ <owner>jdoerrie@chromium.org</owner>
+ <summary>
+ The number of duplicates forms from the password store. Recorded once for
+ the profile on startup.
+ </summary>
+</histogram>
+
<histogram name="PasswordManager.BlacklistedSites">
<owner>gcasto@chromium.org</owner>
<owner>vabr@chromium.org</owner>
@@ -66566,6 +69823,69 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="PasswordManager.RequirementsSpecFetcher.HttpResponseCode"
+ enum="HttpResponseCode">
+ <owner>battre@chromium.org</owner>
+ <summary>
+ HTTP response code of fetching a password requirements file.
+ </summary>
+</histogram>
+
+<histogram name="PasswordManager.RequirementsSpecFetcher.NetErrorCode"
+ enum="NetErrorCodes">
+ <owner>battre@chromium.org</owner>
+ <summary>
+ Network error code of fetching a password requirements file.
+ </summary>
+</histogram>
+
+<histogram name="PasswordManager.RequirementsSpecFetcher.NetworkDuration"
+ units="ms">
+ <owner>battre@chromium.org</owner>
+ <summary>
+ Time until the lookup for a password requirements file completed (or was
+ aborted).
+ </summary>
+</histogram>
+
+<histogram name="PasswordManager.RequirementsSpecFetcher.Result"
+ enum="PasswordRequirementsFetcherResult">
+ <owner>battre@chromium.org</owner>
+ <summary>
+ Result of fetching requirements for password during password generation.
+ </summary>
+</histogram>
+
+<histogram name="PasswordManager.ReusedPasswordType" enum="ReusedPasswordType">
+ <owner>dvadym@chromium.org</owner>
+ <owner>jialiul@chromium.org</owner>
+ <summary>
+ Records the type of password (e.g saved password, sync password, enterprise
+ password etc) reused by the user. This is logged when a password reuse
+ happens.
+ </summary>
+</histogram>
+
+<histogram name="PasswordManager.SavedEnterprisePasswordHashCount">
+ <owner>dvadym@chromium.org</owner>
+ <owner>jialiul@chromium.org</owner>
+ <summary>
+ Records the number of enterprise password hashes that have been saved for
+ password reuse detection. This is logged during the initialization of
+ PasswordStore class.
+ </summary>
+</histogram>
+
+<histogram name="PasswordManager.SavedGaiaPasswordHashCount" units="count">
+ <owner>dvadym@chromium.org</owner>
+ <owner>jialiul@chromium.org</owner>
+ <summary>
+ Records the number of Gaia password hashes that have been saved for password
+ reuse detection. This is logged during the initialization of PasswordStore
+ class.
+ </summary>
+</histogram>
+
<histogram name="PasswordManager.SavePasswordPromptDisappearedQuickly"
enum="Boolean">
<obsolete>
@@ -66662,6 +69982,17 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="PasswordManager.ShouldShowPromptComparison"
+ enum="ShouldShowPromptResults" expires_after="M70">
+ <owner>dvadym@chromium.org</owner>
+ <owner>vabr@chromium.org</owner>
+ <summary>
+ Records results of the new and the old algorithm for detecting whether to
+ show a password prompt to the user. Recorded on each password form
+ successful submission.
+ </summary>
+</histogram>
+
<histogram name="PasswordManager.ShowAllSavedPasswordsAcceptedContext"
enum="ShowAllSavedPasswordsContext">
<owner>jdoerrie@chromium.org</owner>
@@ -66873,6 +70204,17 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="PasswordManager.TimeBetweenStoreAndServer" units="ms"
+ expires_after="2018-11-01">
+ <owner>dvadym@chromium.org</owner>
+ <owner>vabr@chromium.org</owner>
+ <summary>
+ The time between receiving saved credentials from the password store and
+ predictions from the Autofill server. Recorded each time when predictions
+ for a form are received.
+ </summary>
+</histogram>
+
<histogram name="PasswordManager.TimeReadingExportedPasswords" units="ms">
<owner>cfroussios@chromium.org</owner>
<owner>ioanap@chromium.org</owner>
@@ -67037,6 +70379,17 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="PasswordProtection.InterstitialActionByUserNavigation"
+ enum="PasswordProtectionWarningAction" expires_after="M71">
+ <owner>jialiul@chromium.org</owner>
+ <owner>nparker@chromium.org</owner>
+ <summary>
+ When user manually navigates to chrome://reset-password page, records how
+ this user interacts with this page. Logged when the interstitial is shown
+ and when the user chooses to change their password.
+ </summary>
+</histogram>
+
<histogram name="PasswordProtection.InterstitialString"
enum="PasswordProtectionInterstitialStringType">
<owner>jialiul@chromium.org</owner>
@@ -67068,6 +70421,19 @@ uploading your change for review.
</summary>
</histogram>
+<histogram
+ name="PasswordProtection.NumberOfVerdictsMigratedDuringInitialization"
+ units="verdicts" expires_after="M70">
+ <owner>jialiul@chromium.org</owner>
+ <owner>nparker@chromium.org</owner>
+ <summary>
+ We start changing the way of caching password protection verdicts in M69.
+ This histogram counts the number of verdicts migrated to the new way during
+ initialization of PasswordProtectionService. It helps determine when we can
+ remove migration code.
+ </summary>
+</histogram>
+
<histogram name="PasswordProtection.PageInfoAction"
enum="PasswordProtectionWarningAction">
<owner>jialiul@chromium.org</owner>
@@ -67080,6 +70446,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram base="true" name="PasswordProtection.PasswordAlertModeOutcome"
+ enum="PasswordProtectionRequestOutcome">
+ <owner>jialiul@chromium.org</owner>
+ <owner>nparker@chromium.org</owner>
+ <summary>
+ Records the outcome of the password alert mode, indicating if password alert
+ warning is shown successfully or if it is skipped for some reason.
+ </summary>
+</histogram>
+
<histogram name="PasswordProtection.PasswordProtectionResponseOrErrorCode"
enum="CombinedHttpResponseAndNetErrorCode">
<owner>jialiul@chromium.org</owner>
@@ -67114,6 +70490,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="PasswordProtection.ReferrerChainSize" units="referrers"
+ expires_after="M71">
+ <owner>drubery@chromium.org</owner>
+ <owner>jialiul@chromium.org</owner>
+ <summary>
+ The referrer chain size of a password protection request. This is recorded
+ when Chrome receives a verdict for this request.
+ </summary>
+</histogram>
+
<histogram name="PasswordProtection.RequestNetworkDuration" units="ms">
<owner>jialiul@chromium.org</owner>
<owner>nparker@chromium.org</owner>
@@ -68307,7 +71693,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Platform.AsvGroup">
+<histogram name="Platform.AsvGroup" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Chrome OS (ARM Chromebooks using Exynos 5250 only) Adaptive Support Voltage
@@ -68767,7 +72153,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Platform.KernelWarningHashes">
+<histogram name="Platform.KernelWarningHashes" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The 32-bit hash of a kernel warning. This is the hash of the
@@ -68787,7 +72173,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Platform.LotIdEnum" enum="Exynos5250LotIdEnum">
+<histogram name="Platform.LotIdEnum" enum="Exynos5250LotIdEnum"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Chrome OS (ARM Chromebooks using Exynos 5250 only) indication about whether
@@ -68877,6 +72264,27 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Platform.MountEncrypted.EncryptionKeyStatus"
+ enum="MountEncryptedEncryptionKeyStatus">
+ <owner>apronin@chromium.org</owner>
+ <owner>mnissler@chromium.org</owner>
+ <summary>
+ File system encryption key status for the encrypted stateful file system on
+ Chrome OS. The encryption key is the one that is used by the kernel to
+ protect actual file contents on disk.
+ </summary>
+</histogram>
+
+<histogram name="Platform.MountEncrypted.SystemKeyStatus"
+ enum="MountEncryptedSystemKeyStatus">
+ <owner>apronin@chromium.org</owner>
+ <owner>mnissler@chromium.org</owner>
+ <summary>
+ Type/Origin of the system key used for the encrypted stateful file system on
+ Chrome OS. This key is used to wrap the actual file system encryption key.
+ </summary>
+</histogram>
+
<histogram name="Platform.PageFaultsLong" units="page faults/second">
<owner>sonnyrao@chromium.org</owner>
<summary>
@@ -69723,7 +73131,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Platform.Temperature.Sensor00" units="Celsius">
+<histogram name="Platform.Temperature.Sensor00" units="Celsius"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Temperature reading at sensor 0 (I2C_CPU-Die) taken every 30s.
@@ -69737,56 +73146,64 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Platform.Temperature.Sensor02" units="Celsius">
+<histogram name="Platform.Temperature.Sensor02" units="Celsius"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Temperature reading at sensor 2 (I2C_PCH-Die) taken every 30s.
</summary>
</histogram>
-<histogram name="Platform.Temperature.Sensor03" units="Celsius">
+<histogram name="Platform.Temperature.Sensor03" units="Celsius"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Temperature reading at sensor 3 (I2C_PCH-Object) taken every 30s.
</summary>
</histogram>
-<histogram name="Platform.Temperature.Sensor04" units="Celsius">
+<histogram name="Platform.Temperature.Sensor04" units="Celsius"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Temperature reading at sensor 4 (I2C_DDR-Die) taken every 30s.
</summary>
</histogram>
-<histogram name="Platform.Temperature.Sensor05" units="Celsius">
+<histogram name="Platform.Temperature.Sensor05" units="Celsius"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Temperature reading at sensor 5 (I2C_DDR-Object) taken every 30s.
</summary>
</histogram>
-<histogram name="Platform.Temperature.Sensor06" units="Celsius">
+<histogram name="Platform.Temperature.Sensor06" units="Celsius"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Temperature reading at sensor 6 (Charger-Die), taken every 30s.
</summary>
</histogram>
-<histogram name="Platform.Temperature.Sensor07" units="Celsius">
+<histogram name="Platform.Temperature.Sensor07" units="Celsius"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Temperature reading at sensor 7 (Charger-Object) taken every 30s.
</summary>
</histogram>
-<histogram name="Platform.Temperature.Sensor08" units="Celsius">
+<histogram name="Platform.Temperature.Sensor08" units="Celsius"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Temperature reading at sensor 8 (ECInternal) taken every 30s.
</summary>
</histogram>
-<histogram name="Platform.Temperature.Sensor09" units="Celsius">
+<histogram name="Platform.Temperature.Sensor09" units="Celsius"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Temperature reading at sensor 9 (PECI) taken every 30s.</summary>
</histogram>
@@ -71467,7 +74884,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Plugin.FlashNavigateUsage" enum="FlashNavigateUsageType">
+<histogram name="Plugin.FlashNavigateUsage" enum="FlashNavigateUsageType"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Record usage of PPB_Flash.Navigate() Pepper API.</summary>
</histogram>
@@ -71589,7 +75007,7 @@ uploading your change for review.
<summary>The time spent to load a PPAPI plugin.</summary>
</histogram>
-<histogram name="Plugin.PpapiSyncIPCTime" units="ms">
+<histogram name="Plugin.PpapiSyncIPCTime" units="ms" expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
The time it took to complete a synchronous IPC made from the PPAPI process.
@@ -72427,6 +75845,15 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="PowerML.PreviousEventLogging.Result"
+ enum="PowerMLPreviousEventLoggingResult">
+ <owner>jiameng@chromium.org</owner>
+ <summary>
+ Status of logging previous idle event after a screen dim imminent signal is
+ received.
+ </summary>
+</histogram>
+
<histogram name="Precache.BatteryPercentage.Start" units="%">
<obsolete>
Deprecated July 11 2017.
@@ -72916,7 +76343,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="PreloadScanner.ExternalCSS.PreloadCount" units="preloads">
+<histogram name="PreloadScanner.ExternalCSS.PreloadCount" units="preloads"
+ expires_after="2018-08-30">
<owner>csharrison@chromium.org</owner>
<summary>
The number of preloads generated by scanning an external preloaded CSS
@@ -72924,14 +76352,17 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="PreloadScanner.ExternalCSS.ScanTime" units="microseconds">
+<histogram name="PreloadScanner.ExternalCSS.ScanTime" units="microseconds"
+ expires_after="2018-08-30">
<owner>csharrison@chromium.org</owner>
<summary>
Microseconds it took to scan the first chunk of external CSS for preloads.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -74068,6 +77499,9 @@ uploading your change for review.
</histogram>
<histogram name="Previews.OptOut.DBRowCount" units="rows">
+ <obsolete>
+ No longer used as of 06/2018.
+ </obsolete>
<owner>ryansturm@chromium.org</owner>
<summary>
The number of rows in the Previews opt out SQLite table at profile startup.
@@ -74075,6 +77509,9 @@ uploading your change for review.
</histogram>
<histogram name="Previews.OptOut.SQLiteLoadError" enum="SqliteErrorCode">
+ <obsolete>
+ No longer used as of 06/2018.
+ </obsolete>
<owner>ryansturm@chromium.org</owner>
<summary>
The SQLite error code that the previews opt out store saw when trying to
@@ -74632,12 +78069,12 @@ uploading your change for review.
<summary>Load status of an avatar for decorating the Windows taskbar</summary>
</histogram>
-<histogram name="Profile.BookmarksSize" units="MB">
+<histogram name="Profile.BookmarksSize" units="MB" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Size of the bookmarks database.</summary>
</histogram>
-<histogram name="Profile.CookiesSize" units="MB">
+<histogram name="Profile.CookiesSize" units="MB" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Size of the cookies database.</summary>
</histogram>
@@ -74750,12 +78187,12 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Profile.ExtensionSize" units="MB">
+<histogram name="Profile.ExtensionSize" units="MB" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Size of the extension cookies database.</summary>
</histogram>
-<histogram name="Profile.FaviconsSize" units="MB">
+<histogram name="Profile.FaviconsSize" units="MB" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Size of the favicons database.</summary>
</histogram>
@@ -75103,7 +78540,7 @@ uploading your change for review.
</histogram>
<histogram name="Profile.SwitchGaiaPhotoSettings"
- enum="ProfileGaiaPhotoOptions">
+ enum="ProfileGaiaPhotoOptions" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Counts of when users switch to using their GAIA photo instead of an avatar
@@ -75120,7 +78557,8 @@ uploading your change for review.
<summary>Activity of the user with regards to sync.</summary>
</histogram>
-<histogram name="Profile.SyncCustomize" enum="ProfileSyncCustomize">
+<histogram name="Profile.SyncCustomize" enum="ProfileSyncCustomize"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
Number of times and ways the user customized the sync options of their
@@ -75153,17 +78591,18 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Profile.TopSitesSize" units="MB">
+<histogram name="Profile.TopSitesSize" units="MB" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Size of the top sites database.</summary>
</histogram>
-<histogram name="Profile.TotalHistorySize" units="MB">
+<histogram name="Profile.TotalHistorySize" units="MB"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Total size of all history databases.</summary>
</histogram>
-<histogram name="Profile.TotalSize" units="MB">
+<histogram name="Profile.TotalSize" units="MB" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Total size of the profile data (excluding sub-folders).</summary>
</histogram>
@@ -75219,16 +78658,26 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Profile.VisitedLinksSize" units="MB">
+<histogram name="Profile.VisitedLinksSize" units="MB"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Size of the visited links database.</summary>
</histogram>
-<histogram name="Profile.WebDataSize" units="MB">
+<histogram name="Profile.WebDataSize" units="MB" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>Size of the web data database.</summary>
</histogram>
+<histogram name="ProfileChooser.HasProfilesShown" enum="BooleanShown">
+ <owner>vasilii@chromium.org</owner>
+ <owner>ewald@chromium.org</owner>
+ <summary>
+ Whether any profile was shown in the list when the profile chooser was
+ opened.
+ </summary>
+</histogram>
+
<histogram name="ProfileReset.ResetRequestOrigin"
enum="ProfileResetRequestOriginEnum">
<owner>alito@chromium.org</owner>
@@ -75807,7 +79256,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Quota.ErrorsOnEvictingOriginPerHour">
+<histogram name="Quota.ErrorsOnEvictingOriginPerHour"
+ expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>
Number of errors on evicting origin by QuotaTemporaryStorageEvictor in an
@@ -75815,7 +79265,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Quota.ErrorsOnGettingUsageAndQuotaPerHour">
+<histogram name="Quota.ErrorsOnGettingUsageAndQuotaPerHour"
+ expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>
Number of errors on getting usage and quota by QuotaTemporaryStorageEvictor
@@ -75908,32 +79359,38 @@ uploading your change for review.
<summary>Number of evicted origins per round.</summary>
</histogram>
-<histogram name="Quota.NumberOfPersistentStorageOrigins">
+<histogram name="Quota.NumberOfPersistentStorageOrigins"
+ expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>Number of origins using persistent storage.</summary>
</histogram>
-<histogram name="Quota.NumberOfProtectedPersistentStorageOrigins">
+<histogram name="Quota.NumberOfProtectedPersistentStorageOrigins"
+ expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>Number of protected origins using persistent storage.</summary>
</histogram>
-<histogram name="Quota.NumberOfProtectedTemporaryStorageOrigins">
+<histogram name="Quota.NumberOfProtectedTemporaryStorageOrigins"
+ expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>Number of protected origins using temporary storage.</summary>
</histogram>
-<histogram name="Quota.NumberOfTemporaryStorageOrigins">
+<histogram name="Quota.NumberOfTemporaryStorageOrigins"
+ expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>Number of origins using temporary storage.</summary>
</histogram>
-<histogram name="Quota.NumberOfUnlimitedPersistentStorageOrigins">
+<histogram name="Quota.NumberOfUnlimitedPersistentStorageOrigins"
+ expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>Number of unlimited origins using persistent storage.</summary>
</histogram>
-<histogram name="Quota.NumberOfUnlimitedTemporaryStorageOrigins">
+<histogram name="Quota.NumberOfUnlimitedTemporaryStorageOrigins"
+ expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>Number of unlimited origins using temporary storage.</summary>
</histogram>
@@ -75984,7 +79441,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Quota.SkippedEvictionRoundsPerHour">
+<histogram name="Quota.SkippedEvictionRoundsPerHour" expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>Number of skipped eviction rounds in an hour.</summary>
</histogram>
@@ -76003,7 +79460,7 @@ uploading your change for review.
<summary>Time between two consecutive active eviction rounds.</summary>
</histogram>
-<histogram name="Quota.TimeSpentToAEvictionRound">
+<histogram name="Quota.TimeSpentToAEvictionRound" expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>Time spent to an eviction round.</summary>
</histogram>
@@ -76034,7 +79491,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Quota.UsageOverageOfTemporaryGlobalStorage" units="MB">
+<histogram name="Quota.UsageOverageOfTemporaryGlobalStorage" units="MB"
+ expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>
Overage of the temporary global storage usage at beginning of an eviction
@@ -76607,6 +80065,10 @@ uploading your change for review.
</histogram>
<histogram name="Renderer4.CompositorThreadImplDrawDelay" units="ms">
+ <obsolete>
+ Deprecated in 06/2018, M69. Renderer4.CompositorThreadImplDrawDelay is no
+ longer needed due to issue 851784.
+ </obsolete>
<owner>wiltzius@chromium.org</owner>
<summary>
Time between frames, as measured on the compositor thread. This is collected
@@ -76832,9 +80294,11 @@ uploading your change for review.
the compositor. It is recorded every time we decode an image. It is suffixed
by the type of rasterization we're in (either Gpu or Software).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -76847,9 +80311,11 @@ uploading your change for review.
in the compositor. It is recorded every time we decode an image. It is
suffixed by the type of rasterization we're in (either Gpu or Software).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -76880,6 +80346,10 @@ uploading your change for review.
</histogram>
<histogram name="Renderer4.LanguageDetection" units="ms">
+ <obsolete>
+ Deprecated in 06/2018, M69. Renderer4.LanguageDetection is no longer needed
+ due to issue 851784.
+ </obsolete>
<owner>wiltzius@chromium.org</owner>
<summary>
Time to determine the page language. This is done after the page has been
@@ -77065,6 +80535,10 @@ uploading your change for review.
</histogram>
<histogram name="Renderer4.SoftwareCompositorThreadImplDrawDelay" units="ms">
+ <obsolete>
+ Deprecated in 06/2018, M69. Renderer4.SoftwareCompositorThreadImplDrawDelay
+ is no longer needed due to issue 851784.
+ </obsolete>
<owner>wiltzius@chromium.org</owner>
<summary>
Time between frames when the software renderer is being used, as measured on
@@ -77143,9 +80617,11 @@ uploading your change for review.
Time between the issue of a texture copy operation and detecting that it has
completed as measured by the GPU process.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -77222,6 +80698,10 @@ uploading your change for review.
<histogram name="RendererScheduler.BackgroundedRendererTransition"
enum="BackgroundedRendererTransition">
+ <obsolete>
+ Deprecated 6/2018 and replaced with
+ PageScheduler.PageLifecycleStateTransition.
+ </obsolete>
<owner>fmeawad@chromium.org</owner>
<owner>panicker@chromium.org</owner>
<summary>
@@ -77392,10 +80872,6 @@ uploading your change for review.
The estimated queueing duration which would be observed for additional high
priority tasks posted to the RendererScheduler, in microseconds. Recorded
for each 1000 ms window.
-
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
</summary>
</histogram>
@@ -77407,6 +80883,31 @@ uploading your change for review.
The estimated queueing duration which would be observed for additional high
priority tasks posted to the RendererScheduler, in microseconds. Recorded
for each 1000 ms window.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
+<histogram
+ name="RendererScheduler.ExpectedTaskQueueingDurationWithoutMainFrame"
+ units="microseconds">
+ <owner>tdresser@chromium.org</owner>
+ <owner>npm@chromium.org</owner>
+ <summary>
+ The estimated queueing duration which would be observed for additional high
+ priority tasks posted to the RendererScheduler, in microseconds, for
+ renderer processes that do not host any main frame. Recorded for each 1000
+ ms window.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -77597,6 +81098,12 @@ uploading your change for review.
<histogram name="RendererScheduler.TaskCPUDurationPerTaskType.DedicatedWorker"
enum="RendererSchedulerTaskType" units="ms">
+ <obsolete>
+ Replaced with RendererScheduler.TaskCPUDurationPerTaskType2.DedicatedWorker
+ as of June 2018 due to overflows (crbug.com/809668). Some metrics are
+ incremented with large amounts that they sometimes overflow and roll
+ negative before they get uploaded.
+ </obsolete>
<owner>altimin@chromium.org</owner>
<summary>
Total duration of dedicated worker tasks (thread time) split by per thread
@@ -77608,8 +81115,30 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="RendererScheduler.TaskCPUDurationPerTaskType2.DedicatedWorker"
+ enum="RendererSchedulerTaskType">
+ <owner>altimin@chromium.org</owner>
+ <summary>
+ Total duration (reported in full seconds) of dedicated worker tasks (thread
+ time) split by per thread type. Note that partial seconds are rounded
+ up/down so that they average to the correct value when many reports are
+ added. For more details, check base::ScaledLinearHistogram.
+
+ This is reported each time a task is completed.
+
+ Note that this metric discards tasks longer than 30 seconds because they are
+ considered to be a result of measurement glitch.
+ </summary>
+</histogram>
+
<histogram name="RendererScheduler.TaskCPUDurationPerThreadType"
enum="RendererSchedulerThreadType" units="ms">
+ <obsolete>
+ Replaced with RendererScheduler.TaskCPUDurationPerThreadType2 as of June
+ 2018 due to overflows (crbug.com/809668). Some metrics are incremented with
+ large amounts that they sometimes overflow and roll negative before they get
+ uploaded.
+ </obsolete>
<owner>altimin@chromium.org</owner>
<summary>
Total cpu time of renderer tasks split by per thread type. Wall time is
@@ -77624,8 +81153,35 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="RendererScheduler.TaskCPUDurationPerThreadType2"
+ enum="RendererSchedulerThreadType">
+ <owner>altimin@chromium.org</owner>
+ <summary>
+ Total cpu time (reported in full seconds) of renderer tasks split by per
+ thread type. Note that partial seconds are rounded up/down so that they
+ average to the correct value when many reports are added. For more details,
+ check base::ScaledLinearHistogram.
+
+ Wall time is tracked by RendererScheduler.TaskDurationPerThreadType
+ histogram. This histogram is used to compare CPU usage of tasks from
+ different threads.
+
+ Only 1% of randomly sampled tasks have cpu time measured and report duration
+ for this histogram.
+
+ Note that this metric discards tasks longer than 30 seconds because they are
+ considered to be a result of measurement glitch.
+ </summary>
+</histogram>
+
<histogram base="true" name="RendererScheduler.TaskDurationPerFrameOriginType"
enum="RendererSchedulerFrameOriginType">
+ <obsolete>
+ Replaced with RendererScheduler.TaskDurationPerFrameOriginType2 as of June
+ 2018 due to overflows (crbug.com/809668). Some metrics are incremented with
+ large amounts that they sometimes overflow and roll negative before they get
+ uploaded.
+ </obsolete>
<owner>altimin@chromium.org</owner>
<summary>
Total cpu time of renderer tasks split by per frame origin type (main frame
@@ -77636,6 +81192,21 @@ uploading your change for review.
</summary>
</histogram>
+<histogram base="true" name="RendererScheduler.TaskDurationPerFrameOriginType2"
+ enum="RendererSchedulerFrameOriginType">
+ <owner>altimin@chromium.org</owner>
+ <summary>
+ Total cpu time (reported in full seconds) of renderer tasks split by per
+ frame origin type (main frame vs same-origin frame vs cross-origin frame).
+ Note that partial seconds are rounded up/down so that they average to the
+ correct value when many reports are added. For more details, check
+ base::ScaledLinearHistogram.
+
+ Note that this metric discards tasks longer than 30 seconds because they are
+ considered to be a result of measurement glitch.
+ </summary>
+</histogram>
+
<histogram name="RendererScheduler.TaskDurationPerFrameType"
enum="RendererSchedulerFrameType" units="ms">
<obsolete>
@@ -77655,6 +81226,12 @@ uploading your change for review.
<histogram name="RendererScheduler.TaskDurationPerFrameType2"
enum="RendererSchedulerFrameType2" units="ms">
+ <obsolete>
+ Replaced with RendererScheduler.TaskDurationPerFrameType3 as of June 2018
+ due to overflows (crbug.com/809668). Some metrics are incremented with large
+ amounts that they sometimes overflow and roll negative before they get
+ uploaded.
+ </obsolete>
<owner>altimin@chromium.org</owner>
<summary>
Total duration of renderer per-frame tasks split per frame type. Used to
@@ -77666,6 +81243,23 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="RendererScheduler.TaskDurationPerFrameType3"
+ enum="RendererSchedulerFrameType2">
+ <owner>altimin@chromium.org</owner>
+ <summary>
+ Total duration (reported in full seconds) of renderer per-frame tasks split
+ per frame type. Note that partial seconds are rounded up/down so that they
+ average to the correct value when many reports are added. For more details,
+ check base::ScaledLinearHistogram.
+
+ Used to monitor workload coming from different frames. Reported each time a
+ task is completed.
+
+ This metric is susceptible to problematic outliers and should be analyzed
+ with custom scripts accounting for that rather than from a dashboard.
+ </summary>
+</histogram>
+
<histogram name="RendererScheduler.TaskDurationPerQueueType"
enum="RendererSchedulerTaskQueueType" units="ms">
<obsolete>
@@ -77685,6 +81279,12 @@ uploading your change for review.
<histogram name="RendererScheduler.TaskDurationPerQueueType2"
enum="RendererSchedulerTaskQueueType" units="ms">
+ <obsolete>
+ Replaced with RendererScheduler.TaskDurationPerQueueType3 as of June 2018
+ due to overflows (crbug.com/809668). Some metrics are incremented with large
+ amounts that they sometimes overflow and roll negative before they get
+ uploaded.
+ </obsolete>
<owner>altimin@chromium.org</owner>
<owner>alexclarke@chromium.org</owner>
<summary>
@@ -77700,8 +81300,32 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="RendererScheduler.TaskDurationPerQueueType3"
+ enum="RendererSchedulerTaskQueueType">
+ <owner>altimin@chromium.org</owner>
+ <owner>alexclarke@chromium.org</owner>
+ <summary>
+ Total duration (reported in full seconds) of renderer tasks split per task
+ queue type. Note that partial seconds are rounded up/down so that they
+ average to the correct value when many reports are added. For more details,
+ check base::ScaledLinearHistogram.
+
+ Used to monitor usage of each type of task queues. Reported each time a task
+ is completed.
+
+ This metric is susceptible to problematic outliers and should be analyzed
+ with custom scripts accounting for that rather than from a dashboard.
+ </summary>
+</histogram>
+
<histogram name="RendererScheduler.TaskDurationPerTaskType"
enum="RendererSchedulerTaskType" units="ms">
+ <obsolete>
+ Replaced with RendererScheduler.TaskDurationPerTaskType2 as of June 2018 due
+ to overflows (crbug.com/809668). Some metrics are incremented with large
+ amounts that they sometimes overflow and roll negative before they get
+ uploaded.
+ </obsolete>
<owner>altimin@chromium.org</owner>
<owner>hajimehoshi@chromium.org</owner>
<summary>
@@ -77716,6 +81340,12 @@ uploading your change for review.
<histogram name="RendererScheduler.TaskDurationPerTaskType.DedicatedWorker"
enum="RendererSchedulerTaskType" units="ms">
+ <obsolete>
+ Replaced with RendererScheduler.TaskDurationPerTaskType2.DedicatedWorker as
+ of June 2018 due to due to overflows (crbug.com/809668). Some metrics are
+ incremented with large amounts that they sometimes overflow and roll
+ negative before they get uploaded.
+ </obsolete>
<owner>altimin@chromium.org</owner>
<summary>
Total duration of dedicated worker tasks (wall time) split by per thread
@@ -77727,8 +81357,48 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="RendererScheduler.TaskDurationPerTaskType2"
+ enum="RendererSchedulerTaskType">
+ <owner>altimin@chromium.org</owner>
+ <owner>hajimehoshi@chromium.org</owner>
+ <summary>
+ Total duration (reported in full seconds) of renderer per-frame tasks split
+ per task type. Note that partial seconds are rounded up/down so that they
+ average to the correct value when many reports are added. For more details,
+ check base::ScaledLinearHistogram.
+
+ Used to monitor usage of each task type. Reported each time a task is
+ completed.
+
+ This metric is susceptible to problematic outliers and should be analyzed
+ with custom scripts accounting for that rather than from a dashboard.
+ </summary>
+</histogram>
+
+<histogram name="RendererScheduler.TaskDurationPerTaskType2.DedicatedWorker"
+ enum="RendererSchedulerTaskType">
+ <owner>altimin@chromium.org</owner>
+ <summary>
+ Total duration (repored in full seconds) of dedicated worker tasks (wall
+ time) split by per thread type. Note that partial seconds are rounded
+ up/down so that they average to the correct value when many reports are
+ added. For more details, check base::ScaledLinearHistogram.
+
+ Reported each time a task is completed.
+
+ Note that this metric discards tasks longer than 30 seconds because they are
+ considered to be a result of measurement glitch.
+ </summary>
+</histogram>
+
<histogram name="RendererScheduler.TaskDurationPerThreadType"
enum="RendererSchedulerThreadType" units="ms">
+ <obsolete>
+ Replaced with RendererScheduler.TaskDurationPerThreadType2 as of June 2018
+ due to overflows (crbug.com/809668). Some metrics are incremented with large
+ amounts that they sometimes overflow and roll negative before they get
+ uploaded.
+ </obsolete>
<owner>altimin@chromium.org</owner>
<owner>lpy@chromium.org</owner>
<summary>
@@ -77741,8 +81411,32 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="RendererScheduler.TaskDurationPerThreadType2"
+ enum="RendererSchedulerThreadType">
+ <owner>altimin@chromium.org</owner>
+ <owner>lpy@chromium.org</owner>
+ <summary>
+ Total duration (reported in full seconds) of renderer tasks split by per
+ thread type. Note that partial seconds are rounded up/down so that they
+ average to the correct value when many reports are added. For more details,
+ check base::ScaledLinearHistogram.
+
+ Used to compare CPU usage of tasks from different threads. Reported each
+ time a task is completed.
+
+ Note that this metric discards tasks longer than 30 seconds because they are
+ considered to be a result of measurement glitch.
+ </summary>
+</histogram>
+
<histogram name="RendererScheduler.TaskDurationPerUseCase"
enum="RendererSchedulerTaskUseCase">
+ <obsolete>
+ Replaced with RendererScheduler.TaskDurationPerUseCase2 as of June 2018 due
+ to overflows (crbug.com/809668). Some metrics are incremented with large
+ amounts that they sometimes overflow and roll negative before they get
+ uploaded.
+ </obsolete>
<owner>altimin@chromium.org</owner>
<owner>farahcharab@chromium.org</owner>
<summary>
@@ -77753,6 +81447,23 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="RendererScheduler.TaskDurationPerUseCase2"
+ enum="RendererSchedulerTaskUseCase">
+ <owner>altimin@chromium.org</owner>
+ <owner>farahcharab@chromium.org</owner>
+ <summary>
+ Total duration (reported in full seconds) of renderer main thread tasks
+ split by scheduler use case. Note that partial seconds are rounded up/down
+ so that they average to the correct value when many reports are added. For
+ more details, check base::ScaledLinearHistogram.
+
+ Use case is a scheduler's educated guess of the current state of the world.
+ See renderer/use_case.h and
+
+ RendererSchedulerImpl::UpdatePolicy for more details.
+ </summary>
+</histogram>
+
<histogram name="RendererScheduler.TaskQueueManager.DelayedTaskLateness"
units="ms">
<obsolete>
@@ -77801,6 +81512,12 @@ uploading your change for review.
Note that this metric discards tasks longer than 30 seconds because they are
considered to be a result of measurement glitch.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -77908,6 +81625,20 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="RenderFrameHostImpl.ReceivedPostMessageFromNonDescendant"
+ enum="BooleanReceived" expires_after="2018-10-30">
+ <owner>alexmos@chromium.org</owner>
+ <owner>boliu@chromium.org</owner>
+ <summary>
+ Record whether a local root frame ever received post messages from another
+ cross origin frame that's not a descendent. This is useful to evaluate if a
+ frame is safe to be reloaded automatically. Recorded when a frame crashed
+ while invisible, and then becomes visible to the user; this is the point a
+ crashed frame would be reloaded. Note this is not logged for the main frame,
+ which only has descendant frames.
+ </summary>
+</histogram>
+
<histogram name="RenderFrameObservers.DidChangeScrollOffset" units="ms">
<obsolete>
Deprecated 2/2018
@@ -78333,6 +82064,79 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="ResourceCoordinator.LocalDB.DatabaseInit"
+ enum="LocalSiteCharacteristicsDBInitStatus">
+ <owner>sebmarchand@chromium.org</owner>
+ <summary>
+ The result of opening the Local Site Characteristics database.
+ </summary>
+</histogram>
+
+<histogram name="ResourceCoordinator.LocalDB.DatabaseInitAfterDelete"
+ enum="LocalSiteCharacteristicsDBInitStatus">
+ <owner>sebmarchand@chromium.org</owner>
+ <summary>
+ The result of opening the Local Site Characteristics database after deleting
+ it after a failed repair attempt.
+ </summary>
+</histogram>
+
+<histogram name="ResourceCoordinator.LocalDB.DatabaseInitAfterRepair"
+ enum="LocalSiteCharacteristicsDBInitStatus">
+ <owner>sebmarchand@chromium.org</owner>
+ <summary>
+ The result of opening the Local Site Characteristics database after a repair
+ attempt.
+ </summary>
+</histogram>
+
+<histogram name="ResourceCoordinator.LocalDB.DatabaseRepair"
+ enum="BooleanSuccess">
+ <owner>sebmarchand@chromium.org</owner>
+ <summary>
+ The result of trying to repair the Local Site Characteristics database after
+ a failed open.
+ </summary>
+</histogram>
+
+<histogram name="ResourceCoordinator.LocalDB.ObservationTimeBeforeFirstUse"
+ units="ms">
+<!-- Name completed by histogram_suffixes name="LocalSiteCharacteristicsFeatures" -->
+
+ <owner>sebmarchand@chromium.org</owner>
+ <summary>
+ The cumulative observation time before a feature tracked in the Local Site
+ Characteristics database gets used.
+ </summary>
+</histogram>
+
+<histogram name="ResourceCoordinator.LocalDB.OnDiskSize" units="KB">
+ <owner>sebmarchand@chromium.org</owner>
+ <summary>
+ The size of the Local Site Characteristics database on disk. Recorded at
+ startup when the database gets opened.
+ </summary>
+</histogram>
+
+<histogram name="ResourceCoordinator.LocalDB.ReadHasCompletedBeforeQuery"
+ enum="Boolean">
+ <owner>sebmarchand@chromium.org</owner>
+ <summary>
+ Boolean indicating if the read operation from the Local Site Characteristics
+ database has completed when we query for the characteristics of a site.
+ </summary>
+</histogram>
+
+<histogram name="ResourceLoadingHints.CountBlockedSubresourcePatterns"
+ units="pattern count">
+ <owner>tbansal@chromium.org</owner>
+ <summary>
+ The count of resource loading blocking patterns received by the renderer.
+ Recorded every time resource loading hints mojom message is received.
+ Recorded at most once per triggered navigation.
+ </summary>
+</histogram>
+
<histogram name="ResourcePrefetchPredictor.CachePattern"
enum="HttpCachePattern">
<obsolete>
@@ -80080,9 +83884,11 @@ uploading your change for review.
dominated by the time to perform checks for CheckBrowseUrl. Note that this
metric is recorded even for users with low resolution clocks.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -81407,9 +85213,11 @@ uploading your change for review.
extra work. Note that this does include task queue time to respond to the
IPC (and that queue time is often non-trivial).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -81421,9 +85229,11 @@ uploading your change for review.
Java_SafeBrowsingApiBridge_startUriLookup. Logged at every Safe Browsing
check on Android.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -81450,12 +85260,39 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="SB2.RemoteCall.InternalErrorStatusCode">
+ <obsolete>
+ No longer generated. Replaced by SB2.RemoteCall.InternalErrorStatusCode2
+ </obsolete>
+ <owner>vakh@chromium.org</owner>
+ <summary>
+ The status code provided by GmsCore if it is unable to respond to a URL
+ check request due to incorrect initialization, not being ready, etc. Logged
+ on each URL check that hits the internal error condition. The total number
+ of these should add up to the INTERNAL_ERROR reports under
+ SB2.RemoteCall.Result.
+ </summary>
+</histogram>
+
+<histogram name="SB2.RemoteCall.InternalErrorStatusCode2"
+ enum="GooglePlayServicesConnectionResult">
+ <owner>vakh@chromium.org</owner>
+ <summary>
+ The status code provided by GmsCore if it is unable to respond to a URL
+ check request due to incorrect initialization, not being ready, etc. Logged
+ on each URL check that hits the internal error condition. The total number
+ of these should add up to the INTERNAL_ERROR reports under
+ SB2.RemoteCall.Result.
+ </summary>
+</histogram>
+
<histogram name="SB2.RemoteCall.Result" enum="SB2RemoteCallResult">
<owner>nparker@chromium.org</owner>
<summary>
Result of URL-classification API calls from Chrome via
RemoteSafeBrowsingApiHandler. Logged after each URL is judged
- safe/not-safe, or hits a deadline.
+ safe/not-safe, or hits a deadline. The INTERNAL_ERROR cases are further
+ classified under SB2.RemoteCall.InternalErrorStatusCode.
</summary>
</histogram>
@@ -81931,13 +85768,14 @@ uploading your change for review.
</histogram>
<histogram name="SBClientDownload.PPAPIDownloadRequest.RequestDuration"
- units="ms">
+ units="ms" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>Time taken to complete a PPAPIDownloadRequest.</summary>
</histogram>
<histogram name="SBClientDownload.PPAPIDownloadRequest.RequestOutcome"
- enum="SBClientDownloadPPAPIDownloadRequestOutcome">
+ enum="SBClientDownloadPPAPIDownloadRequestOutcome"
+ expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>
Outcome of running CheckPPAPIDownloadRequest. Most failure modes cause an
@@ -81949,11 +85787,66 @@ uploading your change for review.
</histogram>
<histogram name="SBClientDownload.PPAPIDownloadRequest.Result"
- enum="SBClientDownloadCheckResult">
+ enum="SBClientDownloadCheckResult" expires_after="2018-08-30">
<owner>asanka@chromium.org</owner>
<summary>Result returned to the caller of CheckPPAPIDownloadRequest.</summary>
</histogram>
+<histogram name="SBClientDownload.RarFileArchivedBinariesCount" units="count">
+ <owner>vakh@chromium.org</owner>
+ <summary>
+ The original number of archived_binaries found in a rar-like file when it's
+ scanned, if at least one is found. The actual number sent in the download
+ request may be capped below this value.
+ </summary>
+</histogram>
+
+<histogram name="SBClientDownload.RarFileHasArchiveButNoExecutable"
+ enum="Boolean">
+ <owner>vakh@chromium.org</owner>
+ <summary>
+ For each rar file analyzed by the SafeBrowsing download service, records
+ true if the rar did not contain any executables but did contain another
+ archive file, false otherwise.
+ </summary>
+</histogram>
+
+<histogram name="SBClientDownload.RarFileHasExecutable" enum="Boolean">
+ <owner>vakh@chromium.org</owner>
+ <summary>
+ For each rar file analyzed by the SafeBrowsing download service, records if
+ the rar contained an executable file.
+ </summary>
+</histogram>
+
+<histogram name="SBClientDownload.RarFileSuccess" enum="BooleanSuccess">
+ <owner>vakh@chromium.org</owner>
+ <summary>
+ For each rar file analyzed by the SafeBrowsing download service, records if
+ the unpacking was 100% successful.
+ </summary>
+</histogram>
+
+<histogram name="SBClientDownload.RarOpenSuccess" enum="BooleanSuccess">
+ <owner>vakh@chromium.org</owner>
+ <summary>
+ For each rar file analyzed by the SafeBrowsing download service, records if
+ the file could be opened. This should be close to 100% success because the
+ library doesn't actually open the file; it is handed an open file handle and
+ the Open() function call sets that as the file handle to use.
+ </summary>
+</histogram>
+
+<histogram name="SBClientDownload.RarValidArchive" enum="BooleanSuccess">
+ <owner>vakh@chromium.org</owner>
+ <summary>
+ For each rar file analyzed by the SafeBrowsing download service, records if
+ the unrar library considers this file a valid RAR archive. It includes
+ checking the following, and more: magic number is present, valid RAR version
+ format can be parsed, headers are valid, etc.
+ </summary>
+</histogram>
+
<histogram name="SBClientDownload.SignedBinaryDownload"
enum="SBClientDownloadIsSignedBinary">
<owner>mattm@chromium.org</owner>
@@ -82183,7 +86076,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="SBClientPhishing.DOMFeatureResumeTime" units="ms">
+<histogram name="SBClientPhishing.DOMFeatureResumeTime" units="ms"
+ expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
The time that it took to resume DOM feature extraction for the phishing
@@ -82472,17 +86366,20 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="SBIRS.DownloadMetadata.DeleteSuccess" enum="BooleanSuccess">
+<histogram name="SBIRS.DownloadMetadata.DeleteSuccess" enum="BooleanSuccess"
+ expires_after="2018-08-30">
<owner>caitkp@chromium.org</owner>
<summary>The result of deleting a profile's download metadata file.</summary>
</histogram>
-<histogram name="SBIRS.DownloadMetadata.ReadResult" enum="MetadataReadResult">
+<histogram name="SBIRS.DownloadMetadata.ReadResult" enum="MetadataReadResult"
+ expires_after="2018-08-30">
<owner>caitkp@chromium.org</owner>
<summary>The result of reading a profile's download metadata file.</summary>
</histogram>
-<histogram name="SBIRS.DownloadMetadata.WriteResult" enum="MetadataWriteResult">
+<histogram name="SBIRS.DownloadMetadata.WriteResult" enum="MetadataWriteResult"
+ expires_after="2018-08-30">
<owner>caitkp@chromium.org</owner>
<summary>The result of writing a profile's download metadata file.</summary>
</histogram>
@@ -82495,7 +86392,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="SBIRS.EnvCollectionTime" units="ms">
+<histogram name="SBIRS.EnvCollectionTime" units="ms" expires_after="2018-08-30">
<owner>caitkp@google.com</owner>
<summary>
The elapsed time to collect environmental data for a safe browsing incident
@@ -82503,7 +86400,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="SBIRS.FindDownloadedBinaryTime" units="ms">
+<histogram name="SBIRS.FindDownloadedBinaryTime" units="ms"
+ expires_after="2018-08-30">
<owner>caitkp@google.com</owner>
<summary>
The elapsed time to find the most recent binary download from all loaded
@@ -82527,7 +86425,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="SBIRS.InterIncidentTime" units="ms">
+<histogram name="SBIRS.InterIncidentTime" units="ms" expires_after="2018-08-30">
<owner>caitkp@google.com</owner>
<summary>
The elapsed time between two successive incidents collated into the same
@@ -82536,7 +86434,7 @@ uploading your change for review.
</histogram>
<histogram name="SBIRS.NoDownloadIncident" enum="IncidentType">
- <owner>caitkp@google.com</owner>
+ <owner>proberge@google.com</owner>
<summary>
The type of incident pruned by the safe browsing incident reporting service
as a result of not having a matching binary download.
@@ -82544,7 +86442,7 @@ uploading your change for review.
</histogram>
<histogram name="SBIRS.PrunedIncident" enum="IncidentType">
- <owner>caitkp@google.com</owner>
+ <owner>proberge@google.com</owner>
<summary>
The type of incident pruned from a report in the safe browsing incident
reporting service as a result of having previously been reported.
@@ -82584,7 +86482,7 @@ uploading your change for review.
</histogram>
<histogram name="SBIRS.ReportPayloadSize" units="bytes">
- <owner>caitkp@google.com</owner>
+ <owner>proberge@google.com</owner>
<summary>The size, in bytes, of a safe browsing incident report.</summary>
</histogram>
@@ -82637,28 +86535,32 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="SBIRS.VerifyBinaryIntegrity.0" units="ms">
+<histogram name="SBIRS.VerifyBinaryIntegrity.0" units="ms"
+ expires_after="2018-08-30">
<owner>caitkp@google.com</owner>
<summary>
The elapsed time to verify the binary integrity of chrome.exe.
</summary>
</histogram>
-<histogram name="SBIRS.VerifyBinaryIntegrity.1" units="ms">
+<histogram name="SBIRS.VerifyBinaryIntegrity.1" units="ms"
+ expires_after="2018-08-30">
<owner>caitkp@google.com</owner>
<summary>
The elapsed time to verify the binary integrity of chrome.dll.
</summary>
</histogram>
-<histogram name="SBIRS.VerifyBinaryIntegrity.2" units="ms">
+<histogram name="SBIRS.VerifyBinaryIntegrity.2" units="ms"
+ expires_after="2018-08-30">
<owner>caitkp@google.com</owner>
<summary>
The elapsed time to verify the binary integrity of chrome_child.dll.
</summary>
</histogram>
-<histogram name="SBIRS.VerifyBinaryIntegrity.3" units="ms">
+<histogram name="SBIRS.VerifyBinaryIntegrity.3" units="ms"
+ expires_after="2018-08-30">
<owner>caitkp@google.com</owner>
<summary>
The elapsed time to verify the binary integrity of chrome_elf.dll.
@@ -82819,6 +86721,37 @@ uploading your change for review.
</summary>
</histogram>
+<histogram base="true" name="Scheduler.Experimental.Renderer.CPUTimePerThread"
+ enum="RendererSchedulerThreadType">
+ <owner>altimin@chromium.org</owner>
+ <summary>
+ Total cpu time of scheduler-managed threads in the renderer process.
+
+ It is supposed that Scheduler.Experimental.Renderer.CPUTimePerThread.Tracked
+ and Scheduler.Experimental.Renderer.CPUTimePerThread.Untracked histograms
+ should be analysed together.
+
+ The bucket value is the sum of thread durations of all tasks in this thread
+ across all browsing instances. This metric is reported each time we execute
+ a task. Due to thread time being expensive to measure, only 0.01% of threads
+ report this metric.
+ </summary>
+</histogram>
+
+<histogram base="true"
+ name="Scheduler.Experimental.Renderer.TotalTime.Wall.MainThread" units="s">
+ <owner>altimin@chromium.org</owner>
+ <summary>
+ Sum of durations of all scheduler-managed tasks in the renderer process.
+
+ Due to implementation constraints a difference between .Positive and
+ .Negative subhistograms should be analysed. See
+ blink::scheduler::TotalDurationMetricReporter for details.
+
+ These metrics are updated each time a new task is executed.
+ </summary>
+</histogram>
+
<histogram name="Scheduling.ActivateDuration" units="microseconds">
<obsolete>
Replaced by ActivateDuration2, due to inefficient bucketing scheme.
@@ -82827,10 +86760,6 @@ uploading your change for review.
<summary>
How long it takes for the compositor to simply activate the pending tree.
Does not include any PrepareTiles or raster time.
-
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
</summary>
</histogram>
@@ -82839,6 +86768,12 @@ uploading your change for review.
<summary>
How long it takes for the compositor to simply activate the pending tree.
Does not include any PrepareTiles or raster time.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -82848,9 +86783,11 @@ uploading your change for review.
The time from v-sync to when the main side actually starts the
BeginImplFrame.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -82872,20 +86809,6 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Scheduling.BeginMainFrameIntervalCritical2"
- units="microseconds">
- <owner>brianderson@chromium.org</owner>
- <summary>
- This is the time delta between back-to-back BeginMainFrames completions on
- the compositor side when the on_critical_path flag is set, regardless of
- whether they abort (have no updates) or commit (have updates).
-
- The interval is only recorded when the BeginMainFrames are running
- continuously; sepcifically when another BeginMainFrame is requested by the
- next BeginImplFrame after a) an abort or b) activation.
- </summary>
-</histogram>
-
<histogram name="Scheduling.BeginMainFrameIntervalNotCritical"
units="microseconds">
<obsolete>
@@ -82904,20 +86827,6 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Scheduling.BeginMainFrameIntervalNotCritical2"
- units="microseconds">
- <owner>brianderson@chromium.org</owner>
- <summary>
- This is the time delta between back-to-back BeginMainFrames completions on
- the compositor side when the on_critical_path flag is not set, regardless of
- whether they abort (have no updates) or commit (have updates).
-
- The interval is only recorded when the BeginMainFrames are running
- continuously; sepcifically when another BeginMainFrame is requested by the
- next BeginImplFrame after a) an abort or b) activation.
- </summary>
-</histogram>
-
<histogram name="Scheduling.BeginMainFrameQueueDurationCritical"
units="microseconds">
<obsolete>
@@ -82929,10 +86838,6 @@ uploading your change for review.
How long it takes for the main side to start the BeginMainFrame in response
to the compositor's SendBeginMainFrame when the on_critical_path flag is
set.
-
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
</summary>
</histogram>
@@ -82943,6 +86848,12 @@ uploading your change for review.
How long it takes for the main side to start the BeginMainFrame in response
to the compositor's SendBeginMainFrame when the on_critical_path flag is
set.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -82957,20 +86868,6 @@ uploading your change for review.
How long it takes for the main side to start the BeginMainFrame in response
to the compositor's SendBeginMainFrame when the on_critical_path flag is not
set.
-
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
- </summary>
-</histogram>
-
-<histogram name="Scheduling.BeginMainFrameQueueDurationNotCritical2"
- units="microseconds">
- <owner>brianderson@chromium.org</owner>
- <summary>
- How long it takes for the main side to start the BeginMainFrame in response
- to the compositor's SendBeginMainFrame when the on_critical_path flag is not
- set.
</summary>
</histogram>
@@ -82984,10 +86881,6 @@ uploading your change for review.
<summary>
The time from when the main side actually starts the BeginMainFrame to when
the commit completes on the impl side.
-
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
</summary>
</histogram>
@@ -82997,6 +86890,12 @@ uploading your change for review.
<summary>
The time from when the main side actually starts the BeginMainFrame to when
the commit completes on the impl side.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -83014,6 +86913,73 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Scheduling.Browser.BeginMainFrameIntervalCritical2"
+ units="microseconds">
+ <obsolete>
+ Deprecated in 06/2018, M69, due to too much noise in the collected data.
+ </obsolete>
+ <owner>brianderson@chromium.org</owner>
+ <summary>
+ This is the time delta between back-to-back BeginMainFrames completions on
+ the compositor side when the on_critical_path flag is set, regardless of
+ whether they abort (have no updates) or commit (have updates).
+
+ The interval is only recorded when the BeginMainFrames are running
+ continuously; sepcifically when another BeginMainFrame is requested by the
+ next BeginImplFrame after a) an abort or b) activation.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for
+ the solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Browser.BeginMainFrameIntervalNotCritical2"
+ units="microseconds">
+ <obsolete>
+ Deprecated in 07/2018, M69. All begin frames are in critical path for
+ browser, no data is reported.
+ </obsolete>
+ <owner>brianderson@chromium.org</owner>
+ <summary>
+ This is the time delta between back-to-back BeginMainFrames completions on
+ the compositor side when the on_critical_path flag is not set, regardless of
+ whether they abort (have no updates) or commit (have updates).
+
+ The interval is only recorded when the BeginMainFrames are running
+ continuously; sepcifically when another BeginMainFrame is requested by the
+ next BeginImplFrame after a) an abort or b) activation.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Browser.BeginMainFrameQueueDurationNotCritical2"
+ units="microseconds">
+ <obsolete>
+ Deprecated in 07/2018, M69. All begin frames are in critical path for
+ browser, no data is reported.
+ </obsolete>
+ <owner>brianderson@chromium.org</owner>
+ <summary>
+ How long it takes for the main side to start the BeginMainFrame in response
+ to the compositor's SendBeginMainFrame when the on_critical_path flag is not
+ set.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
<histogram name="Scheduling.Browser.BeginMainFrameStartToCommit"
units="microseconds">
<obsolete>
@@ -83040,9 +87006,9 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Scheduling.CommitInterval" units="microseconds">
+<histogram name="Scheduling.Browser.CommitInterval2" units="microseconds">
<obsolete>
- Replaced by CommitInterval2, due to inefficient bucketing scheme.
+ Deprecated in 06/2018, M69, due to too much noise in the collected data.
</obsolete>
<owner>brianderson@chromium.org</owner>
<summary>
@@ -83052,10 +87018,160 @@ uploading your change for review.
The interval is only recorded when the BeginMainFrames are running and
committing continuously, where continuously means when another
BeginMainFrame is requested by the next BeginImplFrame after activation.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for
+ the solution.
</summary>
</histogram>
-<histogram name="Scheduling.CommitInterval2" units="microseconds">
+<histogram name="Scheduling.Browser.DrawInterval2" units="microseconds">
+ <obsolete>
+ Deprecated in 06/2018, M69, due to too much noise in the collected data.
+ </obsolete>
+ <owner>brianderson@chromium.org</owner>
+ <summary>
+ The time delta between the draw times of back-to-back BeginImplFrames,
+ regardless of whether or not they result in a swap.
+
+ The interval is only recorded when every BeginImplFrame wants to draw.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for
+ the solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Browser.DrawIntervalWithCompositedAnimations2"
+ units="microseconds">
+ <obsolete>
+ Deprecated in 07/2018, M69, due to too much noise in the data.
+ </obsolete>
+ <owner>paint-dev@chromium.org</owner>
+ <summary>
+ The time delta between the draw times of back-to-back BeginImplFrames,
+ regardless of whether or not they result in a swap, when there is at least
+ one composited animation.
+
+ The interval is only recorded when every BeginImplFrame wants to draw.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Browser.DrawIntervalWithMainThreadAnimations2"
+ units="microseconds">
+ <obsolete>
+ Deprecated in 07/2018, M69, due to too much noise in the data.
+ </obsolete>
+ <owner>paint-dev@chromium.org</owner>
+ <summary>
+ The time delta between the draw times of back-to-back BeginImplFrames of new
+ active trees only, regardless of whether or not they result in a swap, when
+ there is at least one main thread animation.
+
+ The interval is only recorded when every BeginImplFrame wants to draw.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Browser.PendingTreeDuration" units="microseconds">
+ <obsolete>
+ Deprecated in 07/2018, M69. Since there is no pending tree in Browser, no
+ data is ever reported.
+ </obsolete>
+ <owner>ericrk@chromium.org</owner>
+ <summary>
+ Time between creating a pending tree and activating that tree. This differs
+ from Scheduling.ActivateDuration in that it includes time taken to raster
+ the pending tree, not just the time to activate it.
+
+ The interval is recorded each time a pending tree is activated.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Browser.PendingTreeRasterDuration"
+ units="microseconds">
+ <obsolete>
+ Deprecated in 07/2018, M69. Since there is no pending tree in Browser, no
+ data is ever reported.
+ </obsolete>
+ <owner>khushalsagar@chromium.org</owner>
+ <summary>
+ Time between starting raster work on the pending tree and when it is ready
+ to activate. Unlike PendingTreeDuration which - includes the time to commit
+ to this tree, the raster duration and the time for which the pending tree
+ waits before it can be activated - this only measures the time taken to
+ rasterize tiles required for activation.
+
+ The interval is recorded each time we are notifed that a pending tree is
+ ready for activation.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Browser.ReadyToActivateToActivationDuration2.Impl"
+ units="microseconds">
+ <obsolete>
+ Deprecated in 07/2018, M69. No data reported because there is no pending
+ tree on impl thread for browser side.
+ </obsolete>
+ <owner>brianderson@chromium.org</owner>
+ <summary>
+ How long does the pending tree wait after it is ready to be activated and
+ before it is activated.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution. Impl side invalidation initiated pending tree
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Browser.ReadyToActivateToActivationDuration2.Main"
+ units="microseconds">
+ <owner>brianderson@chromium.org</owner>
+ <summary>
+ How long does the pending tree wait after it is ready to be activated and
+ before it is activated.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution. Commit initiated pending tree.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.CommitInterval" units="microseconds">
+ <obsolete>
+ Replaced by CommitInterval2, due to inefficient bucketing scheme.
+ </obsolete>
<owner>brianderson@chromium.org</owner>
<summary>
The time delta between the *draw* times of back-to-back BeginMainFrames that
@@ -83077,10 +87193,6 @@ uploading your change for review.
<summary>
How long it takes for the compositor to rasterize pending tree content after
a commit before it is ready for activation.
-
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
</summary>
</histogram>
@@ -83090,6 +87202,12 @@ uploading your change for review.
<summary>
How long it takes for the compositor to rasterize pending tree content after
a commit before it is ready for activation.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -83103,7 +87221,15 @@ uploading your change for review.
<histogram name="Scheduling.DrawDuration2" units="microseconds">
<owner>brianderson@chromium.org</owner>
- <summary>How long it takes the compositor to draw a frame.</summary>
+ <summary>
+ How long it takes the compositor to draw a frame.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="Scheduling.DrawInterval" units="microseconds">
@@ -83119,40 +87245,6 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Scheduling.DrawInterval2" units="microseconds">
- <owner>brianderson@chromium.org</owner>
- <summary>
- The time delta between the draw times of back-to-back BeginImplFrames,
- regardless of whether or not they result in a swap.
-
- The interval is only recorded when every BeginImplFrame wants to draw.
- </summary>
-</histogram>
-
-<histogram name="Scheduling.DrawIntervalWithCompositedAnimations2"
- units="microseconds">
- <owner>paint-dev@chromium.org</owner>
- <summary>
- The time delta between the draw times of back-to-back BeginImplFrames,
- regardless of whether or not they result in a swap, when there is at least
- one composited animation.
-
- The interval is only recorded when every BeginImplFrame wants to draw.
- </summary>
-</histogram>
-
-<histogram name="Scheduling.DrawIntervalWithMainThreadAnimations2"
- units="microseconds">
- <owner>paint-dev@chromium.org</owner>
- <summary>
- The time delta between the draw times of back-to-back BeginImplFrames of new
- active trees only, regardless of whether or not they result in a swap, when
- there is at least one main thread animation.
-
- The interval is only recorded when every BeginImplFrame wants to draw.
- </summary>
-</histogram>
-
<histogram name="Scheduling.DrawIntervalWithMainThreadCompositableAnimations2"
units="microseconds">
<obsolete>
@@ -83191,9 +87283,11 @@ uploading your change for review.
How long it takes for the compositor to rasterize pending tree content after
an impl-side invalidation before it is ready for activation.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -83209,10 +87303,6 @@ uploading your change for review.
main-side updates are compared to the impl-side updates. If there are no
mid-frame updates, this metric is a good proxy for how well the main and
impl threads are synchronized.
-
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
</summary>
</histogram>
@@ -83225,10 +87315,186 @@ uploading your change for review.
main-side updates are compared to the impl-side updates. If there are no
mid-frame updates, this metric is a good proxy for how well the main and
impl threads are synchronized.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.PrepareTilesDuration" units="microseconds">
+ <obsolete>
+ Replaced by PrepareTIlesDuration2, due to inefficient bucketing scheme.
+ </obsolete>
+ <owner>brianderson@chromium.org</owner>
+ <summary>
+ How long it takes the compositor to PreapreTiles, which determines what
+ rasterization work to do.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.PrepareTilesDuration2" units="microseconds">
+ <owner>brianderson@chromium.org</owner>
+ <summary>
+ How long it takes the compositor to PreapreTiles, which determines what
+ rasterization work to do.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.ReadyToActivateToActivationDuration"
+ units="microseconds">
+ <obsolete>
+ Replaced by ReadyToActivateToActivationDuration2, due to inefficient
+ bucketing scheme.
+ </obsolete>
+ <owner>brianderson@chromium.org</owner>
+ <summary>
+ How long does the pending tree wait after it is ready to be activated and
+ before it is activated.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Renderer.BeginMainFrameIntervalCritical2"
+ units="microseconds">
+ <owner>brianderson@chromium.org</owner>
+ <summary>
+ This is the time delta between back-to-back BeginMainFrames completions on
+ the compositor side when the on_critical_path flag is set, regardless of
+ whether they abort (have no updates) or commit (have updates).
+
+ The interval is only recorded when the BeginMainFrames are running
+ continuously; sepcifically when another BeginMainFrame is requested by the
+ next BeginImplFrame after a) an abort or b) activation.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for
+ the solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Renderer.BeginMainFrameIntervalNotCritical2"
+ units="microseconds">
+ <owner>brianderson@chromium.org</owner>
+ <summary>
+ This is the time delta between back-to-back BeginMainFrames completions on
+ the compositor side when the on_critical_path flag is not set, regardless of
+ whether they abort (have no updates) or commit (have updates).
+
+ The interval is only recorded when the BeginMainFrames are running
+ continuously; sepcifically when another BeginMainFrame is requested by the
+ next BeginImplFrame after a) an abort or b) activation.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Renderer.BeginMainFrameQueueDurationNotCritical2"
+ units="microseconds">
+ <owner>brianderson@chromium.org</owner>
+ <summary>
+ How long it takes for the main side to start the BeginMainFrame in response
+ to the compositor's SendBeginMainFrame when the on_critical_path flag is not
+ set.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Renderer.CommitInterval2" units="microseconds">
+ <owner>brianderson@chromium.org</owner>
+ <summary>
+ The time delta between the *draw* times of back-to-back BeginMainFrames that
+ result in a commit.
+
+ The interval is only recorded when the BeginMainFrames are running and
+ committing continuously, where continuously means when another
+ BeginMainFrame is requested by the next BeginImplFrame after activation.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for
+ the solution.
</summary>
</histogram>
-<histogram name="Scheduling.PendingTreeDuration" units="microseconds">
+<histogram name="Scheduling.Renderer.DrawInterval2" units="microseconds">
+ <owner>brianderson@chromium.org</owner>
+ <summary>
+ The time delta between the draw times of back-to-back BeginImplFrames,
+ regardless of whether or not they result in a swap.
+
+ The interval is only recorded when every BeginImplFrame wants to draw.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for
+ the solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Renderer.DrawIntervalWithCompositedAnimations2"
+ units="microseconds">
+ <owner>paint-dev@chromium.org</owner>
+ <summary>
+ The time delta between the draw times of back-to-back BeginImplFrames,
+ regardless of whether or not they result in a swap, when there is at least
+ one composited animation.
+
+ The interval is only recorded when every BeginImplFrame wants to draw.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Renderer.DrawIntervalWithMainThreadAnimations2"
+ units="microseconds">
+ <owner>paint-dev@chromium.org</owner>
+ <summary>
+ The time delta between the draw times of back-to-back BeginImplFrames of new
+ active trees only, regardless of whether or not they result in a swap, when
+ there is at least one main thread animation.
+
+ The interval is only recorded when every BeginImplFrame wants to draw.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
+<histogram name="Scheduling.Renderer.PendingTreeDuration" units="microseconds">
<owner>ericrk@chromium.org</owner>
<summary>
Time between creating a pending tree and activating that tree. This differs
@@ -83236,10 +87502,17 @@ uploading your change for review.
the pending tree, not just the time to activate it.
The interval is recorded each time a pending tree is activated.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
-<histogram name="Scheduling.PendingTreeRasterDuration" units="microseconds">
+<histogram name="Scheduling.Renderer.PendingTreeRasterDuration"
+ units="microseconds">
<owner>khushalsagar@chromium.org</owner>
<summary>
Time between starting raster work on the pending tree and when it is ready
@@ -83250,46 +87523,35 @@ uploading your change for review.
The interval is recorded each time we are notifed that a pending tree is
ready for activation.
- </summary>
-</histogram>
-
-<histogram name="Scheduling.PrepareTilesDuration" units="microseconds">
- <obsolete>
- Replaced by PrepareTIlesDuration2, due to inefficient bucketing scheme.
- </obsolete>
- <owner>brianderson@chromium.org</owner>
- <summary>
- How long it takes the compositor to PreapreTiles, which determines what
- rasterization work to do.
-
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
- </summary>
-</histogram>
-<histogram name="Scheduling.PrepareTilesDuration2" units="microseconds">
- <owner>brianderson@chromium.org</owner>
- <summary>
- How long it takes the compositor to PreapreTiles, which determines what
- rasterization work to do.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
-<histogram name="Scheduling.ReadyToActivateToActivationDuration2"
+<histogram name="Scheduling.Renderer.ReadyToActivateToActivationDuration2"
units="microseconds">
<owner>brianderson@chromium.org</owner>
<summary>
How long does the pending tree wait after it is ready to be activated and
before it is activated.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
<histogram name="Scheduling.SwapAckWasFast" enum="BooleanWasFast">
+ <obsolete>
+ Deprecated in 07/2018, M69. The swap ack is always received within 8
+ seconds.
+ </obsolete>
<owner>brianderson@chromium.org</owner>
<summary>
True if the swap ack was received within approximately 8 seconds of the
@@ -83308,7 +87570,15 @@ uploading your change for review.
<histogram name="Scheduling.SwapToAckLatency2" units="microseconds">
<owner>brianderson@chromium.org</owner>
- <summary>How long it takes the swap ack to return after a swap.</summary>
+ <summary>
+ How long it takes the swap ack to return after a swap.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="ScreenLocker.AuthenticationFailure" enum="UnlockType">
@@ -85243,6 +89513,36 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Search.HistoryReport.DeltaFile.LastSeqNo" units="count"
+ expires_after="M71">
+ <owner>wychen@chromium.org</owner>
+ <owner>yusufo@chromium.org</owner>
+ <summary>
+ The last sequential number in the delta file for Icing. This is measured on
+ cold start.
+ </summary>
+</histogram>
+
+<histogram name="Search.HistoryReport.DeltaFile.LevelDBEntries" units="entries"
+ expires_after="2019-06-01">
+ <owner>wychen@chromium.org</owner>
+ <owner>yusufo@chromium.org</owner>
+ <summary>
+ The number of entries in the delta file level DB for Icing. This is measured
+ on cold start.
+ </summary>
+</histogram>
+
+<histogram name="Search.HistoryReport.UsageReportsBuffer.LevelDBEntries"
+ units="entries" expires_after="2019-06-01">
+ <owner>wychen@chromium.org</owner>
+ <owner>yusufo@chromium.org</owner>
+ <summary>
+ The number of entries in the usage report level DB for Icing. This is
+ measured on cold start.
+ </summary>
+</histogram>
+
<histogram name="Search.IcingContextReportingStatus"
enum="IcingContextReportingStatus">
<owner>joaodasilva@chromium.org</owner>
@@ -85512,6 +89812,30 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Security.PageInfo.TimeOpen">
+ <owner>cthomp@chromium.org</owner>
+ <summary>
+ Records the amount of time the Page Info bubble is open before the user
+ closes it or takes an action which closes it.
+ </summary>
+</histogram>
+
+<histogram name="Security.PageInfo.TimeOpen.Action">
+ <owner>cthomp@chromium.org</owner>
+ <summary>
+ Records the amount of time the Page Info bubble is open before the user
+ closes it, for cases where the user has performed an action inside it.
+ </summary>
+</histogram>
+
+<histogram name="Security.PageInfo.TimeOpen.NoAction">
+ <owner>cthomp@chromium.org</owner>
+ <summary>
+ Records the amount of time the Page Info bubble is open before the user
+ closes it, for cases where the user performed no action inside it.
+ </summary>
+</histogram>
+
<histogram name="Security.SecurityLevel.CryptographicScheme"
enum="SecurityLevel">
<owner>estark@chromium.org</owner>
@@ -85714,6 +90038,8 @@ uploading your change for review.
DevTools was attached during startup. This is intended to avoid including
the time for debugging. 3) The request is for New Tab Page. This is because
it tends to dominate the stats and makes the results largely skewed.
+
+ It will be removed after NetS13nSW ships. https://crbug.com/715640
</summary>
</histogram>
@@ -85725,6 +90051,9 @@ uploading your change for review.
active worker to dispatch a FetchEvent for a main frame resource request.
See details at ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time.
The suffixed histograms for .Time record the time required for each type.
+
+ This is recorded regardless of whether NetS13nSW (https://crbug.com/715640)
+ is enabled or disabled.
</summary>
</histogram>
@@ -85866,6 +90195,12 @@ uploading your change for review.
The result of ServiceWorkerContextRequestHandler handling a request for a
service worker script. The histogram is suffixed to distinguish new vs
installed workers and main vs imported scripts.
+
+ Note that since M64, this no longer includes most script loads because those
+ are handled by ServiceWorkerInstalledScriptsManager, which doesn't record
+ this histogram.
+
+ It will be removed after NetS13nSW ships. https://crbug.com/715640
</summary>
</histogram>
@@ -85925,9 +90260,16 @@ uploading your change for review.
<histogram name="ServiceWorker.DiskCache.WriteResponseResult"
enum="ServiceWorkerWriteResponseResult">
+ <owner>bashi@chromium.org</owner>
<owner>nhiroki@chromium.org</owner>
<summary>
- Records result of writing response into ServiceWorkerDiskCache.
+ Records result of writing response into ServiceWorkerDiskCache. This is not
+ recorded when response has no body. Note that this is recorded on every
+ write operation, and can there can be multiple write operations for the same
+ response if it is large enough.
+
+ This is recorded regardless of whether NetS13nSW (https://crbug.com/715640)
+ is enabled or disabled.
</summary>
</histogram>
@@ -85983,11 +90325,19 @@ uploading your change for review.
<summary>
The time taken between sending an event IPC from the browser process to a
Service Worker and executing the event handler in the Service Worker.
+
+ For subresource fetch events (_FETCH_SUB_RESOURCE suffix) When NetS13nSW
+ (https://crbug.com/715640) is enabled, this is the time between sending a
+ DispatchFetchEvent message from the main thread and executing the event
+ handler in the Service Worker.
</summary>
</histogram>
<histogram name="ServiceWorker.EventHandledRatioType.Fetch"
enum="ServiceWorkerEventHandleRatioType">
+ <obsolete>
+ Removed July 2018 (M69)
+ </obsolete>
<owner>kinuko@chromium.org</owner>
<summary>
Records the proportion of (non foreign) fetch events that are handled
@@ -85999,6 +90349,9 @@ uploading your change for review.
<histogram name="ServiceWorker.EventHandledRatioType.ForeignFetch"
enum="ServiceWorkerEventHandleRatioType">
+ <obsolete>
+ Removed July 2018 (M69)
+ </obsolete>
<owner>mek@chromium.org</owner>
<summary>
Records the proportion of foreign fetch events that are handled compared to
@@ -86047,7 +90400,10 @@ uploading your change for review.
<owner>falken@chromium.org</owner>
<summary>
The result of dispatching a fetch event to a Service Worker for a main
- resource request.
+ resource request (i.e., a request for a navigation or a shared worker).
+
+ This is recorded regardless of whether NetS13nSW (https://crbug.com/715640)
+ is enabled or disabled.
</summary>
</histogram>
@@ -86056,7 +90412,10 @@ uploading your change for review.
<owner>falken@chromium.org</owner>
<summary>
The result of dispatching a fetch event to a Service Worker for a
- subresource request.
+ subresource request (i.e., not a navigation or a shared worker request).
+
+ This is recorded regardless of whether NetS13nSW (https://crbug.com/715640)
+ is enabled or disabled.
</summary>
</histogram>
@@ -86352,6 +90711,8 @@ uploading your change for review.
the same restrictions enumerated 1) through 3) for
ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time. The sample is
only recorded to the appropriate suffixed histograms.
+
+ It will be removed after NetS13nSW ships. https://crbug.com/715640
</summary>
</histogram>
@@ -86365,6 +90726,8 @@ uploading your change for review.
fetch event, with the same restrictions numbered 1) through 3) for
ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time. The sample is
only recorded to the appropriate suffixed histograms.
+
+ It will be removed after NetS13nSW ships. https://crbug.com/715640
</summary>
</histogram>
@@ -86377,6 +90740,8 @@ uploading your change for review.
event, with the same restrictions numbered 1) through 3) for
ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time. The sample is
only recorded to the appropriate suffixed histograms.
+
+ It will be removed after NetS13nSW ships. https://crbug.com/715640
</summary>
</histogram>
@@ -86401,6 +90766,8 @@ uploading your change for review.
other ServiceWorker.NavPreload.* metrics so is more safely comparable to
them. We could deprecate the Type_NavigationPreloadEnabled histogram if it
turns out there is no significant difference.
+
+ It will be removed after NetS13nSW ships. https://crbug.com/715640
</summary>
</histogram>
@@ -86532,6 +90899,13 @@ uploading your change for review.
</histogram>
<histogram name="ServiceWorker.ScriptLoadSuccess" enum="BooleanSuccess">
+ <obsolete>
+ Removed June 2018 (M69). This was recorded as 100% success since service
+ worker script streaming launched in M64, since load failures didn't reach
+ this UMA. When there is an error reading the script from storage, it's
+ typically recorded as a start worker failure under
+ SERVICE_WORKER_ERROR_DISK_CACHE.
+ </obsolete>
<owner>falken@chromium.org</owner>
<summary>
Whether loading the service worker script succeeded. Only recorded for
@@ -86607,6 +90981,129 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="ServiceWorker.StartTiming.ClockConsistency"
+ enum="CrossProcessTimeDelta" expires_after="2019-07-30">
+ <owner>falken@chromium.org</owner>
+ <owner>shimazu@chromium.org</owner>
+ <summary>
+ Recorded on each successful service worker startup.
+ ServiceWorker.StartTiming.* uses timing data from both the renderer process
+ and browser process. This histogram describes whether the clocks are known
+ to be accurate and consistent accross processes, and whether the actual
+ timing data for this worker startup was consistent, i.e., TimeTicks did not
+ go backwards.
+
+ If the clocks and timing were inconsistent, ServiceWorker.StartTiming.*
+ metrics (other than this one) are not recorded.
+ </summary>
+</histogram>
+
+<histogram name="ServiceWorker.StartTiming.Duration" units="ms"
+ expires_after="2021-07-30">
+ <owner>falken@chromium.org</owner>
+ <owner>shimazu@chromium.org</owner>
+ <summary>
+ The time taken to start a service worker that is already installed, from
+ start of the start sequence (finding a renderer) to ACK of started from the
+ renderer (which occurs after script execution). The metric is not recorded
+ if DevTools was ever attached to the Service Worker during startup. It does
+ not include time, if any, waiting for the service worker to finish stopping
+ before asking it to start, if that occurred.
+ </summary>
+</histogram>
+
+<histogram
+ name="ServiceWorker.StartTiming.ReceivedStartWorkerToScriptEvaluationStart"
+ units="ms" expires_after="2021-07-30">
+ <owner>falken@chromium.org</owner>
+ <owner>shimazu@chromium.org</owner>
+ <summary>
+ The time taken from (a) the renderer receiving the start worker IPC message,
+ to (b) initial JavaScript evaluation starting on the worker thread. Recorded
+ when ServiceWorker.StartTiming.Duration is recorded.
+ </summary>
+</histogram>
+
+<histogram name="ServiceWorker.StartTiming.ScriptEvaluationEndToEnd" units="ms"
+ expires_after="2021-07-30">
+ <owner>falken@chromium.org</owner>
+ <owner>shimazu@chromium.org</owner>
+ <summary>
+ The time taken from (a) initial JavaScript evaluation finishing on the
+ worker thread, to (b) the browser receiving the worker started IPC message
+ (the final step of worker startup). Recorded when
+ ServiceWorker.StartTiming.Duration is recorded.
+ </summary>
+</histogram>
+
+<histogram
+ name="ServiceWorker.StartTiming.ScriptEvaluationStartToScriptEvaluationEnd"
+ units="ms" expires_after="2021-07-30">
+ <owner>falken@chromium.org</owner>
+ <owner>shimazu@chromium.org</owner>
+ <summary>
+ The time taken from (a) initial JavaScript evaluation starting on the worker
+ thread, to (b) initial JavaScript evaluation finishing on the worker thread.
+ Recorded when ServiceWorker.StartTiming.Duration is recorded.
+ </summary>
+</histogram>
+
+<histogram
+ name="ServiceWorker.StartTiming.SentStartWorkerToReceivedStartWorker"
+ units="ms" expires_after="2021-07-30">
+ <owner>falken@chromium.org</owner>
+ <owner>shimazu@chromium.org</owner>
+ <summary>
+ The time taken from (a) the browser sending the start worker IPC message, to
+ (b) the renderer receiving the start worker IPC message. Recorded when
+ ServiceWorker.StartTiming.Duration is recorded.
+ </summary>
+</histogram>
+
+<histogram name="ServiceWorker.StartTiming.StartToReceivedStartWorker"
+ units="ms" expires_after="2021-07-30">
+ <owner>falken@chromium.org</owner>
+ <owner>shimazu@chromium.org</owner>
+ <summary>
+ The time taken from (a) the start of service worker startup, to (b) the
+ renderer receiving the start worker IPC message. Recorded when
+ ServiceWorker.StartTiming.Duration is recorded.
+ </summary>
+</histogram>
+
+<histogram name="ServiceWorker.StartTiming.StartToScriptEvaluationEnd"
+ units="ms" expires_after="2021-07-30">
+ <owner>falken@chromium.org</owner>
+ <owner>shimazu@chromium.org</owner>
+ <summary>
+ The time taken from (a) the start of service worker startup, to (b) initial
+ JavaScript evaluation finishing on the worker thread. Recorded when
+ ServiceWorker.StartTiming.Duration is recorded.
+ </summary>
+</histogram>
+
+<histogram name="ServiceWorker.StartTiming.StartToScriptEvaluationStart"
+ units="ms" expires_after="2021-07-30">
+ <owner>falken@chromium.org</owner>
+ <owner>shimazu@chromium.org</owner>
+ <summary>
+ The time taken from (a) the start of service worker startup, to (b) initial
+ JavaScript evaluation starting on the worker thread. Recorded when
+ ServiceWorker.StartTiming.Duration is recorded.
+ </summary>
+</histogram>
+
+<histogram name="ServiceWorker.StartTiming.StartToSentStartWorker" units="ms"
+ expires_after="2021-07-30">
+ <owner>falken@chromium.org</owner>
+ <owner>shimazu@chromium.org</owner>
+ <summary>
+ The time taken from (a) the start of service worker startup, to (b) the
+ browser sending the start worker IPC message. Recorded when
+ ServiceWorker.StartTiming.Duration is recorded.
+ </summary>
+</histogram>
+
<histogram name="ServiceWorker.StartWorker.AfterFailureStreak"
enum="ServiceWorkerStatusCode">
<owner>falken@chromium.org</owner>
@@ -86979,8 +91476,6 @@ uploading your change for review.
</histogram>
<histogram name="Session.TotalDuration" units="ms">
- <owner>mariakhomenko@chromium.org</owner>
- <owner>fqian@chromium.org</owner>
<owner>asvitkine@chromium.org</owner>
<owner>chrisha@chromium.org</owner>
<summary>
@@ -86989,7 +91484,8 @@ uploading your change for review.
Desktop: This also takes into account user interaction and audio events.
Starting from M55 the session length is recorded by discounting for default
- inactivity timeout.
+ inactivity timeout. Also, until M69, there was a bug that caused
+ double-counting of some sessions.
Android: There is a known issue where JavaScript dialogs and other things
that take focus away from the Chrome activity can cause this metric to
@@ -87153,6 +91649,23 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Session.TotalDurationMax1Day" units="ms">
+ <owner>asvitkine@chromium.org</owner>
+ <owner>chrisha@chromium.org</owner>
+ <summary>
+ The length of a session (launch/foregrounding to backgrounding) in
+ milliseconds.
+
+ Desktop: This also takes into account user interaction and audio events.
+ Starting from M55 the session length is recorded by discounting for default
+ inactivity timeout. Also, until M69, there was a bug that caused
+ double-counting of some sessions.
+
+ Android: This histogram isn't logged on Android. See instead
+ Session.TotalDuration.
+ </summary>
+</histogram>
+
<histogram name="SessionCrashed.Bubble" enum="SessionCrashedBubbleUserAction">
<owner>yiyaoliu@chromium.org</owner>
<summary>How did the user interact with the SessionCrashed Bubble?</summary>
@@ -87639,14 +92152,16 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Settings.FilterOnLoadTime" units="ms">
+<histogram name="Settings.FilterOnLoadTime" units="ms"
+ expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
The amount of time it took to run PrefHashFilter::FilterOnLoad on startup.
</summary>
</histogram>
-<histogram name="Settings.FilterSerializeDataTime" units="ms">
+<histogram name="Settings.FilterSerializeDataTime" units="ms"
+ expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
The amount of time it took to run PrefHashFilter::FilterSerializeData on the
@@ -87707,7 +92222,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Settings.HomePageIsNewTabPage.PulledFromSync" enum="Boolean">
+<histogram name="Settings.HomePageIsNewTabPage.PulledFromSync" enum="Boolean"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The value of the home-page-is-new-tab-page pref when pulled down from sync
@@ -87715,7 +92231,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Settings.HomePageIsNewTabPage.PushedToSync" enum="Boolean">
+<histogram name="Settings.HomePageIsNewTabPage.PushedToSync" enum="Boolean"
+ expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The value of the home-page-is-new-tab-page pref when pushed up to sync from
@@ -87826,7 +92343,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Settings.PinnedTabEngineTypes" enum="OmniboxSearchEngineType">
+<histogram name="Settings.PinnedTabEngineTypes" enum="OmniboxSearchEngineType"
+ expires_after="2018-08-30">
<owner>mpearson@chromium.org</owner>
<summary>
Tries to pretend pinned tab URLs are search URLs, and records the search
@@ -87912,7 +92430,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Settings.ShowHomeButton.PulledFromSync" enum="BooleanEnabled">
+<histogram name="Settings.ShowHomeButton.PulledFromSync" enum="BooleanEnabled"
+ expires_after="2018-08-30">
<owner>mpearson@chromium.org</owner>
<summary>
The enabled state of the Home button pref when pulled down from sync to
@@ -87920,7 +92439,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Settings.ShowHomeButton.PushedToSync" enum="BooleanEnabled">
+<histogram name="Settings.ShowHomeButton.PushedToSync" enum="BooleanEnabled"
+ expires_after="2018-08-30">
<owner>mpearson@chromium.org</owner>
<summary>
The enabled state of the Home button pref when pushed up to sync from a
@@ -87966,7 +92486,7 @@ uploading your change for review.
</histogram>
<histogram name="Settings.StartupPageEngineTypes"
- enum="OmniboxSearchEngineType">
+ enum="OmniboxSearchEngineType" expires_after="2018-08-30">
<owner>mpearson@chromium.org</owner>
<summary>
Tries to pretend the startup page URLs are search URLs, and records the
@@ -87983,7 +92503,7 @@ uploading your change for review.
</histogram>
<histogram name="Settings.StartupPageLoadSettings.PulledFromSync"
- enum="SessionStartupPref">
+ enum="SessionStartupPref" expires_after="2018-08-30">
<owner>mpearson@chromium.org</owner>
<summary>
The startup page setting when pulled down from sync to update an out-of-sync
@@ -87992,7 +92512,7 @@ uploading your change for review.
</histogram>
<histogram name="Settings.StartupPageLoadSettings.PushedToSync"
- enum="SessionStartupPref">
+ enum="SessionStartupPref" expires_after="2018-08-30">
<owner>mpearson@chromium.org</owner>
<summary>
The startup page setting when pushed up to sync from a change made locally.
@@ -88154,7 +92674,7 @@ uploading your change for review.
</histogram>
<histogram name="Settings.TrackedPreferencesNoEnforcementOnDomain"
- enum="BooleanEnabled">
+ enum="BooleanEnabled" expires_after="2018-08-30">
<owner>gab@chromium.org</owner>
<summary>
Whether settings enforcement was cancelled for a machine joined to a domain.
@@ -88539,7 +93059,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="SharedMemory.CreateError" enum="SharedMemoryCreateError">
+<histogram name="SharedMemory.CreateError" enum="SharedMemoryCreateError"
+ expires_after="2018-08-30">
<owner>erikchen@chromium.org</owner>
<summary>
A histogram entry is emitted each time a base::SharedMemory object is
@@ -88604,7 +93125,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="ShortcutsProvider.DatabaseSize">
+<histogram name="ShortcutsProvider.DatabaseSize" expires_after="2018-08-30">
<owner>mpearson@chromium.org</owner>
<summary>
The number of entries in shortcuts backend's database when initialized,
@@ -89515,6 +94036,9 @@ uploading your change for review.
<histogram base="true" name="SimpleCache.HeaderSizeChange"
enum="SimpleCacheHeaderSizeChange">
+ <obsolete>
+ Removed 2018-06-05
+ </obsolete>
<owner>morlovich@chromium.org</owner>
<summary>
How the header size has changed in a Simple Cache entry, emitted every time
@@ -89525,6 +94049,9 @@ uploading your change for review.
<histogram base="true" name="SimpleCache.HeaderSizeDecreaseAbsolute"
units="bytes">
+ <obsolete>
+ Removed 2018-06-05
+ </obsolete>
<owner>morlovich@chromium.org</owner>
<summary>
The absolute size decrease of the header stream of a Simple Cache entry,
@@ -89534,6 +94061,9 @@ uploading your change for review.
<histogram base="true" name="SimpleCache.HeaderSizeDecreasePercentage"
units="%">
+ <obsolete>
+ Removed 2018-06-05
+ </obsolete>
<owner>morlovich@chromium.org</owner>
<summary>
The relative size decrease of the header stream of a Simple Cache entry,
@@ -89543,6 +94073,9 @@ uploading your change for review.
<histogram base="true" name="SimpleCache.HeaderSizeIncreaseAbsolute"
units="bytes">
+ <obsolete>
+ Removed 2018-06-05
+ </obsolete>
<owner>morlovich@chromium.org</owner>
<summary>
The absolute size increase of the header stream of a Simple Cache entry,
@@ -89552,6 +94085,9 @@ uploading your change for review.
<histogram base="true" name="SimpleCache.HeaderSizeIncreasePercentage"
units="%">
+ <obsolete>
+ Removed 2018-06-05
+ </obsolete>
<owner>morlovich@chromium.org</owner>
<summary>
The relative size increase of the header stream of a Simple Cache entry,
@@ -89804,6 +94340,9 @@ uploading your change for review.
<histogram base="true" name="SimpleCache.ReadIsParallelizable"
enum="SimpleCacheReadParallelizable">
+ <obsolete>
+ Removed 2018-07-02. See https://crrev.com/c/1122706
+ </obsolete>
<owner>morlovich@chromium.org</owner>
<summary>
For each Read operation, whether it could have been issued in parallel of a
@@ -89953,6 +94492,9 @@ uploading your change for review.
<histogram base="true" name="SimpleCache.WriteDependencyType"
enum="SimpleCacheWriteDependencyType">
+ <obsolete>
+ Removed 2018-07-02. See https://crrev.com/c/1122706
+ </obsolete>
<owner>morlovich@chromium.org</owner>
<summary>
Shows whether a write operation depends on the previous operation in queue
@@ -90406,6 +94948,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="SiteIsolation.LowMemoryMode.Transition" enum="BooleanEnabled">
+ <owner>rsesek@chromium.org</owner>
+ <summary>
+ The number of times a render process transitions its main thread isolate
+ into or out of memory savings mode. This is recorded per-renderer-process
+ upon the creation of the first main frame or the destruction of the last
+ main frame.
+ </summary>
+</histogram>
+
<histogram name="SiteIsolation.OutOfProcessIframes">
<owner>nasko@chromium.org</owner>
<summary>
@@ -92117,7 +96669,7 @@ uploading your change for review.
<histogram name="Stability.Android.ProcessedCrashCounts"
enum="AndroidProcessedCrashCounts">
- <owner>mariakhomenko@chromium.org</owner>
+ <owner>boliu@chromium.org</owner>
<summary>
Individual enum counts specific conditions of child process terminations.
There are too many individual states to enumerate into a single histogram,
@@ -92137,6 +96689,18 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Stability.Android.StrongBindingOomRemainingBindingState"
+ enum="Android.ChildProcessBindingStateCombination">
+ <owner>boliu@chromium.org</owner>
+ <owner>ssid@chromium.org</owner>
+ <summary>
+ Record the state of child service bindings left when a child service with
+ strong binding is OOM killed by Android. Recorded when such a OOM kill is
+ detected by browser. Note this does not distinguish process type, and is for
+ example recorded for both GPU and renderer process.
+ </summary>
+</histogram>
+
<histogram name="Stability.BadMessageTerminated.Chrome"
enum="BadMessageReasonChrome">
<owner>nick@chromium.org</owner>
@@ -93101,7 +97665,8 @@ uploading your change for review.
<summary>The calling application (if any).</summary>
</histogram>
-<histogram name="Startup.OSX.AwakeFromNib" units="ms">
+<histogram name="Startup.OSX.AwakeFromNib" units="ms"
+ expires_after="2018-08-30">
<owner>erikchen@chromium.org</owner>
<summary>
The amount of time that elapsed between main entry and the invocation of
@@ -93134,7 +97699,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Startup.OSX.PreMainMessageLoopStart" units="ms">
+<histogram name="Startup.OSX.PreMainMessageLoopStart" units="ms"
+ expires_after="2018-08-30">
<owner>erikchen@chromium.org</owner>
<summary>
The amount of time that elapsed between main entry and the invocation of
@@ -93142,7 +97708,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Startup.OSX.PreProfileInit" units="ms">
+<histogram name="Startup.OSX.PreProfileInit" units="ms"
+ expires_after="2018-08-30">
<owner>erikchen@chromium.org</owner>
<summary>
The amount of time that elapsed between main entry and the invocation of
@@ -93150,7 +97717,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Startup.OSX.WillFinishLaunching" units="ms">
+<histogram name="Startup.OSX.WillFinishLaunching" units="ms"
+ expires_after="2018-08-30">
<owner>erikchen@chromium.org</owner>
<summary>
The amount of time that elapsed between main entry and the invocation of
@@ -93485,6 +98053,19 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Storage.Blob.FileReaderLoader.FailureType"
+ enum="FileReaderLoaderFailureType">
+ <owner>dmurph@chromium.org</owner>
+ <summary>
+ Recorded when an error occurs in the FileReaderLoader, which is used to load
+ blobs in the Renderer. FileReaderUser is mostly used for Javascript's
+ 'FileReader', but can also be used to read blobs for the IndexedDB
+ renderer-side implementation. For the read error category, see
+ Storage.Blob.FileReaderLoader.ReadError for a breakdown of the specific read
+ error reasons.
+ </summary>
+</histogram>
+
<histogram name="Storage.Blob.FileReaderLoader.ReadError" enum="NetErrorCodes">
<owner>dmurph@chromium.org</owner>
<summary>
@@ -93787,9 +98368,11 @@ uploading your change for review.
<summary>
Microseconds spent in StyleSheetContents::parseAuthorStyleSheet.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -93822,10 +98405,21 @@ uploading your change for review.
<histogram name="Style.UpdateTime" units="microseconds">
<owner>csharrison@chromium.org</owner>
- <summary>Microseconds spent in Document::updateStyle.</summary>
+ <summary>
+ Microseconds spent in Document::updateStyle.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="SubresourceFilter.Actions" enum="SubresourceFilterActions">
+ <obsolete>
+ Deprecated June 2018 in favor of SubresourceFilter.Actions2
+ </obsolete>
<owner>csharrison@chromium.org</owner>
<summary>
Counts of various UI and user action events related to the
@@ -93835,6 +98429,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="SubresourceFilter.Actions2" enum="SubresourceFilterActions2">
+ <owner>csharrison@chromium.org</owner>
+ <owner>jkarlin@chromium.org</owner>
+ <summary>
+ Counts of various UI and user action events related to the
+ SubresourceFilter. This will be triggered when portions of the UI are shown
+ or interacted with.
+ </summary>
+</histogram>
+
<histogram name="SubresourceFilter.AdDelay.Delay" units="ms">
<owner>csharrison@chromium.org</owner>
<owner>jkarlin@chromium.org</owner>
@@ -93865,6 +98469,9 @@ uploading your change for review.
</histogram>
<histogram name="SubresourceFilter.AdDelay.IsolatedInfo" enum="AdIsolatedInfo">
+ <obsolete>
+ Deprecated July 2018. Replaced with Ads.Features.AdResourceIsIsolated.
+ </obsolete>
<owner>csharrison@chromium.org</owner>
<owner>jkarlin@chromium.org</owner>
<summary>
@@ -93874,6 +98481,9 @@ uploading your change for review.
</histogram>
<histogram name="SubresourceFilter.AdDelay.SecureInfo" enum="AdSecureInfo">
+ <obsolete>
+ Deprecated July 2018. Replaced with Ads.Features.ResourceIsSecure.
+ </obsolete>
<owner>csharrison@chromium.org</owner>
<owner>jkarlin@chromium.org</owner>
<summary>
@@ -93889,8 +98499,11 @@ uploading your change for review.
Records how much thread CPU time it takes to decide whether subresource
filtering should be activated for a main frame or subframe.
- Note: this histogram is emitted for all clients, both ones which have
- high-resolution timer available and those which don't.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -93901,8 +98514,11 @@ uploading your change for review.
Records how long it takes to decide whether subresource filtering should be
activated for a main frame or subframe.
- Note: this histogram is emitted for all clients, both ones which have
- high-resolution timer available and those which don't.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -93913,9 +98529,11 @@ uploading your change for review.
Records the total time the activation state navigation throttle within a
document is delayed while calculating activation. Recorded at resume time.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -94001,9 +98619,11 @@ uploading your change for review.
whether it should be disallowed or not. Logged for all navigations that were
allowed.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -94101,28 +98721,43 @@ uploading your change for review.
</histogram>
<histogram name="SubresourceFilter.PageLoad.Activation.CPUDuration"
- units="microseconds">
+ units="microseconds" expires_after="2018-08-30">
<owner>csharrison@chromium.org</owner>
<summary>
Records how much thread CPU time it takes to decide whether subresource
filtering should be activated for a main frame.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
+</histogram>
+
+<histogram name="SubresourceFilter.PageLoad.Activation.RedirectPosition"
+ enum="SafeBrowsingActivationPosition">
+ <owner>ericrobinson@chromium.org</owner>
+ <summary>
+ For pages that trigger Safe Browsing activations (not including dry runs),
+ records the position in the redirect chain for the page the activation was
+ triggered by. If SubresourceFilterConsiderRedirects is disabled, then
+ always returns &quot;Only navigation&quot;.
</summary>
</histogram>
<histogram name="SubresourceFilter.PageLoad.Activation.WallDuration"
- units="microseconds">
+ units="microseconds" expires_after="2018-08-30">
<owner>csharrison@chromium.org</owner>
<summary>
Records how long it takes to decide whether subresource filtering should be
activated for a main frame.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -94185,6 +98820,10 @@ uploading your change for review.
<histogram name="SubresourceFilter.PageLoad.ForcedActivation.DisallowedLoad"
enum="Boolean">
+ <obsolete>
+ Deprecated May 2018 in favor of
+ SubresourceFilter.PageLoad.ActivationDecision
+ </obsolete>
<owner>csharrison@chromium.org</owner>
<summary>
Logged when the first resource is disallowed from a page with forced
@@ -94277,6 +98916,10 @@ uploading your change for review.
<histogram
name="SubresourceFilter.PageLoad.SafeBrowsingDelay.NoRedirectSpeculation"
units="ms">
+ <obsolete>
+ Deprecated in May 2018 (M69). We have enough data to show that the redirect
+ speculations we do are necessary, especially for Android.
+ </obsolete>
<owner>csharrison@chromium.org</owner>
<summary>
The navigation delay that would have been imposed by the subresource filter
@@ -94316,6 +98959,9 @@ uploading your change for review.
</histogram>
<histogram name="SubresourceFilter.Prompt.NumReloads" enum="BooleanRequested">
+ <obsolete>
+ Deprecated in favor of the whitelisted bucket in SubresourceFilter.Actions2
+ </obsolete>
<owner>melandory@chromium.org</owner>
<summary>
Number of times the user has requested a reload for the page by clicking on
@@ -94376,8 +99022,11 @@ uploading your change for review.
records the thread CPU time spent on calculating whether it should be
allowed to load.
- Note: this histogram is emitted for all clients, both ones which have
- high-resolution timer available and those which don't.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -94389,8 +99038,11 @@ uploading your change for review.
records how much time was spent on calculating whether it should be allowed
to load.
- Note: this histogram is emitted for all clients, both ones which have
- high-resolution timer available and those which don't.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -95973,6 +100625,38 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Sync.Preferences.ClearedLocalPrefOnTypeMismatch"
+ units="BooleanHit">
+ <owner>tschumann@chromium.org</owner>
+ <owner>treib@chromium.org</owner>
+ <summary>
+ Counts the number of times a syncable pref got registered using a type that
+ mismatched the type present in the pref store. In these events, the
+ persisted value gets removed from the pref store.
+ </summary>
+</histogram>
+
+<histogram name="Sync.Preferences.RemotePrefTypeMismatch" units="BooleanHit">
+ <owner>tschumann@chromium.org</owner>
+ <owner>treib@chromium.org</owner>
+ <summary>
+ Counts the number of times a client received a remote pref update with a
+ value type different from the registered pref type. The client will ignore
+ those remote updates.
+ </summary>
+</histogram>
+
+<histogram name="Sync.Preferences.SyncingUnknownPrefs" units="prefs">
+ <owner>tschumann@chromium.org</owner>
+ <owner>treib@chromium.org</owner>
+ <summary>
+ The number of unknown prefs being synced. This number is computed after the
+ sync model has been associated. Preferences which get handled by sync even
+ before being registered are considered &quot;unknown&quot;. This might be
+ limited to a whitelist of preferences.
+ </summary>
+</histogram>
+
<histogram name="Sync.PreferencesAssociationTime" units="ms">
<owner>zea@chromium.org</owner>
<summary>Time taken during preference association.</summary>
@@ -96232,7 +100916,10 @@ uploading your change for review.
</histogram>
<histogram name="Sync.SesssionsDuplicateSyncId" units="count">
- <owner>skym@chromium.org</owner>
+ <obsolete>
+ Deprecated in M69.
+ </obsolete>
+ <owner>mastiz@chromium.org</owner>
<summary>
https://crbug.com/639009, count of duplicate sync ids (tab node id) when any
are encountered. Likely caused from a persistence race between native tab
@@ -96679,7 +101366,7 @@ uploading your change for review.
</histogram>
<histogram name="SyncFileSystem.RegisterOriginResult"
- enum="SyncFSRemoteServiceState">
+ enum="SyncFSRemoteServiceState" expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>
The result of the registration of Chrome App to Sync FileSystem.
@@ -96695,7 +101382,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="SyncFileSystem.TrackerDB.Open" enum="LevelDBStatus">
+<histogram name="SyncFileSystem.TrackerDB.Open" enum="LevelDBStatus"
+ expires_after="2018-08-30">
<owner>tzik@chromium.org</owner>
<summary>The result of opening the Sync FileSystem tracker database.</summary>
</histogram>
@@ -96776,7 +101464,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Tab.Close.UnloadTime" units="ms">
+<histogram name="Tab.Close.UnloadTime" units="ms" expires_after="2018-08-30">
<summary>
Time in milliseconds from when JS OnUnload handlers have finished to
actually closing tab. Doesn't include time that's spent in JS OnUnload
@@ -97503,6 +102191,66 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="TabManager.Discarding.LocalDatabase.DatabaseInit"
+ enum="LocalSiteCharacteristicsDBInitStatus">
+ <obsolete>
+ Deprecated 07/2018, and replaced by
+ ResourceCoordinator.LocalDB.DatabaseInit.
+ </obsolete>
+ <owner>sebmarchand@chromium.org</owner>
+ <summary>
+ The result of opening the Local Site Characteristics database.
+ </summary>
+</histogram>
+
+<histogram name="TabManager.Discarding.LocalDatabase.DatabaseInitAfterDelete"
+ enum="LocalSiteCharacteristicsDBInitStatus">
+ <obsolete>
+ Deprecated 07/2018, and replaced by
+ ResourceCoordinator.LocalDB.DatabaseInitAfterDelete.
+ </obsolete>
+ <owner>sebmarchand@chromium.org</owner>
+ <summary>
+ The result of opening the Local Site Characteristics database after deleting
+ it after a failed repair attempt.
+ </summary>
+</histogram>
+
+<histogram name="TabManager.Discarding.LocalDatabase.DatabaseInitAfterRepair"
+ enum="LocalSiteCharacteristicsDBInitStatus">
+ <obsolete>
+ Deprecated 07/2018, and replaced by
+ ResourceCoordinator.LocalDB.DatabaseInitAfterRepair.
+ </obsolete>
+ <owner>sebmarchand@chromium.org</owner>
+ <summary>
+ The result of opening the Local Site Characteristics database after a repair
+ attempt.
+ </summary>
+</histogram>
+
+<histogram name="TabManager.Discarding.LocalDatabase.DatabaseRepair"
+ enum="BooleanSuccess">
+ <obsolete>
+ Deprecated 07/2018, and replaced by
+ ResourceCoordinator.LocalDB.DatabaseRepair.
+ </obsolete>
+ <owner>sebmarchand@chromium.org</owner>
+ <summary>
+ The result of trying to repair the Local Site Characteristics database after
+ a failed open.
+ </summary>
+</histogram>
+
+<histogram name="TabManager.Discarding.LogMemoryTime" units="ms">
+ <owner>cywang@chromium.org</owner>
+ <owner>georgesak@chromium.org</owner>
+ <summary>
+ Elapsed time to collect memory usage of each tab triggered by a LogMemory()
+ call().
+ </summary>
+</histogram>
+
<histogram name="TabManager.Discarding.ReloadCount" units="Reloads">
<owner>georgesak@chromium.org</owner>
<summary>
@@ -98404,7 +103152,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Tabs.ScrubDistance" units="tabs">
+<histogram name="Tabs.ScrubDistance" units="tabs" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The distance a user 3 finger scrubbed to change tabs. Always positive
@@ -98607,6 +103355,66 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Tabs.Tasks.AverageTabGroupSize" units="tabs">
+ <owner>yusufo@chromium.org</owner>
+ <owner>wychen@chromium.org</owner>
+ <summary>
+ The average tab group size, average number of tabs in a group, on a cold
+ start after all tabs are restored.
+ </summary>
+</histogram>
+
+<histogram name="Tabs.Tasks.HubAndSpokeNavigationUsage" units="spokes"
+ expires_after="2019-01-01">
+<!-- Name completed by histogram_suffixes name="HubAndSpokeNavigationUsageType" -->
+
+ <owner>yusufo@chromium.org</owner>
+ <owner>wychen@chromium.org</owner>
+ <summary>
+ The cumulative number of &quot;spokes&quot; from any &quot;hub&quot; page in
+ every tab. A &quot;hub&quot; is any page that the user navigates away from,
+ and a &quot;spoke&quot; is a page that's navigated to. The
+ &quot;spokes&quot; count is incremented and recorded each time the user
+ navigates back to a &quot;hub&quot; page via navigation back button and then
+ navigates to a new &quot;spoke&quot;.
+ </summary>
+</histogram>
+
+<histogram name="Tabs.Tasks.TabGroupCount" units="groups">
+ <owner>yusufo@chromium.org</owner>
+ <owner>wychen@chromium.org</owner>
+ <summary>
+ The number of tab groups on a cold start after all tabs are restored.
+ </summary>
+</histogram>
+
+<histogram name="Tabs.Tasks.TabGroupDensity" units="%">
+ <owner>yusufo@chromium.org</owner>
+ <owner>wychen@chromium.org</owner>
+ <summary>
+ The tab group density, the ratio of the number of tab groups to the total
+ number of tabs, on a cold start after all tabs are restored.
+ </summary>
+</histogram>
+
+<histogram name="Tabs.Tasks.TabsInGroupCount" units="tabs">
+ <owner>yusufo@chromium.org</owner>
+ <owner>wychen@chromium.org</owner>
+ <summary>
+ The number of tabs is belonging to a tab group on a cold start after all
+ tabs are restored.
+ </summary>
+</histogram>
+
+<histogram name="Tabs.Tasks.TabsInGroupRatio" units="%">
+ <owner>yusufo@chromium.org</owner>
+ <owner>wychen@chromium.org</owner>
+ <summary>
+ The ratio of all tabs in tab groups to the total number of tabs on a cold
+ start after all tabs are restored.
+ </summary>
+</histogram>
+
<histogram name="Tabs.TimeSinceLastInteraction" units="ms">
<owner>alexmos@chromium.org</owner>
<owner>dcheng@chromium.org</owner>
@@ -98662,6 +103470,15 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="TaskQueueManager.ActiveQueuesCount">
+ <owner>altimin@chromium.org</owner>
+ <owner>farahcharab@chromium.org</owner>
+ <summary>
+ Used to track the number of active task queues in the task queue manager.
+ Reported every time a task is selected for execution.
+ </summary>
+</histogram>
+
<histogram name="TaskQueueSelector.TaskServicedPerSelectorLogic"
enum="TaskQueueSelectorLogic">
<owner>altimin@chromium.org</owner>
@@ -98705,6 +103522,12 @@ uploading your change for review.
report and other work in the system. See
TaskScheduler.TaskLatencyMicroseconds.* for a metric that is closer to the
real workload.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -98769,6 +103592,28 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="TextToSpeech.Settings.DefaultVoicePicked"
+ enum="TextToSpeechVoiceIdHashes">
+ <owner>katie@chromium.org</owner>
+ <owner>dtseng@chromium.org</owner>
+ <owner>dmazzoni@chromium.org</owner>
+ <summary>
+ The user picked a default voice of the specified voice ID, which is hashed
+ from a JSON string of the voice name and extension ID.
+ </summary>
+</histogram>
+
+<histogram name="TextToSpeech.Settings.PreviewVoiceClicked"
+ enum="TextToSpeechVoiceIdHashes">
+ <owner>katie@chromium.org</owner>
+ <owner>dtseng@chromium.org</owner>
+ <owner>dmazzoni@chromium.org</owner>
+ <summary>
+ When the user requests a preview of a text-to-speech voice, records which
+ voice was previewed.
+ </summary>
+</histogram>
+
<histogram name="TextToSpeech.Utterance.FromExtensionAPI"
enum="TextToSpeechFromExtensionAPI">
<owner>dmazzoni@chromium.org</owner>
@@ -98843,6 +103688,30 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="TextToSpeechEngine.ParseVoice.HasGender"
+ enum="TextToSpeechHasGender" expires_after="M70">
+ <owner>katie@chromium.org</owner>
+ <owner>dtseng@chromium.org</owner>
+ <owner>dmazzoni@chromium.org</owner>
+ <summary>
+ True if a voice parsed from a ttsEngine extension manifest has a specific
+ gender. This is recorded each time a TTS extension is parsed, which may
+ occur multiple times per extension, in tts_engine_manifest_handler:
+ TtsVoices::Parse.
+ </summary>
+</histogram>
+
+<histogram name="TextToSpeechEngine.UpdateVoice.HasGender"
+ enum="TextToSpeechHasGender" expires_after="M70">
+ <owner>katie@chromium.org</owner>
+ <owner>dtseng@chromium.org</owner>
+ <owner>dmazzoni@chromium.org</owner>
+ <summary>
+ True if a voice specified in chrome.ttsEngine.updateVoices by a ttsEngine
+ extension has a specific gender.
+ </summary>
+</histogram>
+
<histogram name="ThirdPartyModules.Certificates.Microsoft" units="certificates">
<owner>chrisha@chromium.org</owner>
<summary>
@@ -98862,6 +103731,14 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="ThirdPartyModules.GetDriveLetterPathFound" enum="BooleanFound">
+ <owner>pmonette@chromium.org</owner>
+ <summary>
+ Records whether an equivalent driver letter path was found for a device
+ path.
+ </summary>
+</histogram>
+
<histogram name="ThirdPartyModules.InputMethodEditorsCount" units="counts">
<owner>pmonette@chromium.org</owner>
<summary>
@@ -99085,33 +103962,38 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="TimeZone.TimeZoneRequest.Event" enum="TimeZoneRequestEvent">
+<histogram name="TimeZone.TimeZoneRequest.Event" enum="TimeZoneRequestEvent"
+ expires_after="2018-08-30">
<summary>Events in TimeZoneRequest.</summary>
</histogram>
-<histogram name="TimeZone.TimeZoneRequest.ResponseCode" enum="HttpResponseCode">
+<histogram name="TimeZone.TimeZoneRequest.ResponseCode" enum="HttpResponseCode"
+ expires_after="2018-08-30">
<summary>Http response codes in TimeZoneRequest.</summary>
</histogram>
-<histogram name="TimeZone.TimeZoneRequest.ResponseFailureTime" units="ms">
+<histogram name="TimeZone.TimeZoneRequest.ResponseFailureTime" units="ms"
+ expires_after="2018-08-30">
<summary>
The time elapsed between the sending of the first API request and the time
the final (failed) response was recorded. Includes all retries.
</summary>
</histogram>
-<histogram name="TimeZone.TimeZoneRequest.ResponseSuccessTime" units="ms">
+<histogram name="TimeZone.TimeZoneRequest.ResponseSuccessTime" units="ms"
+ expires_after="2018-08-30">
<summary>
The time elapsed between the sending of the first API request and the time
the final (successfull) response was recorded. Includes all retries.
</summary>
</histogram>
-<histogram name="TimeZone.TimeZoneRequest.Result" enum="TimeZoneRequestResult">
+<histogram name="TimeZone.TimeZoneRequest.Result" enum="TimeZoneRequestResult"
+ expires_after="2018-08-30">
<summary>Result of TimeZoneRequest.</summary>
</histogram>
-<histogram name="TimeZone.TimeZoneRequest.Retries">
+<histogram name="TimeZone.TimeZoneRequest.Retries" expires_after="2018-08-30">
<summary>Number of retries until the final response was recorded.</summary>
</histogram>
@@ -99205,12 +104087,12 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="TopSites.NumberOfApplyBlacklist">
+<histogram name="TopSites.NumberOfApplyBlacklist" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>The number of times TopSitesImpl::ApplyBlacklist is called.</summary>
</histogram>
-<histogram name="TopSites.NumberOfBlacklistedItems">
+<histogram name="TopSites.NumberOfBlacklistedItems" expires_after="2018-08-30">
<owner>Please list the metric's owners. Add more owner tags as needed.</owner>
<summary>
The number of items in the user Most Visited blacklist every time
@@ -99418,6 +104300,9 @@ uploading your change for review.
</histogram>
<histogram name="TrafficStatsAmortizer.AmortizationDelay" units="ms">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>sclittle@chromium.org</owner>
<owner>bengr@chromium.org</owner>
<summary>
@@ -99428,6 +104313,9 @@ uploading your change for review.
</histogram>
<histogram name="TrafficStatsAmortizer.BufferSizeOnFlush" units="count">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>sclittle@chromium.org</owner>
<owner>bengr@chromium.org</owner>
<summary>
@@ -99436,6 +104324,9 @@ uploading your change for review.
</histogram>
<histogram name="TrafficStatsAmortizer.ConcurrentTabs" units="count">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>sclittle@chromium.org</owner>
<owner>bengr@chromium.org</owner>
<summary>
@@ -99448,6 +104339,9 @@ uploading your change for review.
<histogram name="TrafficStatsAmortizer.PostAmortizationRunDataUseBytes"
units="bytes">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>sclittle@chromium.org</owner>
<owner>bengr@chromium.org</owner>
<summary>
@@ -99460,6 +104354,9 @@ uploading your change for review.
<histogram name="TrafficStatsAmortizer.PreAmortizationRunDataUseBytes"
units="bytes">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<owner>sclittle@chromium.org</owner>
<owner>bengr@chromium.org</owner>
<summary>
@@ -100449,7 +105346,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="UMA.EntropySourceType" enum="UmaEntropySourceType">
+<histogram name="UMA.EntropySourceType" enum="UmaEntropySourceType"
+ expires_after="2018-08-30">
<owner>asvitkine@chromium.org</owner>
<summary>
Logs the entropy source type that was used for field trial randomization.
@@ -100457,30 +105355,31 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="UMA.ExpiredHistogram.BugReportTest" expires_after="2018-05-01">
+<histogram name="UMA.ExpiredHistogram.BugReportTest" expires_after="2018-07-20">
<owner>gayane@chromium.org</owner>
<summary>Not logged. Used for testing histogram expiry checker.</summary>
</histogram>
<histogram name="UMA.ExpiredHistogram.Milestone.BugReportTest"
- expires_after="M67">
+ expires_after="M68">
<owner>gayane@chromium.org</owner>
<summary>Not logged. Used for testing histogram expiry checker.</summary>
</histogram>
<histogram name="UMA.ExpiredHistogram.Milestone.Soon.BugReportTest"
- expires_after="M68">
+ expires_after="M69">
<owner>gayane@chromium.org</owner>
<summary>Not logged. Used for testing histogram expiry checker.</summary>
</histogram>
<histogram name="UMA.ExpiredHistogram.Soon.BugReportTest"
- expires_after="2018-06-01">
+ expires_after="2018-08-01">
<owner>gayane@chromium.org</owner>
<summary>Not logged. Used for testing histogram expiry checker.</summary>
</histogram>
-<histogram name="UMA.ExternalExperiment.GroupCount" units="groups">
+<histogram name="UMA.ExternalExperiment.GroupCount" units="groups"
+ expires_after="2018-08-30">
<owner>asvitkine@chromium.org</owner>
<summary>
Logged on Android whenever an external experiment is registered. The logged
@@ -100709,7 +105608,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="UMA.Large Accumulated Log Not Persisted" units="bytes">
+<histogram name="UMA.Large Accumulated Log Not Persisted" units="bytes"
+ expires_after="2018-08-30">
<owner>asvitkine@chromium.org</owner>
<summary>
Number of bytes in an excessively large log that was discarded at shutdown
@@ -100717,7 +105617,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="UMA.Large Rejected Log was Discarded" units="bytes">
+<histogram name="UMA.Large Rejected Log was Discarded" units="bytes"
+ expires_after="2018-08-30">
<owner>asvitkine@chromium.org</owner>
<summary>
Number of bytes in a log was was rejected by server, and then discarded.
@@ -100815,7 +105716,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="UMA.LowEntropySourceValue">
+<histogram name="UMA.LowEntropySourceValue" expires_after="2018-08-30">
<owner>asvitkine@chromium.org</owner>
<summary>
Distribution of the low entropy source value used for field trial
@@ -101170,6 +106071,37 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="UnifiedConsent.ConsentBump.Action"
+ enum="UnifiedConsentBumpAction" expires_after="2019-08-01">
+ <owner>tangltom@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <summary>
+ The action the user takes when the unified consent bump is shown.
+ </summary>
+</histogram>
+
+<histogram name="UnifiedConsent.ConsentBump.SuppressReason"
+ enum="UnifiedConsentBumpSuppressReason" expires_after="2019-08-01">
+ <owner>tangltom@chromium.org</owner>
+ <owner>msarda@chromium.org</owner>
+ <summary>
+ The reason the consent bump isn't shown to the user. This is recorded at
+ startup during the migration to Unified Consent.
+ </summary>
+</histogram>
+
+<histogram name="UnifiedConsent.SyncAndGoogleServicesSettings"
+ enum="UnifiedConsentSyncAndGoogleServicesSettings"
+ expires_after="2019-08-21">
+ <owner>tangltom@chromium.org</owner>
+ <owner>droger@chromium.org</owner>
+ <summary>
+ State of the user settings for Sync and Google services, recorded at
+ startup. Multiple samples may be recorded at once, except for 'None' which
+ is recorded when no other bucket is used.
+ </summary>
+</histogram>
+
<histogram name="UpdateClient.BackgroundDownloaderJobs" units="jobs">
<owner>sorin@chromium.org</owner>
<summary>
@@ -101759,6 +106691,20 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="UpdateEngine.SuccessfulUpdate.TotalDurationUptimeMinutes"
+ units="minutes">
+ <owner>senj@chromium.org</owner>
+ <summary>
+ The total number of minutes from when an update was detected until an update
+ (possibly another update) was applied. This does not include the time
+ waiting for update checks and time the device spent sleeping.
+
+ This is reported on every successful update.
+
+ This metric is specific to Chrome OS.
+ </summary>
+</histogram>
+
<histogram name="UpdateEngine.SuccessfulUpdate.UpdatesAbandonedCount"
units="count">
<owner>zeuthen@chromium.org</owner>
@@ -101868,7 +106814,24 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="Uptime.OtherProcessesTerminatedToChromeExecAfterLogout"
+ units="ms">
+ <owner>hajimehoshi@chromium.org</owner>
+ <owner>kouhei@chromium.org</owner>
+ <summary>
+ Measures the time elapsed on Chrome OS between when all user-associated
+ processes have been terminated during the logout process and when Chrome is
+ started again to show the login screen. Since at least ChromeOS M62,
+ equivalent to Uptime.XTerminatedToChromeExecAfterLogout.
+ </summary>
+</histogram>
+
<histogram name="Uptime.ProcessesTerminatedToXTerminatedAfterLogout" units="ms">
+ <obsolete>
+ Deprecated 05/2018 in Issue 721891 with removal of X11. Replaced by
+ Uptime.OtherProcessesTerminatedToChromeExecAfterLogout in ChromeOS M69.
+ Equal to 0 since at least ChromeOS M62.
+ </obsolete>
<owner>hajimehoshi@chromium.org</owner>
<owner>kouhei@chromium.org</owner>
<summary>
@@ -101891,6 +106854,10 @@ uploading your change for review.
</histogram>
<histogram name="Uptime.XTerminatedToChromeExecAfterLogout" units="ms">
+ <obsolete>
+ Replaced by Uptime.OtherProcessesTerminatedToChromeExecAfterLogout in
+ ChromeOS M69. Equivalent to the new name since at least ChromeOS M62.
+ </obsolete>
<owner>hajimehoshi@chromium.org</owner>
<owner>kouhei@chromium.org</owner>
<summary>
@@ -102067,7 +107034,15 @@ uploading your change for review.
<owner>bradnelson@chromium.org</owner>
<owner>titzer@chromium.org</owner>
<owner>aseemgarg@chromium.org</owner>
- <summary>Time to convert asm.js code to WebAssembly.</summary>
+ <summary>
+ Time to convert asm.js code to WebAssembly.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="V8.AsmWasmTranslationThroughput" units="MB/s">
@@ -102141,9 +107116,11 @@ uploading your change for review.
<summary>
Time spent compiling a script that may be subject to caching.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -102157,7 +107134,15 @@ uploading your change for review.
<histogram name="V8.CompileDeserializeMicroSeconds" units="microseconds">
<owner>vogelheim@chromium.org</owner>
- <summary>Time spent deseriailzing code, used by V8 code caching.</summary>
+ <summary>
+ Time spent deseriailzing code, used by V8 code caching.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="V8.CompileEval" units="ms">
@@ -102170,7 +107155,15 @@ uploading your change for review.
<histogram name="V8.CompileEvalMicroSeconds" units="microseconds">
<owner>yangguo@chromium.org</owner>
- <summary>Time spent in V8 compiler (full codegen) for eval.</summary>
+ <summary>
+ Time spent in V8 compiler (full codegen) for eval.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="V8.CompileHeuristicsDecision" enum="CompileHeuristicsDecision">
@@ -102208,15 +107201,25 @@ uploading your change for review.
Aggregated time spent compiling functions lazily during a single script
execution.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
<histogram name="V8.CompileMicroSeconds" units="microseconds">
<owner>yangguo@chromium.org</owner>
- <summary>Time spent in V8 compiler (full codegen) excluding parser.</summary>
+ <summary>
+ Time spent in V8 compiler (full codegen) excluding parser.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="V8.CompileNoncacheableMicroSeconds" units="microseconds">
@@ -102238,9 +107241,11 @@ uploading your change for review.
<summary>
Total time spent in compiling a script (incl. parsing/caching).
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -102257,6 +107262,12 @@ uploading your change for review.
<owner>yangguo@chromium.org</owner>
<summary>
Total time spent in compiling a script (incl. parsing/caching).
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -102267,9 +107278,11 @@ uploading your change for review.
Total time spent in compiling a script (incl. parsing) on a background
thread.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -102280,9 +107293,11 @@ uploading your change for review.
Total time spent in compiling a script when the 'compilation' is
deserializing it from the code cache.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -102293,9 +107308,11 @@ uploading your change for review.
Total time spent in compiling a script (incl. parsing/caching) when the
compilation tried to deserialize it from the code cache, but failed.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -102306,9 +107323,11 @@ uploading your change for review.
Total time spent in compiling a script (incl. parsing/caching) in the case
where the V8 isolate's compilation cache is hit.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -102319,9 +107338,11 @@ uploading your change for review.
Total time spent in compiling a script (incl. parsing) when the cache is too
cold to use.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -102332,9 +107353,11 @@ uploading your change for review.
Total time spent in compiling a script (incl. parsing) when the script is an
inline script.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -102345,9 +107368,11 @@ uploading your change for review.
Total time spent in compiling a script (incl. parsing) when we do not want
to cache it.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -102358,9 +107383,11 @@ uploading your change for review.
Total time spent in compiling a script (incl. parsing) when the script is
too small to be cached.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -102371,9 +107398,11 @@ uploading your change for review.
Total time spent in compiling a script (incl. parsing) and serializing it
for the code cache.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -102387,7 +107416,15 @@ uploading your change for review.
<histogram name="V8.CompileSerializeMicroSeconds" units="microseconds">
<owner>vogelheim@chromium.org</owner>
- <summary>Time spent serializing code, used by V8 code caching.</summary>
+ <summary>
+ Time spent serializing code, used by V8 code caching.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="V8.DebugFeatureUsage" enum="V8DebugFeature">
@@ -102447,9 +107484,11 @@ uploading your change for review.
Latency (post-to-schedule) of each parallel task posted during V8 garbage
collection.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -102504,15 +107543,79 @@ uploading your change for review.
<histogram name="V8.GCFinalizeMC" units="ms">
<owner>ulan@chromium.org</owner>
<owner>hpayer@chromium.org</owner>
- <summary>Time spent in finalize incremental mark-sweep phase of GC.</summary>
+ <summary>
+ Time spent in the final atomic pause of incremental latency-optimized
+ Mark-Compact GC.
+ </summary>
+</histogram>
+
+<histogram name="V8.GCFinalizeMC.Clear" units="ms">
+ <owner>ulan@chromium.org</owner>
+ <owner>hpayer@chromium.org</owner>
+ <summary>
+ Time spent in the clearing phase of incremental latency-optimized
+ Mark-Compact GC.
+ </summary>
+</histogram>
+
+<histogram name="V8.GCFinalizeMC.Epilogue" units="ms">
+ <owner>ulan@chromium.org</owner>
+ <owner>hpayer@chromium.org</owner>
+ <summary>
+ Time spent in the epilogue of incremental latency-optimized Mark-Compact GC.
+ </summary>
+</histogram>
+
+<histogram name="V8.GCFinalizeMC.Evacuate" units="ms">
+ <owner>ulan@chromium.org</owner>
+ <owner>hpayer@chromium.org</owner>
+ <summary>
+ Time spent in the evacuation phase of incremental latency-optimized
+ Mark-Compact GC.
+ </summary>
+</histogram>
+
+<histogram name="V8.GCFinalizeMC.Finish" units="ms">
+ <owner>ulan@chromium.org</owner>
+ <owner>hpayer@chromium.org</owner>
+ <summary>
+ Time spent in the finish phase of incremental latency-optimized Mark-Compact
+ GC.
+ </summary>
+</histogram>
+
+<histogram name="V8.GCFinalizeMC.Mark" units="ms">
+ <owner>ulan@chromium.org</owner>
+ <owner>hpayer@chromium.org</owner>
+ <summary>
+ Time spent in the marking phase of incremental latency-optimized
+ Mark-Compact GC.
+ </summary>
+</histogram>
+
+<histogram name="V8.GCFinalizeMC.Prologue" units="ms">
+ <owner>ulan@chromium.org</owner>
+ <owner>hpayer@chromium.org</owner>
+ <summary>
+ Time spent in the prologue of incremental latency-optimized Mark-Compact GC.
+ </summary>
+</histogram>
+
+<histogram name="V8.GCFinalizeMC.Sweep" units="ms">
+ <owner>ulan@chromium.org</owner>
+ <owner>hpayer@chromium.org</owner>
+ <summary>
+ Time spent in the sweeping phase of incremental latency-optimized
+ Mark-Compact GC.
+ </summary>
</histogram>
<histogram name="V8.GCFinalizeMCBackground" units="ms">
<owner>ulan@chromium.org</owner>
<owner>hpayer@chromium.org</owner>
<summary>
- Time spent in finalize incremental mark-sweep phase of GC in a background
- isolate.
+ Time spent in the final atomic pause of incremental latency-optimized
+ Mark-Compact GC in a background isolate.
</summary>
</histogram>
@@ -102520,8 +107623,8 @@ uploading your change for review.
<owner>ulan@chromium.org</owner>
<owner>hpayer@chromium.org</owner>
<summary>
- Time spent in finalize incremental mark-sweep phase of GC in a foreground
- isolate.
+ Time spent in the final atomic pause of incremental latency-optimized
+ Mark-Compact GC in a foreground isolate.
</summary>
</histogram>
@@ -102529,7 +107632,8 @@ uploading your change for review.
<owner>ulan@chromium.org</owner>
<owner>hpayer@chromium.org</owner>
<summary>
- Time spent in finalize incremental memory-reducing mark-sweep phase of GC.
+ Time spent in the final atomic pause of incremental memory-optimized
+ Mark-Compact GC.
</summary>
</histogram>
@@ -102537,8 +107641,8 @@ uploading your change for review.
<owner>ulan@chromium.org</owner>
<owner>hpayer@chromium.org</owner>
<summary>
- Time spent in finalize incremental memory-reducing mark-sweep phase of GC in
- a background isolate.
+ Time spent in the final atomic pause of incremental memory-optimized
+ Mark-Compact GC in a background isolate.
</summary>
</histogram>
@@ -102546,8 +107650,8 @@ uploading your change for review.
<owner>ulan@chromium.org</owner>
<owner>hpayer@chromium.org</owner>
<summary>
- Time spent in finalize incremental memory-reducing mark-sweep phase of GC in
- a foreground isolate.
+ Time spent in the final atomic pause of incremental memory-optimized
+ Mark-Compact GC in a foreground isolate.
</summary>
</histogram>
@@ -102734,6 +107838,9 @@ uploading your change for review.
</histogram>
<histogram name="V8.MemoryHeapCommitted" units="KB">
+ <obsolete>
+ This histogram has been replaced by Memory.Experimental.Renderer2.V8.
+ </obsolete>
<owner>ulan@chromium.org</owner>
<summary>
The committed memory used by V8 in KB averaged over time, logged before each
@@ -102869,6 +107976,10 @@ uploading your change for review.
</histogram>
<histogram name="V8.MemoryHeapUsed" units="KB">
+ <obsolete>
+ This histogram has been replaced by
+ Memory.Experimental.Renderer2.V8.AllocatedObjects.
+ </obsolete>
<owner>ulan@chromium.org</owner>
<summary>
The live memory used by V8 in KB averaged over time, logged before each GC.
@@ -102999,7 +108110,15 @@ uploading your change for review.
<histogram name="V8.WasmCompileFunctionMicroSeconds" units="microseconds">
<owner>bradnelson@chromium.org</owner>
<owner>titzer@chromium.org</owner>
- <summary>Time to compile a WebAssembly function.</summary>
+ <summary>
+ Time to compile a WebAssembly function.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="V8.WasmCompileFunctionPeakMemoryBytes" units="bytes">
@@ -103011,19 +108130,43 @@ uploading your change for review.
<histogram name="V8.WasmCompileModuleMicroSeconds" units="microseconds">
<owner>bradnelson@chromium.org</owner>
<owner>titzer@chromium.org</owner>
- <summary>Time to compile a WebAssembly module.</summary>
+ <summary>
+ Time to compile a WebAssembly module.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="V8.WasmDecodeFunctionMicroSeconds" units="microseconds">
<owner>bradnelson@chromium.org</owner>
<owner>titzer@chromium.org</owner>
- <summary>Time to decode a WebAssembly function.</summary>
+ <summary>
+ Time to decode a WebAssembly function.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="V8.WasmDecodeModuleMicroSeconds" units="microseconds">
<owner>bradnelson@chromium.org</owner>
<owner>titzer@chromium.org</owner>
- <summary>Time to decode a WebAssembly module.</summary>
+ <summary>
+ Time to decode a WebAssembly module.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="V8.WasmDecodeModulePeakMemoryBytes" units="bytes">
@@ -103037,7 +108180,15 @@ uploading your change for review.
<owner>titzer@chromium.org</owner>
<owner>eholk@chromium.org</owner>
<owner>kschimpf@chromium.org</owner>
- <summary>Time spent executing WebAssembly.</summary>
+ <summary>
+ Time spent executing WebAssembly.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="V8.WasmFunctionSizeBytes" units="bytes">
@@ -103055,7 +108206,15 @@ uploading your change for review.
<histogram name="V8.WasmInstantiateModuleMicroSeconds" units="microseconds">
<owner>bradnelson@chromium.org</owner>
<owner>titzer@chromium.org</owner>
- <summary>Time to instantiate a WebAssembly module.</summary>
+ <summary>
+ Time to instantiate a WebAssembly module.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="V8.WasmLazyCompilationMicroSeconds" units="microseconds">
@@ -103066,9 +108225,11 @@ uploading your change for review.
Time for lazy compilation of WebAssembly functions. This is recorded per
function for the functions that are lazily compiled.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -103239,7 +108400,15 @@ uploading your change for review.
<histogram name="Variations.HeaderConstructionTime" units="microseconds">
<owner>asvitkine@chromium.org</owner>
- <summary>How long it took to create the X-Client-Data header.</summary>
+ <summary>
+ How long it took to create the X-Client-Data header.
+
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
+ </summary>
</histogram>
<histogram name="Variations.Headers.ExperimentCount">
@@ -103268,7 +108437,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Variations.LoadSeedSignature" enum="VariationSeedSignature">
+<histogram name="Variations.LoadSeedSignature" enum="VariationSeedSignature"
+ expires_after="2018-08-30">
<owner>asvitkine@chromium.org</owner>
<summary>
The result of verifying the latest variations seed's signature, recorded
@@ -103288,7 +108458,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Variations.RequestCount">
+<histogram name="Variations.RequestCount" expires_after="2018-08-30">
<owner>asvitkine@chromium.org</owner>
<summary>
Number of previous requests to the variations server in the same session,
@@ -103555,7 +108725,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Variations.SimulateSeed.Duration" units="ms">
+<histogram name="Variations.SimulateSeed.Duration" units="ms"
+ expires_after="2018-08-30">
<owner>asvitkine@chromium.org</owner>
<summary>
Records the time taken to perform variations seed simulation.
@@ -103564,7 +108735,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Variations.SimulateSeed.KillBestEffortChanges">
+<histogram name="Variations.SimulateSeed.KillBestEffortChanges"
+ expires_after="2018-08-30">
<owner>asvitkine@chromium.org</owner>
<summary>
Records the result of variations seed simulation. Logs the number of
@@ -103575,7 +108747,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Variations.SimulateSeed.KillCriticalChanges">
+<histogram name="Variations.SimulateSeed.KillCriticalChanges"
+ expires_after="2018-08-30">
<owner>asvitkine@chromium.org</owner>
<summary>
Records the result of variations seed simulation. Logs the number of
@@ -103586,7 +108759,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Variations.SimulateSeed.NormalChanges">
+<histogram name="Variations.SimulateSeed.NormalChanges"
+ expires_after="2018-08-30">
<owner>asvitkine@chromium.org</owner>
<summary>
Records the result of variations seed simulation. Logs the number of
@@ -103654,7 +108828,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="Variations.StringsOverridden" units="strings">
+<histogram name="Variations.StringsOverridden" units="strings"
+ expires_after="2018-08-30">
<owner>asvitkine@chromium.org</owner>
<summary>
Records the number of UI strings overriden for each study that overrides
@@ -104313,6 +109488,9 @@ uploading your change for review.
</histogram>
<histogram name="WebApk.Install.AvailableSpaceAfterFreeUpAll.Fail" units="MB">
+ <obsolete>
+ Deprecated in Chrome M69.
+ </obsolete>
<owner>hanxi@chromium.org</owner>
<owner>ranj@chromium.org</owner>
<owner>yfriedman@chromium.org</owner>
@@ -104342,6 +109520,9 @@ uploading your change for review.
<histogram
name="WebApk.Install.AvailableSpaceAfterFreeUpUnimportantStorage.Fail"
units="MB">
+ <obsolete>
+ Deprecated in Chrome M69.
+ </obsolete>
<owner>hanxi@chromium.org</owner>
<owner>ranj@chromium.org</owner>
<owner>yfriedman@chromium.org</owner>
@@ -104365,6 +109546,9 @@ uploading your change for review.
</histogram>
<histogram name="WebApk.Install.ChromeUnimportantStorage.Fail" units="MB">
+ <obsolete>
+ Deprecated in Chrome M69.
+ </obsolete>
<owner>hanxi@chromium.org</owner>
<owner>ranj@chromium.org</owner>
<owner>yfriedman@chromium.org</owner>
@@ -104376,6 +109560,9 @@ uploading your change for review.
</histogram>
<histogram name="WebApk.Install.GooglePlayBindDuration" units="ms">
+ <obsolete>
+ Deprecated in Chrome M69.
+ </obsolete>
<owner>hanxi@chromium.org</owner>
<owner>pkotwicz@chromium.org</owner>
<owner>yfriedman@chromium.org</owner>
@@ -104563,6 +109750,9 @@ uploading your change for review.
</histogram>
<histogram name="WebApk.OpenFromMenu" enum="WebApkOpenResult">
+ <obsolete>
+ Deprecated in Chrome M69.
+ </obsolete>
<owner>hanxi@chromium.org</owner>
<owner>pkotwicz@chromium.org</owner>
<summary>
@@ -104632,6 +109822,38 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="WebApk.Startup.Cold.ShellLaunchToSplashscreenHidden"
+ units="ms">
+ <owner>mheikal@chromium.org</owner>
+ <owner>yfriedman@chromium.org</owner>
+ <summary>
+ Tracks the time to splashscreen hidden starting from the launch of the
+ WebAPK shell (rather than from the launch of Chrome). The splashscreen is
+ hidden after the first visually non-empty paint.
+
+ This is recorded iff: - This is a cold startup of Chrome. - Chrome has not
+ been sent to the background since launch. - There was no recents entry for
+ Chrome (android replays intents if a recents entry exists), which otherwise
+ adds noise/long-tail to this histogram.
+ </summary>
+</histogram>
+
+<histogram name="WebApk.Startup.Cold.ShellLaunchToSplashscreenVisible"
+ units="ms">
+ <owner>mheikal@chromium.org</owner>
+ <owner>yfriedman@chromium.org</owner>
+ <summary>
+ Tracks the time to splashscreen visible starting from the launch of the
+ WebAPK shell (rather than from the launch of Chrome). The splashscreen is
+ shown during postInflationStartup.
+
+ This is recorded iff: - This is a cold startup of Chrome. - Chrome has not
+ been sent to the background since launch. - There was no recents entry for
+ Chrome (android replays intents if a recents entry exists), which otherwise
+ adds noise/long-tail to this histogram.
+ </summary>
+</histogram>
+
<histogram name="WebApk.Update.GooglePlayUpdateResult"
enum="WebApkGooglePlayInstallResult">
<owner>hanxi@chromium.org</owner>
@@ -104955,9 +110177,12 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="WebAudio.Autoplay" enum="WebAudioAutoplayStatus">
+<histogram name="WebAudio.Autoplay" enum="WebAudioAutoplayStatus"
+ expires_after="2019-06-30">
<owner>mlamouri@chromium.org</owner>
<owner>media-dev@chromium.org</owner>
+ <owner>rtoy@chromium.org</owner>
+ <owner>hongchan@chromium.org</owner>
<summary>
The autoplay status of an AudioContext when destroyed. This include all
types of frames. In order to know the value only for main frames, the
@@ -104965,15 +110190,30 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="WebAudio.Autoplay.CrossOrigin" enum="WebAudioAutoplayStatus">
+<histogram name="WebAudio.Autoplay.CrossOrigin" enum="WebAudioAutoplayStatus"
+ expires_after="2019-06-30">
<owner>mlamouri@chromium.org</owner>
<owner>media-dev@chromium.org</owner>
+ <owner>rtoy@chromium.org</owner>
+ <owner>hongchan@chromium.org</owner>
<summary>
The autoplay status of an AudioContext when destroyed in a cross-origin
frame.
</summary>
</histogram>
+<histogram name="WebAudio.Autoplay.UnlockType"
+ enum="WebAudioAutoplayUnlockType" expires_after="2019-06-30">
+ <owner>mlamouri@chromium.org</owner>
+ <owner>media-dev@chromium.org</owner>
+ <owner>rtoy@chromium.org</owner>
+ <owner>hongchan@chromium.org</owner>
+ <summary>
+ Records how an AudioContext was unlocked (if it was). This is recorded when
+ the AudioContext is destroyed.
+ </summary>
+</histogram>
+
<histogram name="WebAudio.BiquadFilter.Q.Highpass">
<obsolete>
Removed in Issue 774526 on 2017/10; statistics aren't needed anymore.
@@ -105194,9 +110434,11 @@ uploading your change for review.
frame. These statistics would be used as features to classify whether the
page is suitable for DOM distiller.
- Warning: This high-resolution (microseconds) metric includes report from
- clients with low-resolution clocks on Windows, see
- UMA_HISTOGRAM_CUSTOM_HIGH_RESOLUTION_TIMES for a solution.
+ Warning: This metric may include reports from clients with low-resolution
+ clocks (i.e. on Windows, ref. |TimeTicks::IsHighResolution()|). Such reports
+ will cause this metric to have an abnormal distribution. When considering
+ revising this histogram, see UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES for the
+ solution.
</summary>
</histogram>
@@ -106683,7 +111925,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="WebHistory.LocalResultMissingOnServer" units="%">
+<histogram name="WebHistory.LocalResultMissingOnServer" units="%"
+ expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>
Percentage of results that are present locally but are not returned by the
@@ -106692,7 +111935,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="WebHistory.OAuthTokenCompletion" enum="BooleanSuccess">
+<histogram name="WebHistory.OAuthTokenCompletion" enum="BooleanSuccess"
+ expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>
Whether getting the OAuth token was successful for a web history query. On
@@ -106701,7 +111945,8 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="WebHistory.OAuthTokenResponseCode" units="code">
+<histogram name="WebHistory.OAuthTokenResponseCode" units="code"
+ expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>
HTTP Response code returned by the server when trying to fetch the OAuth
@@ -106719,7 +111964,7 @@ uploading your change for review.
</summary>
</histogram>
-<histogram name="WebHistory.ResponseTime" units="ms">
+<histogram name="WebHistory.ResponseTime" units="ms" expires_after="2018-08-30">
<owner>zea@chromium.org</owner>
<summary>
Time it took for the web history to reply. Recorded when the web history API
@@ -107902,6 +113147,16 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="WebRTC.PeerConnection.UsagePattern"
+ enum="WebRtcPeerConnectionUsagePattern">
+ <owner>hta@chromium.org</owner>
+ <summary>
+ Capsule history of a WebRTC PeerConnection, encoded as a sequence of bits
+ encapsulated in an integer. Only a few values will be deemed interesting,
+ but the interesting values may change over time.
+ </summary>
+</histogram>
+
<histogram name="WebRTC.ReceivedAudioTrackDuration" units="ms">
<owner>perkj@chromium.org</owner>
<summary>
@@ -108445,6 +113700,22 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="WebRTC.Video.MeanFreezeDurationMs" units="ms">
+ <owner>ilnik@chromium.org</owner>
+ <summary>
+ The average duration of a freeze in video playback. Recorded then a recieve
+ stream is removed or content type changes.
+ </summary>
+</histogram>
+
+<histogram name="WebRTC.Video.MeanTimeBetweenFreezesMs" units="ms">
+ <owner>ilnik@chromium.org</owner>
+ <summary>
+ The average duration of a smooth video playback. Recorded then a recieve
+ stream is removed or content type changes.
+ </summary>
+</histogram>
+
<histogram name="WebRTC.Video.MediaBitrateReceivedInKbps" units="kbps">
<owner>asapersson@chromium.org</owner>
<summary>
@@ -108490,6 +113761,15 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="WebRTC.Video.NumberResolutionDownswitchesPerMinute"
+ units="switches/minute">
+ <owner>ilnik@chromium.org</owner>
+ <summary>
+ The average number of resolution down-switches per minute for a receive
+ video stream. Recorded then a stream is removed or content type changes.
+ </summary>
+</histogram>
+
<histogram name="WebRTC.Video.OnewayDelayInMs" units="ms">
<owner>asapersson@chromium.org</owner>
<summary>
@@ -108890,6 +114170,22 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="WebRTC.Video.Screenshare.MeanFreezeDurationMs" units="ms">
+ <owner>ilnik@chromium.org</owner>
+ <summary>
+ The average duration of a freeze in screenshare playback. Recorded then a
+ recieve stream is removed or content type changes.
+ </summary>
+</histogram>
+
+<histogram name="WebRTC.Video.Screenshare.MeanTimeBetweenFreezesMs" units="ms">
+ <owner>ilnik@chromium.org</owner>
+ <summary>
+ The average duration of a smooth video playback for screenshare stream.
+ Recorded then a recieve stream is removed or content type changes.
+ </summary>
+</histogram>
+
<histogram name="WebRTC.Video.Screenshare.MediaBitrateReceivedInKbps"
units="kbps">
<owner>ilnik@chromium.org</owner>
@@ -108919,6 +114215,17 @@ uploading your change for review.
</summary>
</histogram>
+<histogram
+ name="WebRTC.Video.Screenshare.NumberResolutionDownswitchesPerMinute"
+ units="switches/minute">
+ <owner>ilnik@chromium.org</owner>
+ <summary>
+ The average number of resolution down-switches per minute for a receive
+ screenshare stream. Recorded then a stream is removed or content type
+ changes.
+ </summary>
+</histogram>
+
<histogram name="WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"
units="kbps">
<owner>sprang@chromium.org</owner>
@@ -109079,6 +114386,23 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="WebRTC.Video.Screenshare.TimeInBlockyVideoPercentage"
+ units="%">
+ <owner>ilnik@chromium.org</owner>
+ <summary>
+ Percentage of time the recieve screenshare stream playbacks low quality
+ blocky video. Recorded then a stream is removed or content type changes.
+ </summary>
+</histogram>
+
+<histogram name="WebRTC.Video.Screenshare.TimeInHdPercentage" units="%">
+ <owner>ilnik@chromium.org</owner>
+ <summary>
+ Percentage of time the recieve screenshare stream playbacks HD resolution.
+ Recorded then a stream is removed or content type changes.
+ </summary>
+</histogram>
+
<histogram name="WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"
units="%">
<owner>sprang@chromium.org</owner>
@@ -109177,6 +114501,22 @@ uploading your change for review.
</summary>
</histogram>
+<histogram name="WebRTC.Video.TimeInBlockyVideoPercentage" units="%">
+ <owner>ilnik@chromium.org</owner>
+ <summary>
+ Percentage of time the recieve video stream playbacks low quality blocky
+ video. Recorded then a stream is removed or content type changes.
+ </summary>
+</histogram>
+
+<histogram name="WebRTC.Video.TimeInHdPercentage" units="%">
+ <owner>ilnik@chromium.org</owner>
+ <summary>
+ Percentage of time the recieve video stream playbacks HD resolution.
+ Recorded then a stream is removed or content type changes.
+ </summary>
+</histogram>
+
<histogram name="WebRTC.Video.UniqueNackRequestsReceivedInPercent" units="%">
<owner>asapersson@chromium.org</owner>
<summary>
@@ -110255,6 +115595,14 @@ uploading your change for review.
<histogram_suffixes_list>
+<histogram_suffixes name="AccessorySheetType" separator=".">
+ <suffix name="Passwords" label="Password suggestions and generation."/>
+ <affected-histogram name="KeyboardAccessory.AccessorySheetSuggestionCount"/>
+ <affected-histogram
+ name="KeyboardAccessory.AccessorySheetSuggestionsSelected"/>
+ <affected-histogram name="KeyboardAccessory.AccessorySheetTriggered"/>
+</histogram_suffixes>
+
<histogram_suffixes name="AccountInvestigationReportingType" separator="_">
<suffix name="OnChange"
label="Driven from a change in signin status or change in content area
@@ -110291,10 +115639,8 @@ uploading your change for review.
<suffix name="Tabbed"
label="Chrome starts up with intent to ChromeTabbedActivity"/>
<suffix name="WebApk" label="Chrome starts up with intent to WebApkActivity"/>
- <affected-histogram
- name="Startup.Android.Experimental.Cold.TimeToFirstContentfulPaint"/>
- <affected-histogram
- name="Startup.Android.Experimental.Cold.TimeToFirstNavigationCommit"/>
+ <affected-histogram name="Startup.Android.Cold.TimeToFirstContentfulPaint"/>
+ <affected-histogram name="Startup.Android.Cold.TimeToFirstNavigationCommit"/>
</histogram_suffixes>
<histogram_suffixes name="AdsPageLoadMetrics" separator="." ordering="prefix">
@@ -110483,12 +115829,20 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="ArcUserTypes" separator=".">
+ <suffix name="ActiveDirectory" label="User with active directory account"/>
<suffix name="Child" label="User with child accounts."/>
+ <suffix name="DemoMode" label="Demo devices with a demo mode robot account."/>
<suffix name="Managed" label="User with forced Play Store feature"/>
+ <suffix name="OfflineDemoMode" label="Offline enrolled demo mode devices."/>
<suffix name="RobotAccount"
label="Managed devices with a robot account (Public Session or Kiosk)"/>
<suffix name="Unmanaged" label="User with optional Play Store feature"/>
<affected-histogram name="Arc.PlayStoreShown.TimeDelta"/>
+ <affected-histogram name="Arc.Provisioning.Result"/>
+ <affected-histogram name="Arc.Provisioning.TimeDelta.Failure"/>
+ <affected-histogram name="Arc.Provisioning.TimeDelta.Success"/>
+ <affected-histogram name="Arc.Reauthorization.Result"/>
+ <affected-histogram name="Arc.StateByUserType"/>
</histogram_suffixes>
<histogram_suffixes name="AsyncDNSPref" separator="_">
@@ -110507,13 +115861,13 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="AttemptResultCode" separator="_">
+ <obsolete>
+ Deprecated 2016/03. The async set-as-default experiments are finished.
+ </obsolete>
<suffix name="Abandoned"/>
<suffix name="Failure"/>
<suffix name="NoErrorsNotDefault"/>
<suffix name="Retry"/>
- <obsolete>
- Deprecated 2016/03. The async set-as-default experiments are finished.
- </obsolete>
<suffix name="Success"/>
<affected-histogram name="DefaultBrowser.AsyncSetAsDefault.Duration"/>
<affected-histogram name="DefaultBrowser.SetDefaultAsyncDuration"/>
@@ -110550,6 +115904,16 @@ uploading your change for review.
<affected-histogram name="Autofill.CreditCardInfoBar"/>
</histogram_suffixes>
+<histogram_suffixes name="AutofillCreditCardType" separator=".">
+ <suffix name="Local" label="Local"/>
+ <suffix name="Server" label="Server (Google Payments)"/>
+ <affected-histogram name="Autofill.DaysSinceLastUse.StoredCreditCard"/>
+ <affected-histogram name="Autofill.SaveCardWithFirstAndLastNameComplete"/>
+ <affected-histogram name="Autofill.SaveCardWithFirstAndLastNameOffered"/>
+ <affected-histogram name="Autofill.StoredCreditCardCount"/>
+ <affected-histogram name="Autofill.StoredCreditCardDisusedCount"/>
+</histogram_suffixes>
+
<histogram_suffixes name="AutofillDataAvailability" separator=".">
<suffix name="WithBothServerAndLocalData"
label="both server and local autofill data"/>
@@ -110586,6 +115950,13 @@ uploading your change for review.
<affected-histogram name="Autofill.UserHappiness"/>
</histogram_suffixes>
+<histogram_suffixes name="AutofillLocalCardMigrationBubbleShow" separator=".">
+ <suffix name="FirstShow" label="First time bubble is shown"/>
+ <suffix name="Reshows" label="Bubble was reopened after being closed"/>
+ <affected-histogram name="Autofill.LocalCardMigrationBubbleOffer"/>
+ <affected-histogram name="Autofill.LocalCardMigrationBubbleUserInteraction"/>
+</histogram_suffixes>
+
<histogram_suffixes name="AutofillPayloadCompressionType" separator=".">
<suffix name="Query" label="Query request compression"/>
<suffix name="Upload" label="Upload request compression"/>
@@ -110623,6 +115994,14 @@ uploading your change for review.
<affected-histogram name="Autofill.SaveCreditCardPrompt.Upload.Reshows"/>
</histogram_suffixes>
+<histogram_suffixes name="AutofillSaveCreditCardPromptRequestingCardholderName"
+ separator=".">
+ <suffix name="RequestingCardholderName"
+ label="Cardholder name was explicitly requested in prompt"/>
+ <affected-histogram name="Autofill.SaveCreditCardPrompt.Upload.FirstShow"/>
+ <affected-histogram name="Autofill.SaveCreditCardPrompt.Upload.Reshows"/>
+</histogram_suffixes>
+
<histogram_suffixes name="AutofillSaveCreditCardPromptShow" separator=".">
<suffix name="FirstShow"
label="first time prompt is shown for a single credit card submit"/>
@@ -110632,6 +116011,13 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="AutofillServerExperiments" separator="_">
+ <obsolete>
+ Deprecated as of at least 2013. Current autofill experiments rely on Finch
+ rather than a custom experimentation setup.
+ </obsolete>
+ <suffix name="ar1" label="Acceptance ratio: 1.0"/>
+ <suffix name="ar2" label="Acceptance ratio: 2.0"/>
+ <suffix name="ar4" label="Acceptance ratio: 4.0"/>
<suffix name="ar04wr3fs4"
label="Acceptance ratio: 0.4; winner lead ratio: 3.0; min form score: 4"/>
<suffix name="ar05wlr15"
@@ -110640,15 +116026,7 @@ uploading your change for review.
label="Acceptance ratio: 0.5; winner lead ratio: 2.5"/>
<suffix name="ar05wr15fs5"
label="Acceptance ratio: 0.5; winner lead ratio: 1.5; min form score: 5"/>
- <obsolete>
- Deprecated as of at least 2013. Current autofill experiments rely on Finch
- rather than a custom experimentation setup.
- </obsolete>
<suffix name="ar06" label="Acceptance ratio: 0.6"/>
- <suffix name="ar1" label="Acceptance ratio: 1.0"/>
- <suffix name="ar2" label="Acceptance ratio: 2.0"/>
- <suffix name="ar4" label="Acceptance ratio: 4.0"/>
- <suffix name="fp025" label="Probability picker algorithm, p=0.25"/>
<suffix name="fp05" label="Probability picker algorithm, p=0.5"/>
<suffix name="fp05cc03"
label="Probability picker algorithm, p=0.5; p_ccname=0.3"/>
@@ -110663,6 +116041,7 @@ uploading your change for review.
label="Probability picker algorithm, p=0.5;
p_ccname_given_other_cc_fields=0.3; with fallback to the default
algorithm"/>
+ <suffix name="fp025" label="Probability picker algorithm, p=0.25"/>
<suffix name="tbar1" label="Use only Toolbar upload data"/>
<affected-histogram name="Autofill.Quality"/>
<affected-histogram name="AutoFill.Quality"/>
@@ -110674,14 +116053,6 @@ uploading your change for review.
<affected-histogram name="Autofill.Quality.ServerType.ByFieldType"/>
</histogram_suffixes>
-<histogram_suffixes name="AutofillStoredCreditCardCount" separator=".">
- <suffix name="Local" label="Local"/>
- <suffix name="Server" label="Server (Google Payments)"/>
- <affected-histogram name="Autofill.DaysSinceLastUse.StoredCreditCard"/>
- <affected-histogram name="Autofill.StoredCreditCardCount"/>
- <affected-histogram name="Autofill.StoredCreditCardDisusedCount"/>
-</histogram_suffixes>
-
<histogram_suffixes name="AutofillStoredServerCardType" separator=".">
<suffix name="Masked" label="Masked cards"/>
<suffix name="Unmasked" label="Unmasked cards (locally cached)"/>
@@ -110732,21 +116103,21 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="BatchStunPingParameters" separator=".">
- <suffix name="10ms.1" label="10ms gap, 1st batch"/>
- <suffix name="10ms.2" label="10ms gap, 2nd batch"/>
- <suffix name="10ms.3" label="10ms gap, 3rd batch"/>
<suffix name="1ms.1" label="1ms gap, 1st batch"/>
<suffix name="1ms.2" label="1ms gap, 2nd batch"/>
<suffix name="1ms.3" label="1ms gap, 3rd batch"/>
+ <suffix name="5ms.1" label="5ms gap, 1st batch"/>
+ <suffix name="5ms.2" label="5ms gap, 2nd batch"/>
+ <suffix name="5ms.3" label="5ms gap, 3rd batch"/>
+ <suffix name="10ms.1" label="10ms gap, 1st batch"/>
+ <suffix name="10ms.2" label="10ms gap, 2nd batch"/>
+ <suffix name="10ms.3" label="10ms gap, 3rd batch"/>
<suffix name="25ms.1" label="25ms gap, 1st batch"/>
<suffix name="25ms.2" label="25ms gap, 2nd batch"/>
<suffix name="25ms.3" label="25ms gap, 3rd batch"/>
<suffix name="50ms.1" label="50ms gap, 1st batch"/>
<suffix name="50ms.2" label="50ms gap, 2nd batch"/>
<suffix name="50ms.3" label="50ms gap, 3rd batch"/>
- <suffix name="5ms.1" label="5ms gap, 1st batch"/>
- <suffix name="5ms.2" label="5ms gap, 2nd batch"/>
- <suffix name="5ms.3" label="5ms gap, 3rd batch"/>
<affected-histogram name="WebRTC.Stun.BatchSuccessPercent.NoNAT"/>
<affected-histogram name="WebRTC.Stun.BatchSuccessPercent.NonSymNAT"/>
<affected-histogram name="WebRTC.Stun.BatchSuccessPercent.SymNAT"/>
@@ -110855,12 +116226,42 @@ uploading your change for review.
<histogram_suffixes name="BlinkGCReason" separator="_">
<suffix name="ConservativeGC" label="Conservative GC"/>
- <suffix name="ForcedGC" label="Forced GC for testing"/>
+ <suffix name="ForcedGC" label="Forced GC"/>
<suffix name="IdleGC" label="Idle GC"/>
+ <suffix name="IncrementalIdleGC" label="Idle GC with incremental marking"/>
+ <suffix name="IncrementalV8FollowupGC"
+ label="V8 follow-up GC with incremental marking"/>
<suffix name="MemoryPressureGC" label="Memory pressure GC"/>
<suffix name="PageNavigationGC" label="Page navigation GC"/>
<suffix name="PreciseGC" label="Precise GC"/>
+ <suffix name="Testing" label="Testing GC"/>
+ <suffix name="ThreadTerminationGC" label="Thread termination GC"/>
+ <affected-histogram name="BlinkGC.AtomicPhaseMarking"/>
<affected-histogram name="BlinkGC.CollectionRate"/>
+ <affected-histogram name="BlinkGC.TimeForTotalCollectGarbage"/>
+</histogram_suffixes>
+
+<histogram_suffixes name="BlinkLazyLoadEffectiveConnectionTypeSuffixes"
+ separator=".">
+ <suffix name="2G" label="2G effective connection type"/>
+ <suffix name="3G" label="3G effective connection type"/>
+ <suffix name="4G" label="4G effective connection type"/>
+ <suffix name="Offline" label="Offline effective connection type"/>
+ <suffix name="Slow2G" label="Slow-2G effective connection type"/>
+ <suffix name="Unknown" label="Unknown effective connection type"/>
+ <affected-histogram
+ name="Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction"/>
+</histogram_suffixes>
+
+<histogram_suffixes name="BlinkVisibleLoadTimeSuffixes" separator=".">
+ <suffix name="2G" label="2G effective connection type"/>
+ <suffix name="3G" label="3G effective connection type"/>
+ <suffix name="4G" label="4G effective connection type"/>
+ <suffix name="Slow2G" label="Slow-2G effective connection type"/>
+ <affected-histogram
+ name="Blink.VisibleLoadTime.LazyLoadEligibleFrames.AboveTheFold"/>
+ <affected-histogram
+ name="Blink.VisibleLoadTime.LazyLoadEligibleFrames.BelowTheFold"/>
</histogram_suffixes>
<histogram_suffixes name="CachedResourceType" separator=".">
@@ -111029,6 +116430,9 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="CacheSensitivityAnalysis" separator="_">
+ <obsolete>
+ Experiments no longer active.
+ </obsolete>
<suffix name="100" label="100% slowdown"/>
<suffix name="100A" label="100% slowdown, Group A"/>
<suffix name="100B" label="100% slowdown, Group B"/>
@@ -111039,9 +116443,6 @@ uploading your change for review.
<suffix name="Control" label="Control group"/>
<suffix name="ControlA" label="Control, Group A"/>
<suffix name="ControlB" label="Control, Group B"/>
- <obsolete>
- Experiments no longer active.
- </obsolete>
<suffix name="No" label="Turned off"/>
<affected-histogram name="Net.HttpJob.TotalTime"/>
<affected-histogram name="Net.HttpJob.TotalTimeCached"/>
@@ -111169,12 +116570,12 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="CertIo" separator="">
- <suffix name="ReadFailure"
- label="failure rate of reading a certificate from the disk cache"/>
<obsolete>
Deprecated as of 01/2016. CertCacheTrial has been removed.
https://crbug.com/522312
</obsolete>
+ <suffix name="ReadFailure"
+ label="failure rate of reading a certificate from the disk cache"/>
<suffix name="ReadSuccess"
label="success rate of reading a certificate from the disk cache"/>
<suffix name="WriteFailure"
@@ -111193,7 +116594,10 @@ uploading your change for review.
label="Activity launched in DOCUMENT mode (Tabs and apps together) on
Android"/>
<affected-histogram name="MobileStartup.ToolbarFirstDrawTime"/>
+ <affected-histogram name="MobileStartup.ToolbarFirstDrawTime2"/>
+ <affected-histogram name="MobileStartup.ToolbarFirstFocusStartupState"/>
<affected-histogram name="MobileStartup.ToolbarFirstFocusTime"/>
+ <affected-histogram name="MobileStartup.ToolbarFirstFocusTime2"/>
<affected-histogram name="MobileStartup.ToolbarInflationTime"/>
</histogram_suffixes>
@@ -111275,8 +116679,6 @@ uploading your change for review.
<suffix name="Impl" label="Impl side invalidation initiated pending tree"/>
<suffix name="Main" label="Commit initiated pending tree"/>
<affected-histogram
- name="Scheduling.Browser.ReadyToActivateToActivationDuration2"/>
- <affected-histogram
name="Scheduling.Renderer.ReadyToActivateToActivationDuration2"/>
</histogram_suffixes>
@@ -111286,24 +116688,15 @@ uploading your change for review.
<suffix name="Renderer"/>
<affected-histogram name="Scheduling.ActivateDuration2"/>
<affected-histogram name="Scheduling.BeginImplFrameLatency2"/>
- <affected-histogram name="Scheduling.BeginMainFrameIntervalCritical2"/>
- <affected-histogram name="Scheduling.BeginMainFrameIntervalNotCritical2"/>
<affected-histogram name="Scheduling.BeginMainFrameQueueDurationCritical2"/>
- <affected-histogram
- name="Scheduling.BeginMainFrameQueueDurationNotCritical2"/>
<affected-histogram name="Scheduling.BeginMainFrameStartToCommitDuration2"/>
- <affected-histogram name="Scheduling.CommitInterval2"/>
<affected-histogram name="Scheduling.CommitToReadyToActivateDuration2"/>
<affected-histogram name="Scheduling.DrawDuration2"/>
- <affected-histogram name="Scheduling.DrawInterval2"/>
- <affected-histogram name="Scheduling.DrawIntervalWithCompositedAnimations2"/>
- <affected-histogram name="Scheduling.DrawIntervalWithMainThreadAnimations2"/>
<affected-histogram
name="Scheduling.DrawIntervalWithMainThreadCompositableAnimations2"/>
<affected-histogram name="Scheduling.InvalidationToReadyToActivateDuration2"/>
<affected-histogram name="Scheduling.MainAndImplFrameTimeDelta2"/>
<affected-histogram name="Scheduling.PrepareTilesDuration2"/>
- <affected-histogram name="Scheduling.ReadyToActivateToActivationDuration2"/>
<affected-histogram name="Scheduling.SwapAckWasFast"/>
<affected-histogram name="Scheduling.SwapToAckLatency2"/>
</histogram_suffixes>
@@ -111313,8 +116706,6 @@ uploading your change for review.
<suffix name="Browser"/>
<suffix name="Renderer"/>
<affected-histogram name="Scheduling.ImageInvalidationUpdateDuration"/>
- <affected-histogram name="Scheduling.PendingTreeDuration"/>
- <affected-histogram name="Scheduling.PendingTreeRasterDuration"/>
</histogram_suffixes>
<histogram_suffixes name="CompositorTimingHistoryProcessObsolete" separator="."
@@ -111406,13 +116797,13 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="ConnCountImpact" separator="_">
- <suffix name="conn_count_16" label="with 16 persistent connections per host"/>
<suffix name="conn_count_4" label="with 4 persistent connections per host"/>
<suffix name="conn_count_5" label="with 5 persistent connections per host"/>
<suffix name="conn_count_6" label="with 6 persistent connections per host"/>
<suffix name="conn_count_7" label="with 7 persistent connections per host"/>
<suffix name="conn_count_8" label="with 8 persistent connections per host"/>
<suffix name="conn_count_9" label="with 9 persistent connections per host"/>
+ <suffix name="conn_count_16" label="with 16 persistent connections per host"/>
<affected-histogram name="Net.Transaction_Connected_New"/>
<affected-histogram name="PLT.Abandoned"/>
<affected-histogram name="PLT.BeginToFinish_LinkLoadNormal"/>
@@ -111436,13 +116827,13 @@ uploading your change for review.
<suffix name="Unknown"/>
<affected-histogram name="Net.QuicSession.ConnectionMigration"/>
<affected-histogram name="Net.QuicSession.ConnectionMigrationProbeSuccess"/>
+ <affected-histogram
+ name="Net.QuicSession.HandshakeStatusOnConnectionMigration"/>
</histogram_suffixes>
<histogram_suffixes name="ConnectivityDiagnostics" separator=".">
<suffix name="0" label="INTERNET_DISCONNECTED"/>
<suffix name="1" label="CHROME_VERSION"/>
- <suffix name="10" label="NIC_SIGNAL_STRENGTH"/>
- <suffix name="11" label="PING_GATEWAY"/>
<suffix name="2" label="CHROMEOS_VERSION"/>
<suffix name="3" label="DNS_RESOLVER_PRESENT"/>
<suffix name="4" label="CAPTIVE_PORTAL_DNS"/>
@@ -111451,6 +116842,8 @@ uploading your change for review.
<suffix name="7" label="FIREWALL_443"/>
<suffix name="8" label="RESOLVER_LATENCY"/>
<suffix name="9" label="HTTP_LATENCY"/>
+ <suffix name="10" label="NIC_SIGNAL_STRENGTH"/>
+ <suffix name="11" label="PING_GATEWAY"/>
<affected-histogram name="ConnectivityDiagnostics.TestVerdict"/>
<affected-histogram name="ConnectivityDiagnostics.TimeTaken"/>
</histogram_suffixes>
@@ -111576,6 +116969,8 @@ uploading your change for review.
label="A BrowserCompositor GPU command buffer context"/>
<suffix name="BrowserMainThread"
label="A BrowserMainThread GPU command buffer context"/>
+ <suffix name="DisplayCompositor"
+ label="A display compositor GPU command buffer context"/>
<suffix name="Media" label="The media worker command buffer context"/>
<suffix name="MusClient" label="A mus client command buffer context"/>
<suffix name="RenderCompositor"
@@ -111584,7 +116979,11 @@ uploading your change for review.
label="A RenderMainThread GPU command buffer context"/>
<suffix name="RenderWorker"
label="A RenderWorker GPU command buffer context"/>
- <suffix name="UICompositor" label="The UI compositor command buffer context"/>
+ <suffix name="UICompositor" label="The UI compositor command buffer context">
+ <obsolete>
+ Deprecated and removed from code as of 07/2018.
+ </obsolete>
+ </suffix>
<suffix name="Unknown" label="A GPU command buffer context of unknown type"/>
<suffix name="VideoAccelerator"
label="A VideoAccelerator GPU command buffer context"/>
@@ -111782,12 +117181,12 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="DataReductionProxy_AutoLoFi" separator="_">
- <suffix name="DataReductionProxy_AutoLoFiOff"
- label="Only page loads through the data reduction proxy with auto LoFi
- disabled are considered."/>
<obsolete>
Deprecated 09/2016.
</obsolete>
+ <suffix name="DataReductionProxy_AutoLoFiOff"
+ label="Only page loads through the data reduction proxy with auto LoFi
+ disabled are considered."/>
<suffix name="DataReductionProxy_AutoLoFiOn"
label="Only page loads through the data reduction proxy with auto LoFi
enabled are considered."/>
@@ -111815,12 +117214,12 @@ uploading your change for review.
<suffix name="CompressionRatio_Image_0_10KB"
label="the histogram of compression ratio of images whose sizes are in
the range of 0-10KB"/>
- <suffix name="CompressionRatio_Image_100_500KB"
- label="the histogram of compression ratio of images whose sizes are in
- the range of 100-500KB"/>
<suffix name="CompressionRatio_Image_10_100KB"
label="the histogram of compression ratio of images whose sizes are in
the range of 10-100KB"/>
+ <suffix name="CompressionRatio_Image_100_500KB"
+ label="the histogram of compression ratio of images whose sizes are in
+ the range of 100-500KB"/>
<suffix name="CompressionRatio_Image_500KB"
label="the histogram of compression ratio of images whose sizes are
larger than 500KB"/>
@@ -111964,8 +117363,8 @@ uploading your change for review.
<suffix name="CSS" label="CSS count"/>
<suffix name="Image" label="image count"/>
<suffix name="Image_0_10KB" label="image counts of 0-10KB"/>
- <suffix name="Image_100_500KB" label="image counts of 100-500KB"/>
<suffix name="Image_10_100KB" label="image counts of 10-100KB"/>
+ <suffix name="Image_100_500KB" label="image counts of 100-500KB"/>
<suffix name="Image_500KB" label="image counts of more than 500KB"/>
<suffix name="Image_GIF" label="GIF image count"/>
<suffix name="Image_JPG" label="JPG image count"/>
@@ -112236,6 +117635,8 @@ uploading your change for review.
<suffix name="Downstream.Foreground"/>
<suffix name="Upstream.Background"/>
<suffix name="Upstream.Foreground"/>
+ <affected-histogram name="DataReductionProxy.LastWeekAggregateKB.Services"/>
+ <affected-histogram name="DataReductionProxy.ThisWeekAggregateKB.Services"/>
<affected-histogram name="DataUse.AllServicesKB"/>
</histogram_suffixes>
@@ -112294,11 +117695,11 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="DefaultPinnedApps" separator="_">
- <suffix name="Alternate"/>
- <suffix name="Control"/>
<obsolete>
Deprecated as of 12/2013. Default pinned apps trial is finished.
</obsolete>
+ <suffix name="Alternate"/>
+ <suffix name="Control"/>
<suffix name="Existing"/>
<affected-histogram name="Cros.ClickOnShelf"/>
</histogram_suffixes>
@@ -112602,6 +118003,17 @@ uploading your change for review.
<affected-histogram name="Dialog.Create"/>
</histogram_suffixes>
+<histogram_suffixes name="DiscardReason" separator=".">
+ <suffix name="Extension" label="An extension discarded a tab."/>
+ <suffix name="Proactive"
+ label="The browser proactively discarded a tab to avoid entering a
+ memory pressure state."/>
+ <suffix name="Urgent"
+ label="The browser urgently discarded a tab because there was memory
+ pressure."/>
+ <affected-histogram name="Discarding.OnlineOnReload"/>
+</histogram_suffixes>
+
<histogram_suffixes name="DiskUsagePerUserCount" separator=".">
<suffix name="1User" label="Only 1 user exists on device."/>
<suffix name="2Users" label="2 users exist on device."/>
@@ -112690,12 +118102,6 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="DnsParallelism" separator="_">
- <suffix name="parallel_10"
- label="with only 10 concurrent resolutions done in parallel"/>
- <suffix name="parallel_14"
- label="with only 14 concurrent resolutions done in parallel"/>
- <suffix name="parallel_20"
- label="with only 20 concurrent resolutions done in parallel"/>
<suffix name="parallel_6"
label="with only 6 concurrent resolutions done in parallel"/>
<suffix name="parallel_7"
@@ -112704,6 +118110,12 @@ uploading your change for review.
label="with only 8 concurrent resolutions done in parallel"/>
<suffix name="parallel_9"
label="with only 9 concurrent resolutions done in parallel"/>
+ <suffix name="parallel_10"
+ label="with only 10 concurrent resolutions done in parallel"/>
+ <suffix name="parallel_14"
+ label="with only 14 concurrent resolutions done in parallel"/>
+ <suffix name="parallel_20"
+ label="with only 20 concurrent resolutions done in parallel"/>
<suffix name="parallel_default"
label="with the default number of concurrent resolutions done in
parallel"/>
@@ -112944,7 +118356,6 @@ uploading your change for review.
<owner>calamity@chromium.org</owner>
<suffix name="0"/>
<suffix name="10"/>
- <suffix name="100"/>
<suffix name="20"/>
<suffix name="30"/>
<suffix name="40"/>
@@ -112953,6 +118364,7 @@ uploading your change for review.
<suffix name="70"/>
<suffix name="80"/>
<suffix name="90"/>
+ <suffix name="100"/>
<affected-histogram name="SiteEngagementService.EngagementScoreBucket"/>
</histogram_suffixes>
@@ -113398,6 +118810,13 @@ uploading your change for review.
<affected-histogram name="GPU.ContextMemory"/>
</histogram_suffixes>
+<histogram_suffixes name="GPU.DirectComposition.OverlayFormat" separator=".">
+ <suffix name="BGRA" label="BGRA"/>
+ <suffix name="NV12" label="NV12"/>
+ <suffix name="YUY2" label="YUY2"/>
+ <affected-histogram name="GPU.DirectComposition.OverlaySupportFlags2"/>
+</histogram_suffixes>
+
<histogram_suffixes name="GPU.MemorySamplingTime" separator=".">
<suffix name="Periodic" label="Sampled periodically."/>
<suffix name="Pressure" label="Sampled on CRITICAL memory pressure signal."/>
@@ -113423,79 +118842,79 @@ uploading your change for review.
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment10"
+ <suffix name="Experiment2"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment11"
+ <suffix name="Experiment3"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment12"
+ <suffix name="Experiment4"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment13"
+ <suffix name="Experiment5"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment14"
+ <suffix name="Experiment6"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment15"
+ <suffix name="Experiment7"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment16"
+ <suffix name="Experiment8"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment17"
+ <suffix name="Experiment9"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment18"
+ <suffix name="Experiment10"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment19"
+ <suffix name="Experiment11"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment2"
+ <suffix name="Experiment12"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment20"
+ <suffix name="Experiment13"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment3"
+ <suffix name="Experiment14"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment4"
+ <suffix name="Experiment15"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment5"
+ <suffix name="Experiment16"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment6"
+ <suffix name="Experiment17"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment7"
+ <suffix name="Experiment18"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment8"
+ <suffix name="Experiment19"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
- <suffix name="Experiment9"
+ <suffix name="Experiment20"
label="Only page loads that are a result of a navigation from a web
search under a specific web search/Chrome joint experiment.
Unused at this moment."/>
@@ -113648,13 +119067,25 @@ uploading your change for review.
<affected-histogram name="NetConnectivity.Pipeline.Success"/>
</histogram_suffixes>
+<histogram_suffixes name="HubAndSpokeNavigationUsageType" separator=".">
+ <suffix name="FromDefaultSearchEngine"
+ label="User navigates to a new page from default search engine result
+ page"/>
+ <suffix name="FromFormSubmit"
+ label="User navigates to a new page from a form submit page"/>
+ <suffix name="FromOther"
+ label="User navigates to a new page from a page other than a default
+ search engine result page or a form submit page"/>
+ <affected-histogram name="Tabs.Tasks.HubAndSpokeNavigationUsage"/>
+</histogram_suffixes>
+
<histogram_suffixes name="IdleSktToImpact" separator="_">
+ <suffix name="idle_timeout_5"
+ label="with 5-second unused idle socket timeout"/>
<suffix name="idle_timeout_10"
label="with 10-second unused idle socket timeout"/>
<suffix name="idle_timeout_20"
label="with 20-second unused idle socket timeout"/>
- <suffix name="idle_timeout_5"
- label="with 5-second unused idle socket timeout"/>
<suffix name="idle_timeout_60"
label="with 60-second unused idle socket timeout"/>
<affected-histogram name="PLT.Abandoned"/>
@@ -113782,13 +119213,13 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="InstantExtended_QuerytoQuery" separator="_">
- <suffix name="1200" label="Omnibox width &lt; 1200"/>
<obsolete>
All relevant histograms have been marked as obsolete as of Sep 2016.
</obsolete>
<owner>macourteau@chromium.org</owner>
<suffix name="400" label="Omnibox width &lt; 400"/>
<suffix name="700" label="Omnibox width &lt; 700"/>
+ <suffix name="1200" label="Omnibox width &lt; 1200"/>
<suffix name="large" label="Omnibox width &gt;= 1200"/>
<affected-histogram name="InstantExtended.PercentageMatchV2_QuerytoQuery"/>
<affected-histogram name="InstantExtended.PercentageMatchV2_QuerytoURL"/>
@@ -113797,6 +119228,9 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="InstantSearchClicks" separator="_">
+ <obsolete>
+ Deprecated as of 7/2015.
+ </obsolete>
<suffix name="NoPreview"
label="Only page loads through data reduction proxy that are result of
navigation from web search and preview version of the page shown
@@ -113805,9 +119239,6 @@ uploading your change for review.
label="Only page loads through data reduction proxy that are result of
navigation from web search and preview version of the page shown
are considered."/>
- <obsolete>
- Deprecated as of 7/2015.
- </obsolete>
<suffix name="WithPreview"
label="Only page loads through data reduction proxy that are result of
navigation from web search and preview version of the page shown
@@ -113870,10 +119301,10 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="Interval_lt_gt_20ms" separator="_">
- <suffix name="GreaterThan_20ms" label="greater than 20ms."/>
<obsolete>
Removed 11/2016.
</obsolete>
+ <suffix name="GreaterThan_20ms" label="greater than 20ms."/>
<suffix name="LessThanOrEqual_10ms" label="less than or equal to 10ms."/>
<suffix name="LessThanOrEqual_20ms"
label="more than 10ms, and less than or equal to 20ms."/>
@@ -113913,6 +119344,7 @@ uploading your change for review.
<suffix name="IPH_BadgedReadingList"
label="In product help badged reading list."/>
<suffix name="IPH_Bookmark" label="In product help bookmark."/>
+ <suffix name="IPH_BottomToolbarTip" label="In product help bottom toolbar."/>
<suffix name="IPH_ChromeHomeExpand"
label="In product help for Chrome Home shown on cold start."/>
<suffix name="IPH_ChromeHomeMenuHeader"
@@ -113968,6 +119400,8 @@ uploading your change for review.
label="In product help to access download settings from download home."/>
<suffix name="IPH_HomePageButton" label="In product help home page button."/>
<suffix name="IPH_IncognitoWindow" label="In product help incognito window."/>
+ <suffix name="IPH_LongPressToolbarTip"
+ label="In product help LongPress toolbar."/>
<suffix name="IPH_MediaDownload" label="In product help media download."/>
<suffix name="IPH_NewIncognitoTabTip"
label="In product help new incognito tab tip."/>
@@ -114009,11 +119443,11 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="JSDialogs.EngagementList" separator=".">
- <suffix name="EngagementHigher" label="site engagement &gt;= 5"/>
- <suffix name="EngagementLessThanOne" label="site engagement &lt; 1"/>
<obsolete>
Deprecated 2017-10.
</obsolete>
+ <suffix name="EngagementHigher" label="site engagement &gt;= 5"/>
+ <suffix name="EngagementLessThanOne" label="site engagement &lt; 1"/>
<suffix name="EngagementNone" label="site engagement = 0"/>
<suffix name="EngagementOneToFive" label="site engagement &gt;= 1, &lt; 5"/>
<affected-histogram name="JSDialogs.CharacterCount"/>
@@ -114132,12 +119566,12 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="LevelDBEnvMaxFDs" separator=".">
- <suffix name="OtherError"
- label="This histogram shows the limit when open failed for reasons
- other than exceeding the limit."/>
<obsolete>
Deprecated as of September 20, 2017.
</obsolete>
+ <suffix name="OtherError"
+ label="This histogram shows the limit when open failed for reasons
+ other than exceeding the limit."/>
<suffix name="Success"
label="This histogram shows the limit when open succeeded."/>
<suffix name="TooManyOpened"
@@ -114175,10 +119609,10 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="LevelDBEnvRetryTimes" separator="">
- <suffix name="LockFile" label="LockFile"/>
<obsolete>
Deprecated 2013-04 in favor of LevelDBEnvRetry.
</obsolete>
+ <suffix name="LockFile" label="LockFile"/>
<suffix name="Rename" label="RenameFile"/>
<affected-histogram name="LevelDBEnv.IDB.TimeTo"/>
<affected-histogram name="LevelDBEnv.TimeTo"/>
@@ -114214,6 +119648,7 @@ uploading your change for review.
<suffix name="FeatureEngagementTrackerEventStore"
label="Database for FeatureEngagementTracker events."/>
<suffix name="FeedImageDatabase" label="Databases for Feed Image Loader."/>
+ <suffix name="FeedStorageDatabase" label="Databases for Feed Storage."/>
<suffix name="GCMKeyStore" label="Databases for GCMKeyStore"/>
<suffix name="ImageManager" label="Databases for ImageManager"/>
<suffix name="OfflinePageMetadataStore"
@@ -114306,6 +119741,20 @@ uploading your change for review.
<affected-histogram name="LocalNetworkRequests.PublicPage.RouterRequests"/>
</histogram_suffixes>
+<histogram_suffixes name="LocalSiteCharacteristicsFeatures" separator=".">
+ <suffix name="AudioUsageInBackground"
+ label="A tab played some audio while it was in background."/>
+ <suffix name="FaviconUpdateInBackground"
+ label="A tab changed its favicon while it was in background."/>
+ <suffix name="NotificationsUsageInBackground"
+ label="A tab triggered a non-persistent notification while it was in
+ background."/>
+ <suffix name="TitleUpdateInBackground"
+ label="A tab changed its title while it was in background."/>
+ <affected-histogram
+ name="ResourceCoordinator.LocalDB.ObservationTimeBeforeFirstUse"/>
+</histogram_suffixes>
+
<histogram_suffixes name="LocalStorageContextOpenReasons" separator="">
<suffix name="CommitErrors" label="After too many commit errors."/>
<suffix name="InvalidVersion" label="After an invalid version was read."/>
@@ -114316,8 +119765,8 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="LocalStorageSizes" separator="">
- <suffix name="100KBTo1MB" label="DB size between 100KB and 1MB"/>
<suffix name="1MBTo5MB" label="DB size between 1MB and 5MB"/>
+ <suffix name="100KBTo1MB" label="DB size between 100KB and 1MB"/>
<suffix name="Under100KB" label="DB size under 100KB"/>
<affected-histogram name="LocalStorage.BrowserTimeToPrimeLocalStorage"/>
<affected-histogram name="LocalStorage.MojoTimeToPrimeFor"/>
@@ -114377,14 +119826,14 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="LowMemoryMargin" separator="_">
- <suffix name="0mb" label="Low memory margin set to 0MB"/>
- <suffix name="100mb" label="Low memory margin set to 100MB"/>
- <suffix name="200mb" label="Low memory margin set to 200MB"/>
- <suffix name="25mb" label="Low memory margin set to 25MB"/>
- <suffix name="50mb" label="Low memory margin set to 50MB"/>
<obsolete>
Deprecated 12/2017. The low memory margin is a per-platform constant.
</obsolete>
+ <suffix name="0mb" label="Low memory margin set to 0MB"/>
+ <suffix name="25mb" label="Low memory margin set to 25MB"/>
+ <suffix name="50mb" label="Low memory margin set to 50MB"/>
+ <suffix name="100mb" label="Low memory margin set to 100MB"/>
+ <suffix name="200mb" label="Low memory margin set to 200MB"/>
<suffix name="default" label="Low memory margin set to the system default"/>
<suffix name="off" label="Low memory notification disabled"/>
<affected-histogram name="Tabs.Discard.DiscardCount"/>
@@ -114554,12 +120003,12 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="MediaTimelineWidths" separator=".">
- <suffix name="128_255"/>
- <suffix name="256_511"/>
<suffix name="32_47"/>
<suffix name="48_79"/>
- <suffix name="512_inf"/>
<suffix name="80_127"/>
+ <suffix name="128_255"/>
+ <suffix name="256_511"/>
+ <suffix name="512_inf"/>
<affected-histogram name="Media.Timeline.DragGestureDuration"/>
<affected-histogram name="Media.Timeline.DragPercent"/>
<affected-histogram name="Media.Timeline.DragSumAbsTimeDelta"/>
@@ -114827,11 +120276,11 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="MobileFreSignInChoiceNumberOfAccounts" separator=".">
- <suffix name="ManyAccounts" label="Two or more accounts"/>
- <suffix name="OneAccount" label="One account"/>
<obsolete>
Removed from code as of 08/2016.
</obsolete>
+ <suffix name="ManyAccounts" label="Two or more accounts"/>
+ <suffix name="OneAccount" label="One account"/>
<suffix name="ZeroAccounts" label="Zero accounts"/>
<affected-histogram name="MobileFre.SignInChoice.MainIntent"/>
<affected-histogram name="MobileFre.SignInChoice.ViewIntent"/>
@@ -114933,12 +120382,12 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="NavigationPreloadOrWorkerFirst" separator="_">
- <suffix name="NavPreloadFirst"
- label="The navigation preload response arrived before the service
- worker finished preparing."/>
<obsolete>
Deprecated as of June 2017.
</obsolete>
+ <suffix name="NavPreloadFirst"
+ label="The navigation preload response arrived before the service
+ worker finished preparing."/>
<suffix name="SWStartFirst"
label="The service worker finished preparing before the navigation
preload response arrived."/>
@@ -115148,6 +120597,12 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="NetConnectivity" separator=".">
+ <suffix name="53.1K" label="1K bytes of data on port 53."/>
+ <suffix name="53.1K.NoProxy"
+ label="1K bytes of data on port 53 with no proxy."/>
+ <suffix name="53.1K.RTT" label="1K bytes of data on port 53 successfully."/>
+ <suffix name="53.1K.RTT.NoProxy"
+ label="1K bytes of data on port 53 successfully with no proxy."/>
<suffix name="53.100B" label="100 bytes of data on port 53."/>
<suffix name="53.100B.NoProxy"
label="100 bytes of data on port 53 with no proxy."/>
@@ -115155,12 +120610,25 @@ uploading your change for review.
label="100 bytes of data on port 53 successfully."/>
<suffix name="53.100B.RTT.NoProxy"
label="100 bytes of data on port 53 successfully with no proxy."/>
- <suffix name="53.1K" label="1K bytes of data on port 53."/>
- <suffix name="53.1K.NoProxy"
- label="1K bytes of data on port 53 with no proxy."/>
- <suffix name="53.1K.RTT" label="1K bytes of data on port 53 successfully."/>
- <suffix name="53.1K.RTT.NoProxy"
- label="1K bytes of data on port 53 successfully with no proxy."/>
+ <suffix name="80.1K" label="1K bytes of data on port 80."/>
+ <suffix name="80.1K.NoProxy"
+ label="1K bytes of data on port 80 with no proxy."/>
+ <suffix name="80.1K.RTT" label="1K bytes of data on port 80 successfully."/>
+ <suffix name="80.1K.RTT.NoProxy"
+ label="1K bytes of data on port 80 successfully with no proxy."/>
+ <suffix name="80.100B" label="100 bytes of data on port 80."/>
+ <suffix name="80.100B.NoProxy"
+ label="100 bytes of data on port 80 with no proxy."/>
+ <suffix name="80.100B.RTT"
+ label="100 bytes of data on port 80 successfully."/>
+ <suffix name="80.100B.RTT.NoProxy"
+ label="100 bytes of data on port 80 successfully with no proxy."/>
+ <suffix name="587.1K" label="1K bytes of data on port 587."/>
+ <suffix name="587.1K.NoProxy"
+ label="1K bytes of data on port 587 with no proxy."/>
+ <suffix name="587.1K.RTT" label="1K bytes of data on port 587 successfully."/>
+ <suffix name="587.1K.RTT.NoProxy"
+ label="1K bytes of data on port 587 successfully with no proxy."/>
<suffix name="587.100B" label="100 bytes of data on port 587."/>
<suffix name="587.100B.NoProxy"
label="100 bytes of data on port 587 with no proxy."/>
@@ -115168,19 +120636,6 @@ uploading your change for review.
label="100 bytes of data on port 587 successfully."/>
<suffix name="587.100B.RTT.NoProxy"
label="100 bytes of data on port 587 successfully with no proxy."/>
- <suffix name="587.1K" label="1K bytes of data on port 587."/>
- <suffix name="587.1K.NoProxy"
- label="1K bytes of data on port 587 with no proxy."/>
- <suffix name="587.1K.RTT" label="1K bytes of data on port 587 successfully."/>
- <suffix name="587.1K.RTT.NoProxy"
- label="1K bytes of data on port 587 successfully with no proxy."/>
- <suffix name="6121.100B" label="100 bytes of data on port 6121."/>
- <suffix name="6121.100B.NoProxy"
- label="100 bytes of data on port 6121 with no proxy."/>
- <suffix name="6121.100B.RTT"
- label="100 bytes of data on port 6121 successfully."/>
- <suffix name="6121.100B.RTT.NoProxy"
- label="100 bytes of data on port 6121 successfully with no proxy."/>
<suffix name="6121.1K" label="1K bytes of data on port 6121."/>
<suffix name="6121.1K.NoProxy"
label="1K bytes of data on port 6121 with no proxy."/>
@@ -115188,26 +120643,13 @@ uploading your change for review.
label="1K bytes of data on port 6121 successfully."/>
<suffix name="6121.1K.RTT.NoProxy"
label="1K bytes of data on port 6121 successfully with no proxy."/>
- <suffix name="80.100B" label="100 bytes of data on port 80."/>
- <suffix name="80.100B.NoProxy"
- label="100 bytes of data on port 80 with no proxy."/>
- <suffix name="80.100B.RTT"
- label="100 bytes of data on port 80 successfully."/>
- <suffix name="80.100B.RTT.NoProxy"
- label="100 bytes of data on port 80 successfully with no proxy."/>
- <suffix name="80.1K" label="1K bytes of data on port 80."/>
- <suffix name="80.1K.NoProxy"
- label="1K bytes of data on port 80 with no proxy."/>
- <suffix name="80.1K.RTT" label="1K bytes of data on port 80 successfully."/>
- <suffix name="80.1K.RTT.NoProxy"
- label="1K bytes of data on port 80 successfully with no proxy."/>
- <suffix name="8080.100B" label="100 bytes of data on port 8080."/>
- <suffix name="8080.100B.NoProxy"
- label="100 bytes of data on port 8080 with no proxy."/>
- <suffix name="8080.100B.RTT"
- label="100 bytes of data on port 8080 successfully."/>
- <suffix name="8080.100B.RTT.NoProxy"
- label="100 bytes of data on port 8080 successfully with no proxy."/>
+ <suffix name="6121.100B" label="100 bytes of data on port 6121."/>
+ <suffix name="6121.100B.NoProxy"
+ label="100 bytes of data on port 6121 with no proxy."/>
+ <suffix name="6121.100B.RTT"
+ label="100 bytes of data on port 6121 successfully."/>
+ <suffix name="6121.100B.RTT.NoProxy"
+ label="100 bytes of data on port 6121 successfully with no proxy."/>
<suffix name="8080.1K" label="1K bytes of data on port 8080."/>
<suffix name="8080.1K.NoProxy"
label="1K bytes of data on port 8080 with no proxy."/>
@@ -115215,6 +120657,13 @@ uploading your change for review.
label="1K bytes of data on port 8080 successfully."/>
<suffix name="8080.1K.RTT.NoProxy"
label="1K bytes of data on port 8080 successfully with no proxy."/>
+ <suffix name="8080.100B" label="100 bytes of data on port 8080."/>
+ <suffix name="8080.100B.NoProxy"
+ label="100 bytes of data on port 8080 with no proxy."/>
+ <suffix name="8080.100B.RTT"
+ label="100 bytes of data on port 8080 successfully."/>
+ <suffix name="8080.100B.RTT.NoProxy"
+ label="100 bytes of data on port 8080 successfully with no proxy."/>
<affected-histogram name="NetConnectivity.TCP.Status"/>
<affected-histogram name="NetConnectivity.TCP.Success"/>
<affected-histogram name="NetConnectivity.UDP.PacketLoss"/>
@@ -115224,6 +120673,14 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="NetConnectivity2" separator=".">
+ <suffix name="AcksReceivedFromFirst2Packets" label="2 packets."/>
+ <suffix name="AcksReceivedFromFirst3Packets" label="3 packets."/>
+ <suffix name="AcksReceivedFromFirst4Packets" label="4 packets."/>
+ <suffix name="AcksReceivedFromFirst5Packets" label="5 packets."/>
+ <suffix name="AcksReceivedFromFirst6Packets" label="6 packets."/>
+ <suffix name="AcksReceivedFromFirst7Packets" label="7 packets."/>
+ <suffix name="AcksReceivedFromFirst8Packets" label="8 packets."/>
+ <suffix name="AcksReceivedFromFirst9Packets" label="9 packets."/>
<suffix name="AcksReceivedFromFirst10Packets" label="10 packets."/>
<suffix name="AcksReceivedFromFirst11Packets" label="11 packets."/>
<suffix name="AcksReceivedFromFirst12Packets" label="12 packets."/>
@@ -115236,20 +120693,12 @@ uploading your change for review.
<suffix name="AcksReceivedFromFirst19Packets" label="19 packets."/>
<suffix name="AcksReceivedFromFirst20Packets" label="20 packets."/>
<suffix name="AcksReceivedFromFirst21Packets" label="21 packets."/>
- <suffix name="AcksReceivedFromFirst2Packets" label="2 packets."/>
- <suffix name="AcksReceivedFromFirst3Packets" label="3 packets."/>
- <suffix name="AcksReceivedFromFirst4Packets" label="4 packets."/>
- <suffix name="AcksReceivedFromFirst5Packets" label="5 packets."/>
- <suffix name="AcksReceivedFromFirst6Packets" label="6 packets."/>
- <suffix name="AcksReceivedFromFirst7Packets" label="7 packets."/>
- <suffix name="AcksReceivedFromFirst8Packets" label="8 packets."/>
- <suffix name="AcksReceivedFromFirst9Packets" label="9 packets."/>
<affected-histogram name="NetConnectivity.Sent21"/>
</histogram_suffixes>
<histogram_suffixes name="NetConnectivity2a" separator=".">
- <suffix name="6121.100B" label="100 bytes of data is sent on port 6121."/>
<suffix name="6121.1K" label="1K bytes of data is sent on port 6121."/>
+ <suffix name="6121.100B" label="100 bytes of data is sent on port 6121."/>
<suffix name="6121.500B" label="500 bytes of data is sent on port 6121."/>
<affected-histogram name="NetConnectivity2.Sent21.AckReceivedForNthPacket"/>
<affected-histogram name="NetConnectivity2.Sent21.GotAnAck"/>
@@ -115257,6 +120706,22 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="NetConnectivity2b" separator=".">
+ <suffix name="AcksReceivedFromFirst2Packets.6121.100B"
+ label="2 packets. 100 bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst3Packets.6121.100B"
+ label="3 packets. 100 bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst4Packets.6121.100B"
+ label="4 packets. 100 bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst5Packets.6121.100B"
+ label="5 packets. 100 bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst6Packets.6121.100B"
+ label="6 packets. 100 bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst7Packets.6121.100B"
+ label="7 packets. 100 bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst8Packets.6121.100B"
+ label="8 packets. 100 bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst9Packets.6121.100B"
+ label="9 packets. 100 bytes of data is sent on port 6121."/>
<suffix name="AcksReceivedFromFirst10Packets.6121.100B"
label="10 packets. 100 bytes of data is sent on port 6121."/>
<suffix name="AcksReceivedFromFirst11Packets.6121.100B"
@@ -115281,32 +120746,16 @@ uploading your change for review.
label="20 packets. 100 bytes of data is sent on port 6121."/>
<suffix name="AcksReceivedFromFirst21Packets.6121.100B"
label="21 packets. 100 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst2Packets.6121.100B"
- label="2 packets. 100 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst3Packets.6121.100B"
- label="3 packets. 100 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst4Packets.6121.100B"
- label="4 packets. 100 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst5Packets.6121.100B"
- label="5 packets. 100 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst6Packets.6121.100B"
- label="6 packets. 100 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst7Packets.6121.100B"
- label="7 packets. 100 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst8Packets.6121.100B"
- label="8 packets. 100 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst9Packets.6121.100B"
- label="9 packets. 100 bytes of data is sent on port 6121."/>
<affected-histogram name="NetConnectivity2.Sent21"/>
</histogram_suffixes>
<histogram_suffixes name="NetConnectivity2c" separator=".">
- <suffix name="6121.100B" label="100 bytes of data is sent on port 6121."/>
- <suffix name="6121.100B.NoProxy"
- label="100 bytes of data is sent on port 6121 with no proxy."/>
<suffix name="6121.1K" label="1K bytes of data is sent on port 6121."/>
<suffix name="6121.1K.NoProxy"
label="1K bytes of data is sent on port 6121 with no proxy."/>
+ <suffix name="6121.100B" label="100 bytes of data is sent on port 6121."/>
+ <suffix name="6121.100B.NoProxy"
+ label="100 bytes of data is sent on port 6121 with no proxy."/>
<suffix name="6121.500B" label="500 bytes of data is sent on port 6121."/>
<suffix name="6121.500B.NoProxy"
label="500 bytes of data is sent on port 6121 with no proxy."/>
@@ -115315,6 +120764,22 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="NetConnectivity2d" separator=".">
+ <suffix name="AcksReceivedFromFirst2Packets.6121.500B"
+ label="2 packets. 500 bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst3Packets.6121.500B"
+ label="3 packets. 500 bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst4Packets.6121.500B"
+ label="4 packets. 500 bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst5Packets.6121.500B"
+ label="5 packets. 500 bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst6Packets.6121.500B"
+ label="6 packets. 500 bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst7Packets.6121.500B"
+ label="7 packets. 500 bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst8Packets.6121.500B"
+ label="8 packets. 500 bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst9Packets.6121.500B"
+ label="9 packets. 500 bytes of data is sent on port 6121."/>
<suffix name="AcksReceivedFromFirst10Packets.6121.500B"
label="10 packets. 500 bytes of data is sent on port 6121."/>
<suffix name="AcksReceivedFromFirst11Packets.6121.500B"
@@ -115339,26 +120804,26 @@ uploading your change for review.
label="20 packets. 500 bytes of data is sent on port 6121."/>
<suffix name="AcksReceivedFromFirst21Packets.6121.500B"
label="21 packets. 500 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst2Packets.6121.500B"
- label="2 packets. 500 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst3Packets.6121.500B"
- label="3 packets. 500 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst4Packets.6121.500B"
- label="4 packets. 500 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst5Packets.6121.500B"
- label="5 packets. 500 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst6Packets.6121.500B"
- label="6 packets. 500 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst7Packets.6121.500B"
- label="7 packets. 500 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst8Packets.6121.500B"
- label="8 packets. 500 bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst9Packets.6121.500B"
- label="9 packets. 500 bytes of data is sent on port 6121."/>
<affected-histogram name="NetConnectivity2.Sent21"/>
</histogram_suffixes>
<histogram_suffixes name="NetConnectivity2e" separator=".">
+ <suffix name="AcksReceivedFromFirst2Packets.6121.1K"
+ label="2 packets. 1K bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst3Packets.6121.1K"
+ label="3 packets. 1K bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst4Packets.6121.1K"
+ label="4 packets. 1K bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst5Packets.6121.1K"
+ label="5 packets. 1K bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst6Packets.6121.1K"
+ label="6 packets. 1K bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst7Packets.6121.1K"
+ label="7 packets. 1K bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst8Packets.6121.1K"
+ label="8 packets. 1K bytes of data is sent on port 6121."/>
+ <suffix name="AcksReceivedFromFirst9Packets.6121.1K"
+ label="9 packets. 1K bytes of data is sent on port 6121."/>
<suffix name="AcksReceivedFromFirst10Packets.6121.1K"
label="10 packets. 1K bytes of data is sent on port 6121."/>
<suffix name="AcksReceivedFromFirst11Packets.6121.1K"
@@ -115383,22 +120848,6 @@ uploading your change for review.
label="20 packets. 1K bytes of data is sent on port 6121."/>
<suffix name="AcksReceivedFromFirst21Packets.6121.1K"
label="21 packets. 1K bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst2Packets.6121.1K"
- label="2 packets. 1K bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst3Packets.6121.1K"
- label="3 packets. 1K bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst4Packets.6121.1K"
- label="4 packets. 1K bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst5Packets.6121.1K"
- label="5 packets. 1K bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst6Packets.6121.1K"
- label="6 packets. 1K bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst7Packets.6121.1K"
- label="7 packets. 1K bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst8Packets.6121.1K"
- label="8 packets. 1K bytes of data is sent on port 6121."/>
- <suffix name="AcksReceivedFromFirst9Packets.6121.1K"
- label="9 packets. 1K bytes of data is sent on port 6121."/>
<affected-histogram name="NetConnectivity2.Sent21"/>
</histogram_suffixes>
@@ -115493,16 +120942,16 @@ uploading your change for review.
<histogram_suffixes name="NetConnectivity3PacketDelay2" separator=".">
<suffix name="443.100B.PacketDelay"
label="100 bytes of data is sent on port 443."/>
- <suffix name="443.1200B.PacketDelay"
- label="1200 bytes of data is sent on port 443."/>
<suffix name="443.500B.PacketDelay"
label="500 bytes of data is sent on port 443."/>
+ <suffix name="443.1200B.PacketDelay"
+ label="1200 bytes of data is sent on port 443."/>
<suffix name="6121.100B.PacketDelay"
label="100 bytes of data is sent on port 6121."/>
- <suffix name="6121.1200B.PacketDelay"
- label="1200 bytes of data is sent on port 6121."/>
<suffix name="6121.500B.PacketDelay"
label="500 bytes of data is sent on port 6121."/>
+ <suffix name="6121.1200B.PacketDelay"
+ label="1200 bytes of data is sent on port 6121."/>
<affected-histogram name="NetConnectivity3.NonPacedPacket.Sent21"/>
<affected-histogram name="NetConnectivity3.PacedPacket.Sent21"/>
<affected-histogram name="NetConnectivity3.StartPacket.Sent21"/>
@@ -115546,11 +120995,11 @@ uploading your change for review.
<histogram_suffixes name="NetConnectivity3PacketsSentBytes" separator=".">
<suffix name="443.100B" label="100 bytes of data is sent on port 443."/>
- <suffix name="443.1200B" label="1200 bytes of data is sent on port 443."/>
<suffix name="443.500B" label="500 bytes of data is sent on port 443."/>
+ <suffix name="443.1200B" label="1200 bytes of data is sent on port 443."/>
<suffix name="6121.100B" label="100 bytes of data is sent on port 6121."/>
- <suffix name="6121.1200B" label="1200 bytes of data is sent on port 6121."/>
<suffix name="6121.500B" label="500 bytes of data is sent on port 6121."/>
+ <suffix name="6121.1200B" label="1200 bytes of data is sent on port 6121."/>
<affected-histogram
name="NetConnectivity3.NonPacedPacket.Sent21.AckReceivedForNthPacket"/>
<affected-histogram
@@ -115720,21 +121169,21 @@ uploading your change for review.
<suffix name="443.100B" label="100 bytes of data is sent on port 443."/>
<suffix name="443.100B.NoProxy"
label="100 bytes of data is sent on port 443 with no proxy."/>
- <suffix name="443.1200B" label="1200 bytes of data is sent on port 443."/>
- <suffix name="443.1200B.NoProxy"
- label="1200 bytes of data is sent on port 443 with no proxy."/>
<suffix name="443.500B" label="500 bytes of data is sent on port 443."/>
<suffix name="443.500B.NoProxy"
label="500 bytes of data is sent on port 443 with no proxy."/>
+ <suffix name="443.1200B" label="1200 bytes of data is sent on port 443."/>
+ <suffix name="443.1200B.NoProxy"
+ label="1200 bytes of data is sent on port 443 with no proxy."/>
<suffix name="6121.100B" label="100 bytes of data is sent on port 6121."/>
<suffix name="6121.100B.NoProxy"
label="100 bytes of data is sent on port 6121 with no proxy."/>
- <suffix name="6121.1200B" label="1200 bytes of data is sent on port 6121."/>
- <suffix name="6121.1200B.NoProxy"
- label="1200 bytes of data is sent on port 6121 with no proxy."/>
<suffix name="6121.500B" label="500 bytes of data is sent on port 6121."/>
<suffix name="6121.500B.NoProxy"
label="500 bytes of data is sent on port 6121 with no proxy."/>
+ <suffix name="6121.1200B" label="1200 bytes of data is sent on port 6121."/>
+ <suffix name="6121.1200B.NoProxy"
+ label="1200 bytes of data is sent on port 6121 with no proxy."/>
<affected-histogram name="NetConnectivity3.NonPacedPacket.Send6.SeriesAcked"/>
<affected-histogram name="NetConnectivity3.PacedPacket.Send6.SeriesAcked"/>
<affected-histogram name="NetConnectivity3.StartPacket.Send6.PacketsSent"/>
@@ -115892,12 +121341,12 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="NetConnectivity4PacketsAll" separator=".">
- <suffix name="443.100B" label="100 bytes of data is sent on port 443."/>
- <suffix name="443.1200B" label="1200 bytes of data is sent on port 443."/>
- <suffix name="443.500B" label="500 bytes of data is sent on port 443."/>
<suffix name="80.100B" label="100 bytes of data is sent on port 80."/>
- <suffix name="80.1200B" label="1200 bytes of data is sent on port 80."/>
<suffix name="80.500B" label="500 bytes of data is sent on port 80."/>
+ <suffix name="80.1200B" label="1200 bytes of data is sent on port 80."/>
+ <suffix name="443.100B" label="100 bytes of data is sent on port 443."/>
+ <suffix name="443.500B" label="500 bytes of data is sent on port 443."/>
+ <suffix name="443.1200B" label="1200 bytes of data is sent on port 443."/>
<affected-histogram name="NetConnectivity4.NATBind.Sent2.Bind.Failure"/>
<affected-histogram name="NetConnectivity4.NATBind.Sent2.Bind.Success"/>
<affected-histogram
@@ -116282,8 +121731,8 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="NetConnectivity4PacketSizeTestPort" separator=".">
- <suffix name="443" label="Packet is sent on port 443."/>
<suffix name="80" label="Packet is sent on port 80."/>
+ <suffix name="443" label="Packet is sent on port 443."/>
<affected-histogram
name="NetConnectivity4.PacketSizeTest.Connectivity.Failure"/>
<affected-histogram
@@ -116295,24 +121744,24 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="NetConnectivity4SeriesRecv" separator=".">
- <suffix name="443.100B" label="100 bytes of data is sent on port 443."/>
- <suffix name="443.100B.NoProxy"
- label="100 bytes of data is sent on port 443 with no proxy."/>
- <suffix name="443.1200B" label="1200 bytes of data is sent on port 443."/>
- <suffix name="443.1200B.NoProxy"
- label="1200 bytes of data is sent on port 443 with no proxy."/>
- <suffix name="443.500B" label="500 bytes of data is sent on port 443."/>
- <suffix name="443.500B.NoProxy"
- label="500 bytes of data is sent on port 443 with no proxy."/>
<suffix name="80.100B" label="100 bytes of data is sent on port 80."/>
<suffix name="80.100B.NoProxy"
label="100 bytes of data is sent on port 80 with no proxy."/>
- <suffix name="80.1200B" label="1200 bytes of data is sent on port 80."/>
- <suffix name="80.1200B.NoProxy"
- label="1200 bytes of data is sent on port 80 with no proxy."/>
<suffix name="80.500B" label="500 bytes of data is sent on port 80."/>
<suffix name="80.500B.NoProxy"
label="500 bytes of data is sent on port 80 with no proxy."/>
+ <suffix name="80.1200B" label="1200 bytes of data is sent on port 80."/>
+ <suffix name="80.1200B.NoProxy"
+ label="1200 bytes of data is sent on port 80 with no proxy."/>
+ <suffix name="443.100B" label="100 bytes of data is sent on port 443."/>
+ <suffix name="443.100B.NoProxy"
+ label="100 bytes of data is sent on port 443 with no proxy."/>
+ <suffix name="443.500B" label="500 bytes of data is sent on port 443."/>
+ <suffix name="443.500B.NoProxy"
+ label="500 bytes of data is sent on port 443 with no proxy."/>
+ <suffix name="443.1200B" label="1200 bytes of data is sent on port 443."/>
+ <suffix name="443.1200B.NoProxy"
+ label="1200 bytes of data is sent on port 443 with no proxy."/>
<affected-histogram name="NetConnectivity4.NonPacedPacket.First6.SeriesRecv"/>
<affected-histogram name="NetConnectivity4.PacedPacket.First6.SeriesRecv"/>
<affected-histogram name="NetConnectivity4.StartPacket.First6.SeriesRecv"/>
@@ -116415,10 +121864,10 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="NetProxyResolverExecutionTime" separator="_">
- <suffix name="UrlOver128K" label="URL length was over 128K"/>
<suffix name="UrlOver2K" label="URL length was over 2K"/>
<suffix name="UrlOver4K" label="URL length was over 4K"/>
<suffix name="UrlOver8K" label="URL length was over 8K"/>
+ <suffix name="UrlOver128K" label="URL length was over 128K"/>
<affected-histogram name="Net.ProxyResolver.ExecutionTime"/>
</histogram_suffixes>
@@ -116506,6 +121955,7 @@ uploading your change for review.
Hasn't been used for a while, as of 2016-07.
</obsolete>
</suffix>
+ <suffix name="custom_links" label="User customized links."/>
<suffix name="homepage" label="The currently set home page."/>
<!-- TODO(fhorschig): Add <obsolete> tag as soon as M-62 is rolled out. -->
@@ -116520,22 +121970,22 @@ uploading your change for review.
Hasn't been used for a while, as of 2016-07.
</obsolete>
</suffix>
- <suffix name="server10">
+ <suffix name="server8">
<obsolete>
- Has never been used.
+ Not used anymore as of 2016-07.
</obsolete>
</suffix>
- <suffix name="server11">
+ <suffix name="server9">
<obsolete>
Has never been used.
</obsolete>
</suffix>
- <suffix name="server8">
+ <suffix name="server10">
<obsolete>
- Not used anymore as of 2016-07.
+ Has never been used.
</obsolete>
</suffix>
- <suffix name="server9">
+ <suffix name="server11">
<obsolete>
Has never been used.
</obsolete>
@@ -116722,22 +122172,22 @@ uploading your change for review.
<histogram_suffixes name="NQE.Accuracy.RTT.ObservedIntervals" separator=".">
<suffix name="0_20"
label="Observed metric was between 0 and 20 (inclusive) units"/>
- <suffix name="1260_2540"
- label="Observed metric was between 1260 and 2540 (inclusive) units"/>
- <suffix name="140_300"
- label="Observed metric was between 140 and 300 (inclusive) units"/>
<suffix name="20_60"
label="Observed metric was between 20 and 60 (inclusive) units"/>
- <suffix name="2540_5100"
- label="Observed metric was between 2540 and 51000 (inclusive) units"/>
- <suffix name="300_620"
- label="Observed metric was between 300 and 620 (inclusive) units"/>
- <suffix name="5100_Infinity"
- label="Observed metric was greater than 5100 (inclusive) units"/>
<suffix name="60_140"
label="Observed metric was between 60 and 140 (inclusive) units"/>
+ <suffix name="140_300"
+ label="Observed metric was between 140 and 300 (inclusive) units"/>
+ <suffix name="300_620"
+ label="Observed metric was between 300 and 620 (inclusive) units"/>
<suffix name="620_1260"
label="Observed metric was between 620 and 1260 (inclusive) units"/>
+ <suffix name="1260_2540"
+ label="Observed metric was between 1260 and 2540 (inclusive) units"/>
+ <suffix name="2540_5100"
+ label="Observed metric was between 2540 and 51000 (inclusive) units"/>
+ <suffix name="5100_Infinity"
+ label="Observed metric was greater than 5100 (inclusive) units"/>
<affected-histogram
name="NQE.Accuracy.DownstreamThroughputKbps.EstimatedObservedDiff.Negative.15"/>
<affected-histogram
@@ -116861,16 +122311,16 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="NQE.DifferentPercentiles" separator=".">
+ <obsolete>
+ Deprecated 01/2018.
+ </obsolete>
<suffix name="Percentile0" label="0th percentile"/>
<suffix name="Percentile10" label="10th percentile"/>
- <suffix name="Percentile100" label="100th percentile"/>
<suffix name="Percentile50" label="50th percentile"/>
<suffix name="Percentile90" label="90th percentile"/>
+ <suffix name="Percentile100" label="100th percentile"/>
<affected-histogram name="NQE.RTT"/>
<affected-histogram name="NQE.TransportRTT"/>
- <obsolete>
- Deprecated 01/2018.
- </obsolete>
</histogram_suffixes>
<histogram_suffixes name="NQE.DifferentPercentiles" separator=".">
@@ -116992,6 +122442,10 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="NumLayersBucket" separator=".">
+ <obsolete>
+ Deprecated 2018-07 as the non bucketed metrics are enough for future
+ reference.
+ </obsolete>
<suffix name="0" label="Layer count bucket [0, 10)"/>
<suffix name="1" label="Layer count bucket [10, 30)"/>
<suffix name="2" label="Layer count bucket [30, 70)"/>
@@ -117243,6 +122697,10 @@ uploading your change for review.
</obsolete>
</affected-histogram>
<affected-histogram
+ name="PageLoad.Clients.ServiceWorker2.PaintTiming.NavigationToFirstContentfulPaint"/>
+ <affected-histogram
+ name="PageLoad.Clients.ServiceWorker2.ParseTiming.NavigationToParseStart"/>
+ <affected-histogram
name="PageLoad.DocumentTiming.NavigationToDOMContentLoadedEventFired"/>
<affected-histogram name="PageLoad.DocumentTiming.NavigationToFirstLayout"/>
<affected-histogram
@@ -117358,6 +122816,10 @@ uploading your change for review.
<affected-histogram
name="PageLoad.Clients.ServiceWorker.ParseTiming.NavigationToParseStart.LoadType.ForwardBackNavigation"/>
<affected-histogram
+ name="PageLoad.Clients.ServiceWorker2.PaintTiming.NavigationToFirstContentfulPaint.LoadType.ForwardBackNavigation"/>
+ <affected-histogram
+ name="PageLoad.Clients.ServiceWorker2.ParseTiming.NavigationToParseStart.LoadType.ForwardBackNavigation"/>
+ <affected-histogram
name="PageLoad.PaintTiming.NavigationToFirstContentfulPaint"/>
<affected-histogram
name="PageLoad.PaintTiming.NavigationToFirstContentfulPaint.LoadType.ForwardBackNavigation"/>
@@ -117730,12 +123192,12 @@ uploading your change for review.
Renamed to Clients.Protocol.H11
</obsolete>
</suffix>
- <suffix name="Clients.Protocol.H11"
- label="PageLoadMetrics that are a result of a navigation to main
- resource over HTTP/1.1"/>
<suffix name="Clients.Protocol.H2"
label="PageLoadMetrics that are a result of a navigation to main
resource over HTTP/2"/>
+ <suffix name="Clients.Protocol.H11"
+ label="PageLoadMetrics that are a result of a navigation to main
+ resource over HTTP/1.1"/>
<suffix name="Clients.Protocol.QUIC"
label="PageLoadMetrics that are a result of a navigation to main
resource over QUIC"/>
@@ -117793,15 +123255,48 @@ uploading your change for review.
name="PageLoad.Clients.ResourcePrefetchPredictor.PaintTiming.NavigationToFirstContentfulPaint"/>
</histogram_suffixes>
+<histogram_suffixes name="PageLoadMetricsClientsScheme" separator="."
+ ordering="prefix">
+ <suffix name="Clients.Scheme.HTTP"
+ label="PageLoadMetrics that are a result of a navigation to a main
+ resource where the committed URL is HTTP."/>
+ <suffix name="Clients.Scheme.HTTPS"
+ label="PageLoadMetrics that are a result of a navigation to a main
+ resource where the committed URL is HTTPS."/>
+ <affected-histogram
+ name="PageLoad.Experimental.PaintTiming.NavigationToFirstMeaningfulPaint"/>
+ <affected-histogram
+ name="PageLoad.PaintTiming.NavigationToFirstContentfulPaint"/>
+ <affected-histogram name="PageLoad.ParseTiming.NavigationToParseStart"/>
+</histogram_suffixes>
+
<histogram_suffixes name="PageLoadMetricsClientsServiceWorker" separator="."
ordering="prefix">
<suffix name="Clients.NoServiceWorker"
label="PageLoadMetrics from a page that is not controlled by a Service
Worker. This is intended to understand the performance impact of
- service workers on special apps using Clients.ServiceWorker"/>
+ service workers on special apps using Clients.ServiceWorker">
+ <obsolete>
+ Deprecated on June 2018 (M69) in favor of Clients.NoServiceWorker2.
+ </obsolete>
+ </suffix>
+ <suffix name="Clients.NoServiceWorker2"
+ label="PageLoadMetrics from a page that is either not controlled by a
+ service worker or is controlled by a service worker without a
+ fetch event handler. This should NOT be compared to
+ Clients.ServiceWorker2, see https://goo.gl/EdaGQn.">
+
+ </suffix>
<suffix name="Clients.ServiceWorker"
label="PageLoadMetrics from a page that is controlled by a Service
- Worker"/>
+ Worker.">
+ <obsolete>
+ Deprecated on June 2018 (M69) in favor of Clients.ServiceWorker2.
+ </obsolete>
+ </suffix>
+ <suffix name="Clients.ServiceWorker2"
+ label="PageLoadMetrics from a page that is controlled by a service
+ worker that has a fetch event handler."/>
<affected-histogram
name="PageLoad.DocumentTiming.NavigationToDOMContentLoadedEventFired"/>
<affected-histogram
@@ -117810,8 +123305,10 @@ uploading your change for review.
name="PageLoad.Experimental.PaintTiming.NavigationToFirstMeaningfulPaint"/>
<affected-histogram
name="PageLoad.Experimental.PaintTiming.ParseStartToFirstMeaningfulPaint"/>
+ <affected-histogram name="PageLoad.InteractiveTiming.FirstInputDelay"/>
<affected-histogram
name="PageLoad.PaintTiming.NavigationToFirstContentfulPaint"/>
+ <affected-histogram name="PageLoad.PaintTiming.NavigationToFirstPaint"/>
<affected-histogram
name="PageLoad.PaintTiming.ParseStartToFirstContentfulPaint"/>
<affected-histogram name="PageLoad.ParseTiming.NavigationToParseStart"/>
@@ -117841,6 +123338,20 @@ uploading your change for review.
name="PageLoad.Clients.ServiceWorker.PaintTiming.ParseStartToFirstContentfulPaint"/>
<affected-histogram
name="PageLoad.Clients.ServiceWorker.ParseTiming.NavigationToParseStart"/>
+ <affected-histogram
+ name="PageLoad.Clients.ServiceWorker2.DocumentTiming.NavigationToDOMContentLoadedEventFired"/>
+ <affected-histogram
+ name="PageLoad.Clients.ServiceWorker2.DocumentTiming.NavigationToLoadEventFired"/>
+ <affected-histogram
+ name="PageLoad.Clients.ServiceWorker2.Experimental.PaintTiming.NavigationToFirstMeaningfulPaint"/>
+ <affected-histogram
+ name="PageLoad.Clients.ServiceWorker2.Experimental.PaintTiming.ParseStartToFirstMeaningfulPaint"/>
+ <affected-histogram
+ name="PageLoad.Clients.ServiceWorker2.PaintTiming.NavigationToFirstContentfulPaint"/>
+ <affected-histogram
+ name="PageLoad.Clients.ServiceWorker2.PaintTiming.ParseStartToFirstContentfulPaint"/>
+ <affected-histogram
+ name="PageLoad.Clients.ServiceWorker2.ParseTiming.NavigationToParseStart"/>
</histogram_suffixes>
<histogram_suffixes name="PageLoadMetricsClientsSubresourceFilter"
@@ -117901,6 +123412,10 @@ uploading your change for review.
<affected-histogram
name="PageLoad.Clients.ServiceWorker.ParseTiming.NavigationToParseStart"/>
<affected-histogram
+ name="PageLoad.Clients.ServiceWorker2.PaintTiming.NavigationToFirstContentfulPaint"/>
+ <affected-histogram
+ name="PageLoad.Clients.ServiceWorker2.ParseTiming.NavigationToParseStart"/>
+ <affected-histogram
name="PageLoad.Clients.SubresourceFilter.ActivationDecision"/>
<affected-histogram name="PageLoad.Experimental.Bytes.Cache"/>
<affected-histogram name="PageLoad.Experimental.Bytes.Network"/>
@@ -118169,11 +123684,19 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="PasswordManagerMonitor" separator="_">
- <suffix name="" label=""/>
<obsolete>
Deprecated as of 03/2016.
</obsolete>
+ <suffix name="" label=""/>
<suffix name="group_1" label="group 1"/>
+ <suffix name="group_2" label="group 2"/>
+ <suffix name="group_3" label="group 3"/>
+ <suffix name="group_4" label="group 4"/>
+ <suffix name="group_5" label="group 5"/>
+ <suffix name="group_6" label="group 6"/>
+ <suffix name="group_7" label="group 7"/>
+ <suffix name="group_8" label="group 8"/>
+ <suffix name="group_9" label="group 9"/>
<suffix name="group_10" label="group 10"/>
<suffix name="group_11" label="group 11"/>
<suffix name="group_12" label="group 12"/>
@@ -118184,15 +123707,7 @@ uploading your change for review.
<suffix name="group_17" label="group 17"/>
<suffix name="group_18" label="group 18"/>
<suffix name="group_19" label="group 19"/>
- <suffix name="group_2" label="group 2"/>
<suffix name="group_20" label="group 20"/>
- <suffix name="group_3" label="group 3"/>
- <suffix name="group_4" label="group 4"/>
- <suffix name="group_5" label="group 5"/>
- <suffix name="group_6" label="group 6"/>
- <suffix name="group_7" label="group 7"/>
- <suffix name="group_8" label="group 8"/>
- <suffix name="group_9" label="group 9"/>
<affected-histogram name="PasswordManager.LinuxBackendStatistics"/>
<affected-histogram name="PasswordManager.ProvisionalSaveFailure"/>
<affected-histogram
@@ -118230,6 +123745,17 @@ uploading your change for review.
matches either/both the sync password or a saved password This
is a superset (and should be equal to or larger than)
SyncPasswordEntry and ProtectedPasswordEntry"/>
+ <suffix name="GSuiteSyncPasswordEntry"
+ label="Password protection triggered by entering the sync password that
+ is associated with a GSuite account. This is a subset of
+ SyncPasswordEntry. Note that GSuite sync password reuse
+ detection is only triggered if configured appropriate enterprise
+ policy."/>
+ <suffix name="NonGaiaEnterprisePasswordEntry"
+ label="Password protection triggered by entering a password that
+ matches a non-Gaia enterprise password. Note that non-Gaia
+ enterprise password reuse detection is only triggered if
+ configured appropriate enterprise policy."/>
<suffix name="PasswordFieldOnFocus"
label="Password protection triggered by password field on focus event."/>
<suffix name="ProtectedPasswordEntry"
@@ -118254,12 +123780,22 @@ uploading your change for review.
<affected-histogram
name="PasswordProtection.NumberOfCachedVerdictBeforeShutdown"/>
<affected-histogram name="PasswordProtection.PageInfoAction"/>
+ <affected-histogram name="PasswordProtection.PasswordAlertModeOutcome"/>
<affected-histogram name="PasswordProtection.RequestOutcome"/>
<affected-histogram
name="PasswordProtection.UserClickedThroughSafeBrowsingInterstitial"/>
<affected-histogram name="PasswordProtection.Verdict"/>
</histogram_suffixes>
+<histogram_suffixes name="PasswordProtectionVerdict" separator=".">
+ <suffix name="LowReputation"
+ label="Password protection reponse with low reputation verdict"/>
+ <suffix name="Phishing"
+ label="Password protection response with phishing verdict"/>
+ <suffix name="Safe" label="Password protection response with safe verdict"/>
+ <affected-histogram name="PasswordProtection.ReferrerChainSize"/>
+</histogram_suffixes>
+
<histogram_suffixes name="PasswordReuseSourceRealm" separator=".">
<suffix name="FromHttpRealm"
label="The account in question was saved on an HTTP site."/>
@@ -118669,12 +124205,12 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="Prerender" separator="_">
- <suffix name="Prerender5minTTL"
- label="prerender is enabled, and the TTL is extended to 5 minutes."/>
- <suffix name="PrerenderControl" label="prerender is disabled."/>
<obsolete>
Deprecated August 2016
</obsolete>
+ <suffix name="Prerender5minTTL"
+ label="prerender is enabled, and the TTL is extended to 5 minutes."/>
+ <suffix name="PrerenderControl" label="prerender is disabled."/>
<suffix name="PrerenderEnabled" label="prerender is enabled."/>
<suffix name="PrerenderMatchComplete"
label="prerender is enabled, and match complete replacements are used
@@ -118721,35 +124257,35 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="PrerenderHoverType" separator="_" ordering="prefix">
+ <obsolete>
+ deprecated May 10 2012
+ </obsolete>
+ <suffix name="HoverStats_50" label="Hover stats @ threshold 50 ms."/>
+ <suffix name="HoverStats_75" label="Hover stats @ threshold 75 ms."/>
<suffix name="HoverStats_100" label="Hover stats @ threshold 100 ms."/>
- <suffix name="HoverStats_1000" label="Hover stats @ threshold 1000 ms."/>
<suffix name="HoverStats_150" label="Hover stats @ threshold 150 ms."/>
- <suffix name="HoverStats_1500" label="Hover stats @ threshold 1500 ms."/>
<suffix name="HoverStats_200" label="Hover stats @ threshold 200 ms."/>
- <suffix name="HoverStats_2000" label="Hover stats @ threshold 2000 ms."/>
<suffix name="HoverStats_250" label="Hover stats @ threshold 250 ms."/>
<suffix name="HoverStats_300" label="Hover stats @ threshold 300 ms."/>
- <suffix name="HoverStats_3000" label="Hover stats @ threshold 3000 ms."/>
<suffix name="HoverStats_400" label="Hover stats @ threshold 400 ms."/>
- <suffix name="HoverStats_4000" label="Hover stats @ threshold 4000 ms."/>
- <obsolete>
- deprecated May 10 2012
- </obsolete>
- <suffix name="HoverStats_50" label="Hover stats @ threshold 50 ms."/>
<suffix name="HoverStats_500" label="Hover stats @ threshold 500 ms."/>
- <suffix name="HoverStats_5000" label="Hover stats @ threshold 5000 ms."/>
- <suffix name="HoverStats_75" label="Hover stats @ threshold 75 ms."/>
<suffix name="HoverStats_750" label="Hover stats @ threshold 750 ms."/>
+ <suffix name="HoverStats_1000" label="Hover stats @ threshold 1000 ms."/>
+ <suffix name="HoverStats_1500" label="Hover stats @ threshold 1500 ms."/>
+ <suffix name="HoverStats_2000" label="Hover stats @ threshold 2000 ms."/>
+ <suffix name="HoverStats_3000" label="Hover stats @ threshold 3000 ms."/>
+ <suffix name="HoverStats_4000" label="Hover stats @ threshold 4000 ms."/>
+ <suffix name="HoverStats_5000" label="Hover stats @ threshold 5000 ms."/>
<affected-histogram name="Prerender.Events"/>
<affected-histogram name="Prerender.TimeToClick"/>
</histogram_suffixes>
<histogram_suffixes name="PrerenderModeType" separator="_">
- <suffix name="_15MinTTL" label="PRERENDER_MODE_EXPERIMENT_15MIN_TTL_GROUP"/>
- <suffix name="_Control" label="PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP"/>
<obsolete>
Deprecated August 2016
</obsolete>
+ <suffix name="_15MinTTL" label="PRERENDER_MODE_EXPERIMENT_15MIN_TTL_GROUP"/>
+ <suffix name="_Control" label="PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP"/>
<suffix name="_Disabled" label="PRERENDER_MODE_DISABLED"/>
<suffix name="_Enabled" label="PRERENDER_MODE_EXPERIMENT_PRERENDER_GROUP"/>
<suffix name="_Multi"
@@ -118878,9 +124414,11 @@ uploading your change for review.
<histogram_suffixes name="Previews.Types" separator=".">
<suffix name="AMPRedirection" label="AMP Redirection previews"/>
<suffix name="LitePage" label="Lite page previews"/>
- <suffix name="LoFi" label="Server LoFi previews"/>
+ <suffix name="LoFi" label="LoFi previews"/>
<suffix name="NoScript" label="NoScript previews"/>
<suffix name="Offline" label="Offline previews"/>
+ <suffix name="ResourceLoadingHints"
+ label="Resource loading hints based previews"/>
<affected-histogram name="Previews.EligibilityReason"/>
<affected-histogram name="Previews.InfoBarAction"/>
<affected-histogram name="Previews.OptOut.UserOptedOut"/>
@@ -118926,6 +124464,8 @@ uploading your change for review.
label="Only counting memory used by Skia bitmap resource cache."/>
<suffix name="Sync" label="Only counting memory used by Sync storage."/>
<suffix name="V8" label="Only counting memory used by V8 javascript engine."/>
+ <suffix name="V8.AllocatedObjects"
+ label="Only counting objects allocated by V8 javascript engine."/>
<affected-histogram name="Memory.Experimental.Browser2"/>
<affected-histogram name="Memory.Experimental.Extension2"/>
<affected-histogram name="Memory.Experimental.Gpu2"/>
@@ -119039,6 +124579,12 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="ProgressiveScan" separator="_">
+ <suffix name="33Percent_4MinMax"
+ label="Progressive scan @ 33%, 4 frequency bins."/>
+ <suffix name="50Percent_4MinMax"
+ label="Progressive scan @ 50%, 4 frequency bins."/>
+ <suffix name="50Percent_8MinMax"
+ label="Progressive scan @ 50%, 8 frequency bins."/>
<suffix name="100Percent_1Min_4Max"
label="Progressive scan @ 100%, minimum 1/maximum 4 frequencies."/>
<suffix name="100Percent_1MinSeen_A"
@@ -119047,12 +124593,6 @@ uploading your change for review.
label="Progressive scan @ all previously seen frequencies (B)."/>
<suffix name="100Percent_8MinMax"
label="Progressive scan @ 100%, 8 frequency bins."/>
- <suffix name="33Percent_4MinMax"
- label="Progressive scan @ 33%, 4 frequency bins."/>
- <suffix name="50Percent_4MinMax"
- label="Progressive scan @ 50%, 4 frequency bins."/>
- <suffix name="50Percent_8MinMax"
- label="Progressive scan @ 50%, 8 frequency bins."/>
<suffix name="FullScan" label="Using WPA_supplicant to scan."/>
<affected-histogram name="Network.Shill.TimeToDrop"/>
<affected-histogram name="Network.Shill.WiFi.ScanResult"/>
@@ -119080,15 +124620,22 @@ uploading your change for review.
<affected-histogram name="Protector.StartupSettings"/>
</histogram_suffixes>
+<histogram_suffixes name="ProviderPermissionType" separator=".">
+ <suffix name="READ_HISTORY_BOOKMARKS"/>
+ <suffix name="WRITE_HISTORY_BOOKMARKS"/>
+ <affected-histogram name="Android.ChromeBrowserProvider.CallerHasPermission"/>
+ <affected-histogram name="Android.ChromeBrowserProvider.SignaturePassed"/>
+</histogram_suffixes>
+
<histogram_suffixes name="ProxyConnectionImpact" separator="_">
+ <suffix name="proxy_connections_8"
+ label="with 8 connections per proxy server"/>
<suffix name="proxy_connections_16"
label="with 16 connections per proxy server"/>
<suffix name="proxy_connections_32"
label="with 32 connections per proxy server"/>
<suffix name="proxy_connections_64"
label="with 64 connections per proxy server"/>
- <suffix name="proxy_connections_8"
- label="with 8 connections per proxy server"/>
<affected-histogram name="Net.HttpProxySocketRequestTime"/>
<affected-histogram name="Net.SocksSocketRequestTime"/>
<affected-histogram name="PLT.Abandoned"/>
@@ -119272,16 +124819,16 @@ uploading your change for review.
<histogram_suffixes name="RemotingSessionDuration" separator=".">
<suffix name="Duration0To100MilliSec"
label="remoting sessions have duration in (0, 0.1] seconds"/>
- <suffix name="Duration100MilliSecTo1Sec"
- label="remoting sessions have duration in (0.1, 1] seconds"/>
- <suffix name="Duration10To15Sec"
- label="remoting sessions have duration in (10, 15] seconds"/>
<suffix name="Duration1To3Sec"
label="remoting sessions have duration in (1, 3] seconds"/>
<suffix name="Duration3To5Sec"
label="remoting sessions have duration in (3, 5] seconds"/>
<suffix name="Duration5To10Sec"
label="remoting sessions have duration in (5, 10] seconds"/>
+ <suffix name="Duration10To15Sec"
+ label="remoting sessions have duration in (10, 15] seconds"/>
+ <suffix name="Duration100MilliSecTo1Sec"
+ label="remoting sessions have duration in (0.1, 1] seconds"/>
<affected-histogram name="Media.Remoting.SessionStopTrigger"/>
</histogram_suffixes>
@@ -119410,12 +124957,12 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="RendererMemoryTiming" separator=".">
+ <suffix name="AfterBackgrounded.5min"
+ label="Recorded 5 minutes after backgrounded."/>
<suffix name="AfterBackgrounded.10min"
label="Recorded 10 minutes after backgrounded."/>
<suffix name="AfterBackgrounded.15min"
label="Recorded 15 minutes after backgrounded."/>
- <suffix name="AfterBackgrounded.5min"
- label="Recorded 5 minutes after backgrounded."/>
<suffix name="DidFinishLoad"
label="Recorded each time DidFinishLoad is called for *any* frame
within the page."/>
@@ -119444,8 +124991,14 @@ uploading your change for review.
</obsolete>
</suffix>
<suffix name="ServiceWorkerControlledMainFrameDidFinishLoad"
- label="Recorded when DidFinishLoad is called for the main frame which
- is controlled by a service worker."/>
+ label="Recorded when DidFinishLoad is called for the main frame which is
+ controlled by a service worker.">
+ <obsolete>
+ Deprecated as of June 2018. No longer recorded. This was also being
+ recorded when the page had a controller with no fetch event, which usually
+ means the service worker was not running.
+ </obsolete>
+ </suffix>
<affected-histogram name="Memory.Experimental.Renderer.BlinkGC"/>
<affected-histogram name="Memory.Experimental.Renderer.Discardable"/>
<affected-histogram name="Memory.Experimental.Renderer.Malloc"/>
@@ -119458,6 +125011,19 @@ uploading your change for review.
<affected-histogram name="Memory.Experimental.Renderer.V8MainThreadIsolate"/>
</histogram_suffixes>
+<histogram_suffixes name="RendererScheduler.AfterNthMinuteInBackgroundSplit"
+ separator=".">
+ <suffix name="Background.AfterFifthMinute"
+ label="Time spent in tasks of a particular task type starting from the
+ sixth minute after backgrounding the renderer. The renderer is
+ expected to be mostly idle during this period."/>
+ <suffix name="Background.AfterTenthMinute"
+ label="Time spent in tasks of a particular task type starting from the
+ eleventh minute after backgrounding the renderer. The renderer
+ is expected to be mostly idle during this period."/>
+ <affected-histogram name="RendererScheduler.TaskDurationPerTaskType2"/>
+</histogram_suffixes>
+
<histogram_suffixes name="RendererScheduler.ExpectedQueueingTime.FrameSplit"
separator=".">
<suffix name="CrossOriginBackground"
@@ -119514,10 +125080,16 @@ uploading your change for review.
<suffix name="Background"
label="Main thread load when the renderer is backgrounded. This does
not include extension renderers."/>
+ <suffix name="Background.AfterFifthMinute"
+ label="Main thread load when the renderer is backgrounded for longer
+ than five minutes. This does not include extension renderers."/>
<suffix name="Background.AfterFirstMinute"
label="Main thread load when the renderer is backgrounded for longer
than one minute. Most of loading tasks are expected to complete
by then. This does not include extension renderers."/>
+ <suffix name="Background.AfterTenthMinute"
+ label="Main thread load when the renderer is backgrounded for longer
+ than ten minutes. This does not include extension renderers."/>
<suffix name="Extension" label="This only includes extension renderers"/>
<suffix name="Extension.Background"
label="Main thread load when the renderer is backgrounded. This only
@@ -119539,18 +125111,18 @@ uploading your change for review.
separator=".">
<suffix name="Background"/>
<suffix name="Foreground"/>
- <affected-histogram name="RendererScheduler.TaskCPUDurationPerThreadType"/>
- <affected-histogram name="RendererScheduler.TaskDurationPerTaskType"/>
- <affected-histogram name="RendererScheduler.TaskDurationPerThreadType"/>
+ <affected-histogram name="RendererScheduler.TaskCPUDurationPerThreadType2"/>
+ <affected-histogram name="RendererScheduler.TaskDurationPerTaskType2"/>
+ <affected-histogram name="RendererScheduler.TaskDurationPerThreadType2"/>
</histogram_suffixes>
<histogram_suffixes name="RendererScheduler.TaskCountPerTaskLength"
separator=".">
- <suffix name="LongerThan100ms"/>
- <suffix name="LongerThan150ms"/>
- <suffix name="LongerThan16ms"/>
<suffix name="LongerThan1s"/>
+ <suffix name="LongerThan16ms"/>
<suffix name="LongerThan50ms"/>
+ <suffix name="LongerThan100ms"/>
+ <suffix name="LongerThan150ms"/>
<affected-histogram name="RendererScheduler.TaskCountPerFrameType"/>
<affected-histogram name="RendererScheduler.TaskCountPerQueueType"/>
</histogram_suffixes>
@@ -119565,58 +125137,66 @@ uploading your change for review.
<histogram_suffixes name="RendererScheduler.TaskDurationPerQueueTypeSplit"
separator=".">
<suffix name="Background"
- label="Time spend in tasks of a particular type when the renderer is in
- the background."/>
+ label="Time spent in tasks of a particular queue type when the renderer
+ is in the background."/>
<suffix name="Background.AfterFifthMinute"
- label="Time spent in tasks of a particular type starting from the sixth
- minute after backgrounding the renderer. The renderer is
+ label="Time spent in tasks of a particular queue type starting from the
+ sixth minute after backgrounding the renderer. The renderer is
expected to be mostly idle during this period."/>
+ <suffix name="Background.AfterTenthMinute"
+ label="Time spent in tasks of a particular type starting from the
+ eleventh minute after backgrounding the renderer. The renderer
+ is expected to be mostly idle during this period."/>
<suffix name="Background.FifthMinute"
- label="Time spent in tasks of a particular type during the fifth minute
- after backgrounding the renderer."/>
+ label="Time spent in tasks of a particular queue type during the fifth
+ minute after backgrounding the renderer."/>
<suffix name="Background.FirstMinute"
- label="Time spent in tasks of a particular type during the first minute
- after backgrounding the renderer. A large amount of loading
- tasks are expected during this period."/>
+ label="Time spent in tasks of a particular queue type during the first
+ minute after backgrounding the renderer. A large amount of
+ loading tasks are expected during this period."/>
<suffix name="Background.FourthMinute"
- label="Time spent in tasks of a particular type during the fourth
+ label="Time spent in tasks of a particular queue type during the fourth
minute after backgrounding the renderer."/>
<suffix name="Background.KeepAlive.AfterFifthMinute"
- label="Time spent in tasks of a particular type starting from the sixth
- minute after backgrounding the renderer when keep-alive signal
- is present."/>
+ label="Time spent in tasks of a particular queue type starting from the
+ sixth minute after backgrounding the renderer when keep-alive
+ signal is present."/>
+ <suffix name="Background.KeepAlive.AfterTenthMinute"
+ label="Time spent in tasks of a particular queue type starting from the
+ eleventh minute after backgrounding the renderer when keep-alive
+ signal is present."/>
<suffix name="Background.SecondMinute"
- label="Time spent in tasks of a particular type during the second
+ label="Time spent in tasks of a particular queue type during the second
minute after backgrounding the renderer."/>
<suffix name="Background.ThirdMinute"
- label="Time spent in tasks of a particular type during the third minute
- after backgrounding the renderer."/>
+ label="Time spent in tasks of a particular queue type during the third
+ minute after backgrounding the renderer."/>
<suffix name="Foreground"
- label="Time spent in tasks of a particular type when the renderer is in
- the foreground. Please note that individual tabs in this
+ label="Time spent in tasks of a particular queue type when the renderer
+ is in the foreground. Please note that individual tabs in this
renderer can be backgrounded."/>
<suffix name="Foreground.AfterThirdMinute"
- label="Time spent in tasks of a particular type starting from the
+ label="Time spent in tasks of a particular queue type starting from the
fourth minute after foregrounding the renderer."/>
<suffix name="Foreground.FirstMinute"
- label="Time spent in tasks of a particular type during the first minute
- after foregrounding the renderer."/>
+ label="Time spent in tasks of a particular queue type during the first
+ minute after foregrounding the renderer."/>
<suffix name="Foreground.SecondMinute"
- label="Time spent in tasks of a particular type during the second
+ label="Time spent in tasks of a particular queue type during the second
minute after foregrounding the renderer."/>
<suffix name="Foreground.ThirdMinute"
- label="Time spent in tasks of a particular type during the third minute
- after foregrounding the renderer."/>
+ label="Time spent in tasks of a particular queue type during the third
+ minute after foregrounding the renderer."/>
<suffix name="Hidden"
- label="Time spent in tasks of a particular type when the renderer is
- hidden."/>
+ label="Time spent in tasks of a particular queue type when the renderer
+ is hidden."/>
<suffix name="HiddenMusic"
- label="Time spent in tasks of a particular type when the renderer is
- hidden and is playing audible sound."/>
+ label="Time spent in tasks of a particular queue type when the renderer
+ is hidden and is playing audible sound."/>
<suffix name="Visible"
- label="Time spent in tasks of a particular type when the renderer is
- visible."/>
- <affected-histogram name="RendererScheduler.TaskDurationPerQueueType2"/>
+ label="Time spent in tasks of a particular queue type when the renderer
+ is visible."/>
+ <affected-histogram name="RendererScheduler.TaskDurationPerQueueType3"/>
</histogram_suffixes>
<histogram_suffixes name="RendererScheduler.TaskDurationPerTaskTypeSplit"
@@ -119624,7 +125204,7 @@ uploading your change for review.
<suffix name="UseCaseInputHandling"/>
<suffix name="UseCaseLoading"/>
<suffix name="UseCaseNone"/>
- <affected-histogram name="RendererScheduler.TaskDurationPerTaskType"/>
+ <affected-histogram name="RendererScheduler.TaskDurationPerTaskType2"/>
</histogram_suffixes>
<histogram_suffixes name="RendererThreadType" separator=".">
@@ -119832,12 +125412,12 @@ uploading your change for review.
Deprecated 1/2016
</obsolete>
<suffix name="1Client" label="One Client in the ResourceScheduler."/>
+ <suffix name="Max5Clients"
+ label="Two to five Clients in the ResourceScheduler."/>
<suffix name="Max15Clients"
label="Six to fifteen Clients in the ResourceScheduler."/>
<suffix name="Max30Clients"
label="Sixteen to thirty Clients in the ResourceScheduler."/>
- <suffix name="Max5Clients"
- label="Two to five Clients in the ResourceScheduler."/>
<suffix name="Over30Clients"
label="Over thirty Clients in the ResourceScheduler."/>
<affected-histogram name="ResourceScheduler.ClientLoadedTime.Active"/>
@@ -119914,10 +125494,10 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="SafeBrowsing.V4Store.Metrics" separator=".">
- <suffix name="AnyIpMalware" label="(Obsolete. Was: AnyIpMalware)"/>
+ <suffix name="AnyIpMalware" label="(Obsolete, not recorded)"/>
<suffix name="CertCsdDownloadWhitelist"/>
<suffix name="ChromeExtMalware"/>
- <suffix name="ChromeFilenameClientIncident"/>
+ <suffix name="ChromeFilenameClientIncident" label="(Obsolete, not recorded)"/>
<suffix name="ChromeUrlClientIncident"/>
<suffix name="IpMalware"/>
<suffix name="UrlCsdDownloadWhitelist"/>
@@ -119927,6 +125507,7 @@ uploading your change for review.
<suffix name="UrlSoceng"/>
<suffix name="UrlSubresourceFilter"/>
<suffix name="UrlSuspiciousSite"/>
+ <suffix name="UrlSuspiciousSiteId" label="(Obsolete, UrlSuspiciousSite)"/>
<suffix name="UrlUws"/>
<affected-histogram name="SafeBrowsing.V4Database.Size"/>
<affected-histogram
@@ -120126,6 +125707,23 @@ uploading your change for review.
<affected-histogram name="SB2.MalwareInterstitialTimeTakeMeBack"/>
</histogram_suffixes>
+<histogram_suffixes name="SchedulerDarkMatterMetrics" separator=".">
+ <suffix name="Tracked"
+ label="Total duration of all tasks managed by the scheduler."/>
+ <suffix name="Untracked"
+ label="Total execution time unaccounted for by the scheduler.
+ Calculated as the difference between total thread time and the
+ sum of all tasks managed by the scheduler."/>
+ <affected-histogram name="Scheduler.Experimental.Renderer.CPUTimePerThread"/>
+</histogram_suffixes>
+
+<histogram_suffixes name="SchedulerTotalDurationHistograms" separator=".">
+ <suffix name="Negative"/>
+ <suffix name="Positive"/>
+ <affected-histogram
+ name="Scheduler.Experimental.Renderer.TotalTime.Wall.MainThread"/>
+</histogram_suffixes>
+
<histogram_suffixes name="ScreenshareLayerStats" separator=".">
<suffix name="FrameRate"
label="Frames per second sent, in fps. The value is reported when a
@@ -120271,6 +125869,8 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="SecurityLevel" separator=".">
+ <owner>cthomp@chromium.org</owner>
+ <owner>estark@chromium.org</owner>
<suffix name="DANGEROUS" label="SecurityLevel is DANGEROUS."/>
<suffix name="EV_SECURE" label="SecurityLevel is EV_SECURE."/>
<suffix name="HTTP_SHOW_WARNING" label="SecurityLevel is HTTP_SHOW_WARNING."/>
@@ -120279,7 +125879,16 @@ uploading your change for review.
<suffix name="SECURE" label="SecurityLevel is SECURE."/>
<suffix name="SECURE_WITH_POLICY_INSTALLED_CERT"
label="SecurityLevel is SECURE_WITH_POLICY_INSTALLED_CERT."/>
+ <affected-histogram name="Autofill.SaveCreditCardPrompt.Local"/>
+ <affected-histogram name="Autofill.SaveCreditCardPrompt.Upload"/>
+ <affected-histogram name="Autofill.UserHappiness.Address"/>
+ <affected-histogram name="Autofill.UserHappiness.CreditCard"/>
+ <affected-histogram name="Autofill.UserHappiness.Password"/>
+ <affected-histogram name="Autofill.UserHappiness.Unknown"/>
<affected-histogram name="Security.PageEndReason"/>
+ <affected-histogram name="Security.PageInfo.TimeOpen"/>
+ <affected-histogram name="Security.PageInfo.TimeOpen.Action"/>
+ <affected-histogram name="Security.PageInfo.TimeOpen.NoAction"/>
<affected-histogram name="Security.SiteEngagement"/>
<affected-histogram name="Security.SiteEngagementDelta"/>
<affected-histogram name="Security.TimeOnPage"/>
@@ -120380,7 +125989,21 @@ uploading your change for review.
<affected-histogram name="ServiceWorker.ActivateEventStatus"/>
</histogram_suffixes>
-<histogram_suffixes name="ServiceWorker.StartSituation" separator="_">
+<histogram_suffixes name="ServiceWorker.StartSituation2" separator=".">
+ <suffix name="DuringStartup"
+ label="The worker started up during browser startup."/>
+ <suffix name="ExistingReadyProcess"
+ label="An existing ready process was used for the worker."/>
+ <suffix name="ExistingUnreadyProcess"
+ label="An existing unready process was used for the worker."/>
+ <suffix name="NewProcess" label="A new process was created for the worker."/>
+ <affected-histogram name="ServiceWorker.StartTiming.ClockConsistency"/>
+ <affected-histogram name="ServiceWorker.StartTiming.Duration"/>
+</histogram_suffixes>
+
+<histogram_suffixes name="ServiceWorker.StartSituationDoNotUse" separator="_">
+<!-- Use ServiceWorker.StartSituation instead, which uses standard "." separator. -->
+
<suffix name="DuringStartup"
label="The worker started up during browser startup."/>
<suffix name="ExistingProcess">
@@ -120480,6 +126103,9 @@ uploading your change for review.
<histogram_suffixes name="ServiceWorkerSpecialAppsForEventDispatchingDelay"
separator=".">
+ <obsolete>
+ Removed June 2018 (M69).
+ </obsolete>
<suffix name="docs" label="Custom histogram for Google Docs and Drive"/>
<suffix name="gmail" label="Custom histogram for GMail"/>
<suffix name="inbox" label="Custom histogram for Inbox"/>
@@ -120549,6 +126175,14 @@ uploading your change for review.
<histogram_suffixes name="SessionRestoreTabCounts" separator="_">
<suffix name="1" label="1 tab present"/>
+ <suffix name="2" label="2 tabs present"/>
+ <suffix name="3" label="3 tabs present"/>
+ <suffix name="4" label="4 tabs present"/>
+ <suffix name="5" label="5 tabs present"/>
+ <suffix name="6" label="6 tabs present"/>
+ <suffix name="7" label="7 tabs present"/>
+ <suffix name="8" label="8 tabs present"/>
+ <suffix name="9" label="9 tabs present"/>
<suffix name="10" label="10 tabs present"/>
<suffix name="11" label="11 tab present"/>
<suffix name="12" label="12 tabs present"/>
@@ -120559,15 +126193,7 @@ uploading your change for review.
<suffix name="17" label="17 tabs present"/>
<suffix name="18" label="18 tabs present"/>
<suffix name="19" label="19 tabs present"/>
- <suffix name="2" label="2 tabs present"/>
<suffix name="20" label="20 tabs present"/>
- <suffix name="3" label="3 tabs present"/>
- <suffix name="4" label="4 tabs present"/>
- <suffix name="5" label="5 tabs present"/>
- <suffix name="6" label="6 tabs present"/>
- <suffix name="7" label="7 tabs present"/>
- <suffix name="8" label="8 tabs present"/>
- <suffix name="9" label="9 tabs present"/>
<affected-histogram name="SessionRestore.AllTabsLoaded"/>
<affected-histogram name="SessionRestore.FirstTabPainted"/>
<affected-histogram name="SessionRestore.ForegroundTabFirstLoaded"/>
@@ -120683,7 +126309,19 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="SigninAccountStatus" separator=".">
- <suffix name="NewAccount" label="Using a new account, in the sign-in promo."/>
+ <suffix name="NewAccount" label="Using a new account, in the sign-in promo.">
+ <obsolete>
+ Deprecated as of 2018-8.
+ </obsolete>
+ </suffix>
+ <suffix name="NewAccountExistingAccount"
+ label="Using a new account, in the sign-in promo, while Chrome knows
+ about other accounts."/>
+ <suffix name="NewAccountNoExistingAccount"
+ label="Using a new account, in the sign-in promo, while Chrome does not
+ know about other accounts."/>
+ <suffix name="NewAccountPreDice"
+ label="Using a new account on Desktop, pre-Dice."/>
<suffix name="NotDefault"
label="Using not the default account, in the sign-in promo."/>
<suffix name="WithDefault"
@@ -120785,11 +126423,11 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="SpdyCwnd" separator="_">
- <suffix name="cwnd10" label="using cwnd policy static 10"/>
- <suffix name="cwnd16" label="using cwnd policy static 16"/>
<obsolete>
Deprecated as of 07/2014.
</obsolete>
+ <suffix name="cwnd10" label="using cwnd policy static 10"/>
+ <suffix name="cwnd16" label="using cwnd policy static 16"/>
<owner>willchan@chromium.org</owner>
<suffix name="cwnd32" label="using cwnd policy static 32"/>
<suffix name="cwndDynamic" label="using dynamic cwnd policy"/>
@@ -120821,10 +126459,10 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="SpdySettingsCwnd" separator="">
- <suffix name="100K" label="where at least 100KB was transferred."/>
<suffix name="10K" label="where at least 10KB was transferred."/>
<suffix name="25K" label="where at least 25KB was transferred."/>
<suffix name="50K" label="where at least 50KB was transferred."/>
+ <suffix name="100K" label="where at least 100KB was transferred."/>
<affected-histogram name="Net.SpdySettingsCwnd"/>
</histogram_suffixes>
@@ -120887,10 +126525,10 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="SSLFalseStart" separator="_">
- <suffix name="FalseStart_disabled"/>
<obsolete>
Removed 2011-06-01.
</obsolete>
+ <suffix name="FalseStart_disabled"/>
<suffix name="FalseStart_enabled"/>
<affected-histogram name="Net.SSL_Connection_Latency"/>
<affected-histogram name="Net.SSL_Connection_Latency_2"/>
@@ -121034,7 +126672,7 @@ uploading your change for review.
<histogram_suffixes name="StunPingInternal" separator=".">
<suffix name="0ms" label="0ms between requests"/>
- <suffix name="100ms" label="100ms between requests"/>
+ <suffix name="5ms" label="5ms between requests"/>
<suffix name="10ms" label="10ms between requests"/>
<suffix name="15ms" label="15ms between requests"/>
<suffix name="20ms" label="20ms between requests"/>
@@ -121044,7 +126682,7 @@ uploading your change for review.
<suffix name="40ms" label="40ms between requests"/>
<suffix name="45ms" label="45ms between requests"/>
<suffix name="50ms" label="50ms between requests"/>
- <suffix name="5ms" label="5ms between requests"/>
+ <suffix name="100ms" label="100ms between requests"/>
<affected-histogram name="WebRTC.Stun.ResponseLatency.NoNAT"/>
<affected-histogram name="WebRTC.Stun.ResponseLatency.NonSymNAT"/>
<affected-histogram name="WebRTC.Stun.ResponseLatency.SymNAT"/>
@@ -121139,6 +126777,7 @@ uploading your change for review.
label="SYNCED_NOTIFICATION_APP_INFO"/>
<suffix name="THEME" label="THEME"/>
<suffix name="TYPED_URL" label="TYPED_URL"/>
+ <suffix name="USER_CONSENT" label="USER_CONSENT"/>
<suffix name="USER_EVENT" label="USER_EVENT"/>
<suffix name="WIFI_CREDENTIAL" label="WIFI_CREDENTIAL"/>
<affected-histogram name="Sync.ModelTypeCount"/>
@@ -121146,9 +126785,12 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="SyzygyStartupTime" separator="_">
+ <obsolete>
+ No longer logged.
+ </obsolete>
<suffix name="PreRead_0"/>
+ <suffix name="PreRead_5"/>
<suffix name="PreRead_10"/>
- <suffix name="PreRead_100"/>
<suffix name="PreRead_15"/>
<suffix name="PreRead_20"/>
<suffix name="PreRead_25"/>
@@ -121156,7 +126798,6 @@ uploading your change for review.
<suffix name="PreRead_35"/>
<suffix name="PreRead_40"/>
<suffix name="PreRead_45"/>
- <suffix name="PreRead_5"/>
<suffix name="PreRead_50"/>
<suffix name="PreRead_55"/>
<suffix name="PreRead_60"/>
@@ -121167,14 +126808,12 @@ uploading your change for review.
<suffix name="PreRead_85"/>
<suffix name="PreRead_90"/>
<suffix name="PreRead_95"/>
+ <suffix name="PreRead_100"/>
<suffix name="PreReadDisabled"/>
- <obsolete>
- No longer logged.
- </obsolete>
<suffix name="PreReadEnabled"/>
<suffix name="XP_PreRead_0"/>
+ <suffix name="XP_PreRead_5"/>
<suffix name="XP_PreRead_10"/>
- <suffix name="XP_PreRead_100"/>
<suffix name="XP_PreRead_15"/>
<suffix name="XP_PreRead_20"/>
<suffix name="XP_PreRead_25"/>
@@ -121182,7 +126821,6 @@ uploading your change for review.
<suffix name="XP_PreRead_35"/>
<suffix name="XP_PreRead_40"/>
<suffix name="XP_PreRead_45"/>
- <suffix name="XP_PreRead_5"/>
<suffix name="XP_PreRead_50"/>
<suffix name="XP_PreRead_55"/>
<suffix name="XP_PreRead_60"/>
@@ -121193,6 +126831,7 @@ uploading your change for review.
<suffix name="XP_PreRead_85"/>
<suffix name="XP_PreRead_90"/>
<suffix name="XP_PreRead_95"/>
+ <suffix name="XP_PreRead_100"/>
<suffix name="XP_PreReadDisabled"/>
<suffix name="XP_PreReadEnabled"/>
<affected-histogram name="Startup.BrowserMessageLoopStartTime"/>
@@ -121235,12 +126874,12 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="Tabs.TabUsageIntervalLength" separator="_">
- <suffix name="18000" label="5 hours"/>
<suffix name="30" label="30 seconds"/>
- <suffix name="3600" label="1 hour"/>
- <suffix name="43200" label="12 hours"/>
<suffix name="60" label="1 minute"/>
<suffix name="600" label="10 minutes"/>
+ <suffix name="3600" label="1 hour"/>
+ <suffix name="18000" label="5 hours"/>
+ <suffix name="43200" label="12 hours"/>
<affected-histogram name="Tabs.UnusedAndClosedInInterval.Count"/>
<affected-histogram name="Tabs.UnusedInInterval.Count"/>
<affected-histogram name="Tabs.UsedAndClosedInInterval.Count"/>
@@ -121437,6 +127076,13 @@ uploading your change for review.
</affected-histogram>
</histogram_suffixes>
+<histogram_suffixes name="TeamDrivesSupport" separator=".">
+ <suffix name="TeamDrives"/>
+ <affected-histogram name="Drive.DeltaFeedLoadTime"/>
+ <affected-histogram name="Drive.DirectoryFeedLoadTime"/>
+ <affected-histogram name="Drive.FullFeedLoadTime"/>
+</histogram_suffixes>
+
<histogram_suffixes name="ThreadWatcher" separator=".">
<suffix name="CACHE" label="where watched thread is CACHE BrowserThread."/>
<suffix name="DB" label="where watched thread is DB BrowserThread."/>
@@ -121517,6 +127163,9 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="TrafficStatsAmortizerBytesDirection" separator=".">
+ <obsolete>
+ Deprecated 2018/07.
+ </obsolete>
<suffix name="Rx" label="Records only received network bytes."/>
<suffix name="Tx" label="Records only transmitted network bytes."/>
<affected-histogram
@@ -121526,11 +127175,11 @@ uploading your change for review.
</histogram_suffixes>
<histogram_suffixes name="UnackedPackets" separator=".">
- <suffix name="NoUnackedPackets"
- label="The session had no outstanding unacked packets."/>
<obsolete>
Deprecated as of 08/2016.
</obsolete>
+ <suffix name="NoUnackedPackets"
+ label="The session had no outstanding unacked packets."/>
<suffix name="UnackedPackets"
label="The session had outstanding unacked packets."/>
<affected-histogram
diff --git a/chromium/tools/metrics/histograms/print_style.py b/chromium/tools/metrics/histograms/print_style.py
index f1157586e98..5a442481301 100644
--- a/chromium/tools/metrics/histograms/print_style.py
+++ b/chromium/tools/metrics/histograms/print_style.py
@@ -5,6 +5,7 @@
"""Holds the constants for pretty printing histograms.xml."""
import os
+import re
import sys
# Import the metrics/common module for pretty print xml.
@@ -66,6 +67,15 @@ TAGS_THAT_ALLOW_SINGLE_LINE = ['summary', 'int', 'owner']
LOWERCASE_NAME_FN = lambda n: n.attributes['name'].value.lower()
+
+def _NaturalSortByName(node):
+ """Sort by name, ordering numbers in the way humans expect."""
+ # See: https://blog.codinghorror.com/sorting-for-humans-natural-sort-order/
+ name = node.attributes['name'].value.lower()
+ convert = lambda text: int(text) if text.isdigit() else text
+ return [convert(c) for c in re.split('([0-9]+)', name)]
+
+
# Tags whose children we want to alphabetize. The key is the parent tag name,
# and the value is a list of pairs of tag name and key functions that maps each
# child node to the desired sort key.
@@ -75,7 +85,8 @@ TAGS_ALPHABETIZATION_RULES = {
'enum': [('int', lambda n: int(n.attributes['value'].value))],
'histogram_suffixes_list': [('histogram_suffixes', LOWERCASE_NAME_FN)],
'histogram_suffixes': [
- ('suffix', LOWERCASE_NAME_FN),
+ ('obsolete', lambda n: None),
+ ('suffix', _NaturalSortByName),
('affected-histogram', LOWERCASE_NAME_FN),
],
}
diff --git a/chromium/tools/metrics/rappor/rappor.xml b/chromium/tools/metrics/rappor/rappor.xml
index f073e63d2a0..f9b1fd5d1be 100644
--- a/chromium/tools/metrics/rappor/rappor.xml
+++ b/chromium/tools/metrics/rappor/rappor.xml
@@ -2498,22 +2498,6 @@ now we are only interested in H264, VP8 and VP9.
</summary>
</rappor-metric>
-<rappor-metric name="WebComponents.DocumentRegisterElement"
- type="ETLD_PLUS_ONE">
- <owner>kojii@chromium.org</owner>
- <summary>
- The host of a URL that used Document::RegisterElement().
- </summary>
-</rappor-metric>
-
-<rappor-metric name="WebComponents.ElementCreateShadowRoot"
- type="ETLD_PLUS_ONE">
- <owner>kojii@chromium.org</owner>
- <summary>
- The host of a URL that used Element::CreateShadowRoot().
- </summary>
-</rappor-metric>
-
<rappor-metric name="WebComponents.EventPath" type="ETLD_PLUS_ONE">
<owner>kojii@chromium.org</owner>
<summary>
diff --git a/chromium/tools/metrics/ukm/ukm.xml b/chromium/tools/metrics/ukm/ukm.xml
index cfcf8a34690..530c68d8e53 100644
--- a/chromium/tools/metrics/ukm/ukm.xml
+++ b/chromium/tools/metrics/ukm/ukm.xml
@@ -161,6 +161,129 @@ be describing additional metrics about the same event.
</metric>
</event>
+<event name="Autofill.HiddenRepresentationalFieldSkipDecision">
+ <owner>parastoog@chromium.org</owner>
+ <summary>
+ Recorded while trying to fill or preview a hidden or a representational
+ field.
+ </summary>
+ <metric name="FieldOverallType">
+ <summary>
+ Field's overall |ServerFieldType|. See |AutofillField.GetStorableType()|.
+ </summary>
+ </metric>
+ <metric name="FieldSignature">
+ <summary>
+ The signature of the field. This is the hash identifier used to denote
+ this field for query and voting purposes. See
+ components/autofill/core/common/signatures_util.cc for more details.
+ </summary>
+ </metric>
+ <metric name="FieldTypeGroup">
+ <summary>
+ Field's |FieldTypeGroup|. See |AutofillType.group()|.
+ </summary>
+ </metric>
+ <metric name="FormSignature">
+ <summary>
+ The signature of the form. This is the hash identifier used to denote this
+ form for query and voting purposes. See
+ components/autofill/core/common/signatures_util.cc for more details.
+ </summary>
+ </metric>
+ <metric name="HeuristicType">
+ <summary>
+ Field's |ServerFieldType| based on heuristics. See
+ |AutofillField.heuristic_type()|.
+ </summary>
+ </metric>
+ <metric name="HtmlFieldMode">
+ <summary>
+ Whether the field's autocomplete hint specified 'billing' or 'shipping'.
+ See |AutofillField.html_mode()|.
+ </summary>
+ </metric>
+ <metric name="HtmlFieldType">
+ <summary>
+ Field's autocomplete field type hint. See |AutofillField.html_type()|.
+ </summary>
+ </metric>
+ <metric name="IsSkipped">
+ <summary>
+ True if the field was skipped while filling or previewing the form,
+ because it was hidden or representational, but not a 'select' one.
+ </summary>
+ </metric>
+ <metric name="ServerType">
+ <summary>
+ Field's |ServerFieldType| returned by server. See
+ |AutofillField.server_type()|.
+ </summary>
+ </metric>
+</event>
+
+<event name="Autofill.RepeatedServerTypePredictionRationalized">
+ <owner>parastoog@chromium.org</owner>
+ <summary>
+ Recorded when a field type predicted by server is rationalized because of
+ repetition.
+ </summary>
+ <metric name="FieldNewOverallType">
+ <summary>
+ Field's overall |ServerFieldType| after rationalization. See
+ |AutofillField.GetStorableType()|.
+ </summary>
+ </metric>
+ <metric name="FieldOldOverallType">
+ <summary>
+ Field's overall |ServerFieldType| before rationalization. See
+ |AutofillField.GetStorableType()|.
+ </summary>
+ </metric>
+ <metric name="FieldSignature">
+ <summary>
+ The signature of the field. This is the hash identifier used to denote
+ this field for query and voting purposes. See
+ components/autofill/core/common/signatures_util.cc for more details.
+ </summary>
+ </metric>
+ <metric name="FieldTypeGroup">
+ <summary>
+ Field's |FieldTypeGroup|. See |AutofillType.group()|.
+ </summary>
+ </metric>
+ <metric name="FormSignature">
+ <summary>
+ The signature of the form. This is the hash identifier used to denote this
+ form for query and voting purposes. See
+ components/autofill/core/common/signatures_util.cc for more details.
+ </summary>
+ </metric>
+ <metric name="HeuristicType">
+ <summary>
+ Field's |ServerFieldType| based on heuristics. See
+ |AutofillField.heuristic_type()|.
+ </summary>
+ </metric>
+ <metric name="HtmlFieldMode">
+ <summary>
+ Whether the field's autocomplete hint specified 'billing' or 'shipping'.
+ See |AutofillField.html_mode()|.
+ </summary>
+ </metric>
+ <metric name="HtmlFieldType">
+ <summary>
+ Field's autocomplete field type hint. See |AutofillField.html_type()|.
+ </summary>
+ </metric>
+ <metric name="ServerType">
+ <summary>
+ Field's |ServerFieldType| returned by server. See
+ |AutofillField.server_type()|.
+ </summary>
+ </metric>
+</event>
+
<event name="Autofill.FormSubmitted">
<owner>jiahuiguo@google.com</owner>
<summary>
@@ -255,6 +378,11 @@ be describing additional metrics about the same event.
The signature of the form.
</summary>
</metric>
+ <metric name="IsForCreditCard">
+ <summary>
+ True for credit card forms, false for address/profile forms.
+ </summary>
+ </metric>
<metric name="MillisecondsSinceFormParsed">
<summary>
Time since form parse.
@@ -313,11 +441,21 @@ be describing additional metrics about the same event.
Recorded when user edits a text field. The text field may have been
autofilled.
</summary>
+ <metric name="FieldSignature">
+ <summary>
+ The signature of the field
+ </summary>
+ </metric>
<metric name="FieldTypeGroup">
<summary>
Field's |FieldTypeGroup|. See |AutofillType.group()|.
</summary>
</metric>
+ <metric name="FormSignature">
+ <summary>
+ The signature of the form.
+ </summary>
+ </metric>
<metric name="HeuristicType">
<summary>
Field's |ServerFieldType| based on heuristics. See
@@ -442,6 +580,35 @@ be describing additional metrics about the same event.
</metric>
</event>
+<event name="BloatedRenderer">
+ <owner>ulan@chromium.org</owner>
+ <summary>
+ Metrics related to a bloated renderer that is close to out-of-memory. They
+ are recorded only if the renderer process has a single page.
+ </summary>
+ <metric name="V8.Heap">
+ <summary>
+ The total physical size of V8's heap in MB.
+ </summary>
+ </metric>
+ <metric name="V8.Heap.AllocatedObjects">
+ <summary>
+ The total size of allocated on V8's heap in MB.
+ </summary>
+ </metric>
+ <metric name="V8.Heap.Limit">
+ <summary>
+ The V8 heap limit in MB.
+ </summary>
+ </metric>
+ <metric name="V8.NearV8HeapLimitHandling">
+ <summary>
+ An enum that specifies how the near V8 heap limit event was handled. See
+ blink::NearV8HeapLimitHandling for the enum elements.
+ </summary>
+ </metric>
+</event>
+
<event name="Compositor.UserInteraction">
<owner>khushalsagar@chromium.org</owner>
<summary>
@@ -508,6 +675,20 @@ be describing additional metrics about the same event.
not recorded if there was no subsequent scroll.
</summary>
</metric>
+ <metric name="EntityImpressionsCount">
+ <summary>
+ Emits an integer in the range of 0 - N that represents the number of
+ impressions of an Entity that were shown in the Bar, aggregated in Android
+ device storage for this user, starting in M-69.
+ </summary>
+ </metric>
+ <metric name="EntityOpensCount">
+ <summary>
+ Emits an integer in the range of 0 - N that represents the number of times
+ an Entity was shown in the Bar and the panel was opened, aggregated in
+ Android device storage for this user, starting in M-69.
+ </summary>
+ </metric>
<metric name="FontSize">
<summary>
Emits a value from 0-10 representing the effective font size on the
@@ -566,6 +747,13 @@ be describing additional metrics about the same event.
word, rather than in the middle 50% of the word.
</summary>
</metric>
+ <metric name="OpenCount">
+ <summary>
+ Emits an integer in the range of 0 - N that represents the total number of
+ times the user opened the panel, aggregated in Android device storage for
+ this user since M-69.
+ </summary>
+ </metric>
<metric name="OutcomeRankerDidPredict">
<summary>
Emits a 1 or 0 to indicate whether Ranker was able to make a prediction.
@@ -611,26 +799,61 @@ be describing additional metrics about the same event.
</metric>
<metric name="Previous28DayCtrPercent">
<summary>
- The CTR of the overlay panel for this user, aggregated over a previous 28
- day period, expressed as an integer between 0-99.
+ The CTR of the overlay panel for this user, aggregated in Android device
+ storage over a previous 28 day period, expressed as an integer between
+ 0-99, since M-60.
</summary>
</metric>
<metric name="Previous28DayImpressionsCount">
<summary>
- The count of views of the overlay panel for this user, aggregated over a
- previous 28 day period.
+ The count of views of the overlay panel for this user, aggregated in
+ Android device storage over a previous 28 day period, since M-60.
</summary>
</metric>
<metric name="PreviousWeekCtrPercent">
<summary>
- The CTR of the overlay panel for this user, aggregated over the previous
- week, expressed as an integer between 0-99.
+ The CTR of the overlay panel for this user, aggregated in Android device
+ storage over the previous week, expressed as an integer between 0-99,
+ since M-60.
</summary>
</metric>
<metric name="PreviousWeekImpressionsCount">
<summary>
- The count of views of the overlay panel for this user, aggregated over the
- previous week.
+ The count of views of the overlay panel for this user, aggregated in
+ Android device storage over the previous week, since M-60.
+ </summary>
+ </metric>
+ <metric name="QuickActionImpressionsCount">
+ <summary>
+ Emits an integer in the range of 0 - N that represents the total number of
+ times the user saw a quick action in the caption of the Bar, e.g. a phone
+ number to dial. Aggregated in Android device storage since M-69 for this
+ user.
+ </summary>
+ </metric>
+ <metric name="QuickActionsIgnored">
+ <summary>
+ Emits an integer in the range of 0 - N that represents the total number of
+ times the user ignored a quick action but opened the Bar instead, e.g. a
+ phone number was available but not dialed. Aggregated in Android device
+ storage starting at M-69.
+ </summary>
+ </metric>
+ <metric name="QuickActionsTaken">
+ <summary>
+ Emits an integer in the range of 0 - N that represents the total number of
+ times the user activated a quick action by tapping on a quick action shown
+ in the Bar, e.g. dialed a phone number. Aggregated in Android device
+ storage since M-69 for this user.
+ </summary>
+ </metric>
+ <metric name="QuickAnswerCount">
+ <summary>
+ Emits an integer in the range of 0 - N that represents the total number of
+ times the user saw a quick answer in the caption of the Bar. Typically
+ these quick answers represent an automatic translation of the selection.
+ Aggregated in Android device storage for all time for this user, since
+ M-57.
</summary>
</metric>
<metric name="ScreenTopDps">
@@ -639,6 +862,13 @@ be describing additional metrics about the same event.
DPs.
</summary>
</metric>
+ <metric name="TapCount">
+ <summary>
+ Emits an integer in the range of 0 - N that represents the total number of
+ taps that triggered the Bar, aggregated in Android device storage for this
+ user, since M-43.
+ </summary>
+ </metric>
<metric name="TapDurationMs">
<summary>
The duration of the tap gesture expressed as an integer in milliseconds.
@@ -769,6 +999,12 @@ be describing additional metrics about the same event.
navigation and whether the document was in the main frame. This can be used
to link subframe UKM events to the parent document.
</summary>
+ <metric name="IsCrossOriginFrame">
+ <summary>
+ Whether the document was in a cross origin iframe. This can either be 0 or
+ 1.
+ </summary>
+ </metric>
<metric name="IsMainFrame">
<summary>
Whether the document was in the main frame. This is can either be 0 or 1.
@@ -1073,6 +1309,53 @@ be describing additional metrics about the same event.
</metric>
</event>
+<event name="Layout.DisplayCutout.StateChanged">
+ <owner>beccahughes@chromium.org</owner>
+ <owner>media-dev@chromium.org</owner>
+ <summary>
+ Recorded every time the ViewportFit that is supplied by a frame changes or
+ the fullscreen state of a frame or its parent WebContents changes.
+ </summary>
+ <metric name="IsMainFrame">
+ <summary>
+ Records '1' if the frame that triggered this event is the main frame.
+ </summary>
+ </metric>
+ <metric name="SafeAreasPresent">
+ <summary>
+ Records whether each safe area was present. It will contain the first flag
+ (1) if the top safe area is present. Likewise the second for the left, the
+ third for the bottom and the forth for the right. If the safe area is
+ updated whilst we are allowed to extend into the cutout then we will use
+ the newest safe area values.
+ </summary>
+ </metric>
+ <metric name="ViewportFit.Applied">
+ <summary>
+ Contains the ViewportFit value that was applied by the WebContents. The
+ frame that is fullscreen will always propagate it's ViewportFit value.
+ This is stored as a ViewportFit enum (see display_cutout.mojom).
+ </summary>
+ </metric>
+ <metric name="ViewportFit.IgnoredReason">
+ <summary>
+ Records the reason why the ViewportFit value of this frame was not the
+ applied value. It will be '0' if the value was allowed. It will be '1' if
+ the ViewportFit value from the frame was blocked because the WebContents
+ was not fullscreen. It will be '2' flag if the ViewportFit value from the
+ frame was blocked because another frame is fullscreen.
+ </summary>
+ </metric>
+ <metric name="ViewportFit.Supplied">
+ <summary>
+ Contains the ViewportFit value that was supplied by the frame that
+ triggered the event. This is stored as a ViewportFit enum (see
+ display_cutout.mojom). It can never be kAuto as we ignore events when the
+ page is not trying to use the viewport fit API.
+ </summary>
+ </metric>
+</event>
+
<event name="LocalNetworkRequests">
<owner>uthakore@chromium.org</owner>
<owner>invernizzi@chromium.org</owner>
@@ -1170,6 +1453,33 @@ be describing additional metrics about the same event.
</metric>
</event>
+<event name="Media.Autoplay.AudioContext">
+ <owner>mlamouri@chromium.org</owner>
+ <owner>media-dev@chromium.org</owner>
+ <summary>
+ Records the AudioContext autoplay information.
+ </summary>
+ <metric name="SourceNodeStarted">
+ <summary>
+ A boolean indicating if start() was called for any source node associated
+ to the AudioContext.
+ </summary>
+ </metric>
+ <metric name="Status">
+ <summary>
+ Status of this AudioContext when the autoplay policy applies. It will
+ match the values from AudioContext::AutoplayStatus.
+ </summary>
+ </metric>
+ <metric name="UnlockType">
+ <summary>
+ How the AudioContext was unlocked if it was. It will match the values from
+ AudioContext::AutoplayUnlockType unless the AudioContext was never
+ unlocked in which case it will be equal to -1.
+ </summary>
+ </metric>
+</event>
+
<event name="Media.Autoplay.Muted.UnmuteAction">
<owner>mlamouri@chromium.org</owner>
<owner>media-dev@chromium.org</owner>
@@ -1460,6 +1770,12 @@ be describing additional metrics about the same event.
activation on the page or without a user initiated same-domain navigation.
</summary>
</metric>
+ <metric name="Duration">
+ <summary>
+ Duration in milliseconds, rounded to the most significant digit, of the
+ media being played. May be missing if the duration is unknown or infinite.
+ </summary>
+ </metric>
<metric name="HasAudio">
<summary>
Boolean value indicating the presence of audio.
@@ -1985,6 +2301,11 @@ be describing additional metrics about the same event.
Measure of memory consumed by V8.
</summary>
</metric>
+ <metric name="V8.AllocatedObjects">
+ <summary>
+ Measure of memory consumed by live objects in V8.
+ </summary>
+ </metric>
<metric name="WebCache">
<summary>
Measure of memory consumed by all resources in Blink Web Cache.
@@ -2101,6 +2422,19 @@ be describing additional metrics about the same event.
detailed explanation. In ms.
</summary>
</metric>
+ <metric name="InteractiveTiming.LongestInputDelay">
+ <summary>
+ Measures longest Input Delay, the longest duration between the hardware
+ timestamp and the start of event processing on the main thread for the
+ meaningful input per navigation. In ms.
+ </summary>
+ </metric>
+ <metric name="InteractiveTiming.LongestInputTimestamp">
+ <summary>
+ The duration between navigation start and the hardware timestamp of the
+ meaningful input with longest queuing delay per navigation. In ms.
+ </summary>
+ </metric>
<metric name="Navigation.PageTransition">
<summary>
The |ui::PageTransition| for the main frame navigation of this page load.
@@ -2201,6 +2535,21 @@ be describing additional metrics about the same event.
</metric>
</event>
+<event name="PageLoadCapping" singular="True">
+ <owner>ryansturm@chromium.org</owner>
+ <summary>
+ Metrics related to PageLoadCapping that are recorded using the same UKM IDs
+ as PageLoad.
+ </summary>
+ <metric name="FinalState">
+ <summary>
+ Set to 1 when the InfoBar was shown, but not acted upon. Set to 2 when the
+ page was paused, but not resumed. Set to 3 when the page was resumed. If
+ the InfoBar was not shown, this metrics is not recorded.
+ </summary>
+ </metric>
+</event>
+
<event name="PageLoad.FromGoogleSearch" singular="True">
<owner>bmcquade@chromium.org</owner>
<owner>mushan@chromium.org</owner>
@@ -2230,6 +2579,31 @@ be describing additional metrics about the same event.
distinguish two forms on the same site.
</summary>
</metric>
+ <metric name="Generation.GeneratedPassword">
+ <summary>
+ Records '1' if the user has generated a password on this form.
+ </summary>
+ </metric>
+ <metric name="Generation.GeneratedPasswordModified">
+ <summary>
+ Records '1' if the user has modified a generated a password on this form.
+ </summary>
+ </metric>
+ <metric name="Generation.PopupShown">
+ <summary>
+ Records a PasswordFormMetricsRecorder::PasswordGenerationPopupShown entry
+ if (and only if) a popup was shown.
+ </summary>
+ </metric>
+ <metric name="Generation.SpecPriority">
+ <summary>
+ Reports the priority of a PasswordGenerationRequirementsSpec for a
+ generated password. This can be used for debugging as a 0 means that no
+ spec was used, a 10 means that the spec came from autofill and was crowd
+ sourced, a 20 means that it was overridden per domain and a 30 means that
+ is was overridden for the form.
+ </summary>
+ </metric>
<metric name="ManagerFill.Action">
<summary>
Records for each password form (and HTTP auth), whether the password
@@ -2237,6 +2611,14 @@ be describing additional metrics about the same event.
enum ManagerAutofillEvent.
</summary>
</metric>
+ <metric name="ParsingComparison">
+ <summary>
+ Records comparison result of old and new password form parsing algorithms.
+ Metric is recorded on a password form detection. Recorded values
+ correspond to the enum
+ password_manager::PasswordFormMetricsRecorder::ParsingComparisonResult.
+ </summary>
+ </metric>
<metric name="Saving.Prompt.Interaction">
<summary>
Records how the user interacted with a saving prompt. Recorded values
@@ -2641,20 +3023,26 @@ be describing additional metrics about the same event.
</metric>
<metric name="RendererAudible">
<summary>
- Whether renderer was playing audio when this task was run. Boolean,
+ Whether renderer was playing audio when this task was completed. Boolean,
encoded as an integer (0/1).
</summary>
</metric>
<metric name="RendererBackgrounded">
<summary>
- Whether renderer was backgrounded when this task was run. Boolean, encoded
- as an integer (0/1).
+ Whether renderer was backgrounded when this task was completed. Boolean,
+ encoded as an integer (0/1).
</summary>
</metric>
<metric name="RendererHidden">
<summary>
- Whether renderer was hidden when this task was run. Boolean, encoded as an
- integer (0/1).
+ Whether renderer was hidden when this task was completed. Boolean, encoded
+ as an integer (0/1).
+ </summary>
+ </metric>
+ <metric name="SecondsSinceBackgrounded">
+ <summary>
+ Seconds since the renderer was backgrounded, recorded when the task was
+ completed. Only set if the renderer is backgrounded.
</summary>
</metric>
<metric name="TaskCPUDuration">
@@ -2674,7 +3062,7 @@ be describing additional metrics about the same event.
</metric>
<metric name="UseCase">
<summary>
- MainThreadSchedulerImpl's UseCase when this task was run. See
+ MainThreadSchedulerImpl's UseCase when this task was completed. See
blink::scheduler::UseCase for the values of this enum.
</summary>
</metric>
@@ -3121,6 +3509,13 @@ be describing additional metrics about the same event.
closed.
</summary>
</metric>
+ <metric name="SequenceId">
+ <summary>
+ The sequence of this event and TabManager.TabMetrics event in the current
+ session. Incremented by 1 each time one of the two events is logged to
+ provide an ordering of events.
+ </summary>
+ </metric>
<metric name="TimeFromBackgrounded">
<summary>
Duration in MS from when the tab is backgrounded to when it is brought to
@@ -3201,120 +3596,140 @@ be describing additional metrics about the same event.
</metric>
<metric name="FailureHeuristicAudio">
<summary>
- Booling indicating that the intervention was disallowed because the origin
+ Boolean indicating that the intervention was disallowed because the origin
has historically been observed emitting audio while in the background.
</summary>
</metric>
<metric name="FailureHeuristicFavicon">
<summary>
- Booling indicating that the intervention was disallowed because the origin
+ Boolean indicating that the intervention was disallowed because the origin
has historically been observed updating its favicon while in the
background.
</summary>
</metric>
<metric name="FailureHeuristicInsufficientObservation">
<summary>
- Booling indicating that the site is still being observed locally in order
+ Boolean indicating that the site is still being observed locally in order
to determine which features are in use. In the meantime, it is protected
from this intervention.
</summary>
</metric>
<metric name="FailureHeuristicNotifications">
<summary>
- Booling indicating that the intervention was disallowed because the origin
+ Boolean indicating that the intervention was disallowed because the origin
has historically been observed making use of notifications while in the
background.
</summary>
</metric>
<metric name="FailureHeuristicTitle">
<summary>
- Booling indicating that the intervention was disallowed because the origin
+ Boolean indicating that the intervention was disallowed because the origin
has historically been observed updating its tab title while in the
background.
</summary>
</metric>
<metric name="FailureLifecyclesEnterprisePolicyOptOut">
<summary>
- Booling indicating that the browser was explicitly opted out of the
+ Boolean indicating that the browser was explicitly opted out of the
intervention via enterprise policy.
</summary>
</metric>
<metric name="FailureLifecyclesFeaturePolicyOptOut">
<summary>
- Booling indicating that the tab explicitly opted out of the intervention
+ Boolean indicating that the tab explicitly opted out of the intervention
via feature policy.
</summary>
</metric>
<metric name="FailureLiveStateCapturing">
<summary>
- Booling indicating that the intervention was disallowed because the tab is
+ Boolean indicating that the intervention was disallowed because the tab is
currently capturing user media (making use of webcam or microphone, for
example).
</summary>
</metric>
+ <metric name="FailureLiveStateDesktopCapture">
+ <summary>
+ Boolean indicating that the intervention was disallowed because the tab is
+ currently capturing a window or screen.
+ </summary>
+ </metric>
+ <metric name="FailureLiveStateDevToolsOpen">
+ <summary>
+ Boolean indicating that the intervention was disallowed because the tab is
+ currently using DevTools.
+ </summary>
+ </metric>
<metric name="FailureLiveStateExtensionDisallowed">
<summary>
- Booling indicating that the intervention was disallowed by an extension.
+ Boolean indicating that the intervention was disallowed by an extension.
</summary>
</metric>
<metric name="FailureLiveStateFormEntry">
<summary>
- Booling indicating that the intervention was disallowed because the tab
+ Boolean indicating that the intervention was disallowed because the tab
currently contains text form entry.
</summary>
</metric>
<metric name="FailureLiveStateIsPDF">
<summary>
- Booling indicating that the intervention was disallowed because the tab is
+ Boolean indicating that the intervention was disallowed because the tab is
currently hosting a PDF.
</summary>
</metric>
<metric name="FailureLiveStateMirroring">
<summary>
- Booling indicating that the intervention was disallowed because the tab is
+ Boolean indicating that the intervention was disallowed because the tab is
currently being mirrored (casting its contents, for example).
</summary>
</metric>
<metric name="FailureLiveStatePlayingAudio">
<summary>
- Booling indicating that the intervention was disallowed because the tab is
+ Boolean indicating that the intervention was disallowed because the tab is
currently playing audio.
</summary>
</metric>
+ <metric name="FailureLiveStateSharingBrowsingInstance">
+ <summary>
+ Boolean indicating that the intervention was disallowed because the tab is
+ sharing its BrowsingInstance with at least one other tab.
+ </summary>
+ </metric>
<metric name="FailureLiveStateUsingWebSockets">
<summary>
- Booling indicating that the intervention was disallowed because the tab is
+ Boolean indicating that the intervention was disallowed because the tab is
currently using WebSockets.
</summary>
</metric>
<metric name="FailureLiveStateUsingWebUSB">
<summary>
- Booling indicating that the intervention was disallowed because the tab is
+ Boolean indicating that the intervention was disallowed because the tab is
currently using WebUSB.
</summary>
</metric>
<metric name="FailureLiveStateVisible">
<summary>
- Booling indicating that the intervention was disallowed because the tab is
+ Boolean indicating that the intervention was disallowed because the tab is
currently visible.
</summary>
</metric>
<metric name="LifecycleStateChangeReason">
<summary>
The reason the lifecycle state change was attempted. This corresponds to
- the LifecycleStateChangeReason enumeration in lifecycle_state.h.
+ the LifecycleStateChangeReason enumeration in lifecycle_unit_state.mojom.
</summary>
</metric>
<metric name="NewLifecycleState">
<summary>
The lifecycle state the tab will be in after the state change. Corresponds
- to a value from the LifecycleState enum defined in lifecycle_state.h.
+ to a value from the LifecycleUnitState enum defined in
+ lifecycle_unit_state.mojom.
</summary>
</metric>
<metric name="OldLifecycleState">
<summary>
The lifecycle state the tab was in prior to the state change. Corresponds
- to a value from the LifecycleState enum defined in lifecycle_state.h.
+ to a value from the LifecycleUnitState enum defined in
+ lifecycle_unit_state.mojom.
</summary>
</metric>
<metric name="Outcome">
@@ -3328,19 +3743,19 @@ be describing additional metrics about the same event.
</metric>
<metric name="SuccessGlobalWhitelist">
<summary>
- Booling indicating that the tab was explicitly opted in to the
+ Boolean indicating that the tab was explicitly opted in to the
intervention via the global whitelist.
</summary>
</metric>
<metric name="SuccessHeuristic">
<summary>
- Booling indicating that the tab was deemed safe for the intervention via
+ Boolean indicating that the tab was deemed safe for the intervention via
local observations and heuristics.
</summary>
</metric>
<metric name="SuccessLifecyclesFeaturePolicyOptIn">
<summary>
- Booling indicating that the tab explicitly opted in to the intervention
+ Boolean indicating that the tab explicitly opted in to the intervention
via feature policy.
</summary>
</metric>
@@ -3579,6 +3994,13 @@ be describing additional metrics about the same event.
</metric>
</event>
+<event name="TrustedWebActivity.Open" singular="True">
+ <owner>peconn@chromium.org</owner>
+ <summary>
+ Collected when a page is opened in a Trusted Web Activity.
+ </summary>
+</event>
+
<event name="UserActivity">
<owner>jiameng@chromium.org</owner>
<summary>
@@ -3651,6 +4073,26 @@ be describing additional metrics about the same event.
Last user activity time as hours since midnight in the local time zone.
</summary>
</metric>
+ <metric name="ModelApplied">
+ <summary>
+ A boolean value whether model prediction is applied in the screen-dim
+ decision. False means powerd dims the screen regardless of the model
+ prediction.
+ </summary>
+ </metric>
+ <metric name="ModelDecisionThreshold">
+ <summary>
+ A threhold in the range of [0, 100]. Higher threshold makes screen-dim
+ less likely.
+ </summary>
+ </metric>
+ <metric name="ModelInactivityScore">
+ <summary>
+ Probability that user will remain inactive as predicted by the model. It
+ is in the range of [0, 100]. If score is less than the decision threshold,
+ dim will be deferred.
+ </summary>
+ </metric>
<metric name="MouseEventsInLastHour">
<summary>
The number of mouse events reported as user activity in the last hour.
@@ -3665,6 +4107,16 @@ be describing additional metrics about the same event.
power.
</summary>
</metric>
+ <metric name="PreviousNegativeActionsCount">
+ <summary>
+ Number of times user reactivated, not including the current event.
+ </summary>
+ </metric>
+ <metric name="PreviousPositiveActionsCount">
+ <summary>
+ Number of times user has remained idle, not including the current event.
+ </summary>
+ </metric>
<metric name="RecentTimeActive">
<summary>
Duration of activity in seconds up to last activity.
@@ -3882,8 +4334,9 @@ be describing additional metrics about the same event.
</metric>
<metric name="SequenceId">
<summary>
- The sequence of this event in the current session. Incremented by 1 each
- time this event is logged to provide an ordering of events.
+ The sequence of this event and TabManager.ForegroundedOrClosed event in
+ the current session. Incremented by 1 each time one of the two events is
+ logged to provide an ordering of events.
</summary>
</metric>
<metric name="SiteEngagementScore">
@@ -4033,4 +4486,17 @@ be describing additional metrics about the same event.
</metric>
</event>
+<event name="VirtualKeyboard.Open">
+ <owner>shend@chromium.org</owner>
+ <summary>
+ Collects the used input types with the Virtual Keyboard.
+ </summary>
+ <metric name="TextInputType">
+ <summary>
+ Type of a input field which the user is trying to use the Virtual Keyboard
+ on.
+ </summary>
+ </metric>
+</event>
+
</ukm-configuration>
diff --git a/chromium/tools/perf/clear_system_cache/BUILD.gn b/chromium/tools/perf/clear_system_cache/BUILD.gn
index f3d1c386b30..dd4db916480 100644
--- a/chromium/tools/perf/clear_system_cache/BUILD.gn
+++ b/chromium/tools/perf/clear_system_cache/BUILD.gn
@@ -12,7 +12,6 @@ executable("clear_system_cache") {
deps = [
"//base",
"//base/test:test_support",
- "//build/config:exe_and_shlib_deps",
"//build/win:default_exe_manifest",
]
}
diff --git a/chromium/tools/perf/contrib/vr_benchmarks/BUILD.gn b/chromium/tools/perf/contrib/vr_benchmarks/BUILD.gn
index ade4ad89865..b37cf2bc5e2 100644
--- a/chromium/tools/perf/contrib/vr_benchmarks/BUILD.gn
+++ b/chromium/tools/perf/contrib/vr_benchmarks/BUILD.gn
@@ -22,8 +22,8 @@ group("vr_perf_tests") {
"//chrome/android/shared_preference_files/test/",
"//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk",
"//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk",
- "//chrome/test/data/vr/webvr_info/samples/",
- "//chrome/test/data/vr/webxr_samples/",
+ "//chrome/test/data/xr/webvr_info/samples/",
+ "//chrome/test/data/xr/webxr_samples/",
# Necessary for running on bots
"//testing/scripts/common.py",
diff --git a/chromium/tools/polymer/generate_compiled_resources_gyp.py b/chromium/tools/polymer/generate_compiled_resources_gyp.py
deleted file mode 100755
index 2aa86a21dd1..00000000000
--- a/chromium/tools/polymer/generate_compiled_resources_gyp.py
+++ /dev/null
@@ -1,97 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-from bs4 import BeautifulSoup
-from datetime import date
-import os.path as path
-import sys
-
-
-_SRC = path.join(path.dirname(path.abspath(__file__)), "..", "..")
-_COMPILE_JS = path.join(
- _SRC, "third_party", "closure_compiler", "compile_js2.gypi")
-_POLYMERS = ["polymer%s.html" % p for p in "", "-mini", "-micro"]
-_WEB_ANIMATIONS_BASE = "web-animations.html"
-_WEB_ANIMATIONS_TARGET = "<(EXTERNS_GYP):web_animations"
-_COMPILED_RESOURCES_TEMPLATE = """
-# Copyright %d The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-#
-# NOTE: Created with %s, please do not edit.
-{
- 'targets': [
- %s
- ],
-}
-""".strip()
-
-
-def main(created_by, html_files):
- targets = ""
-
- def _html_to_extracted(html_file):
- assert html_file.endswith(".html")
- return html_file[:-len(".html")] + "-extracted"
-
- def _target_name(target_file):
- return _html_to_extracted(path.basename(target_file))
-
- def _has_extracted_js(html_file):
- return path.isfile(_html_to_extracted(html_file) + ".js")
-
- html_files = filter(_has_extracted_js, html_files)
-
- for html_file in sorted(html_files, key=_target_name):
- html_base = path.basename(html_file)
- if html_base in _POLYMERS:
- continue
-
- parsed = BeautifulSoup(open(html_file), "html.parser")
- imports = set(i.get("href") for i in parsed.find_all("link", rel="import"))
-
- html_dir = path.dirname(html_file)
- dependencies = []
-
- for html_import in sorted(imports):
- import_dir, import_base = path.split(html_import.encode("ascii"))
- if import_base in _POLYMERS:
- continue
-
- if import_base == _WEB_ANIMATIONS_BASE:
- dependencies.append(_WEB_ANIMATIONS_TARGET)
- continue
-
- # Only exclude these after appending web animations externs.
- if not _has_extracted_js(path.join(html_dir, html_import)):
- continue
-
- target = _target_name(import_base)
-
- if import_dir:
- target = "compiled_resources2.gyp:" + target
-
- dependencies.append(path.join(import_dir, target))
-
- path_to_compile_js = path.relpath(_COMPILE_JS, html_dir)
-
- targets += "\n {"
- targets += "\n 'target_name': '%s-extracted'," % html_base[:-5]
- if dependencies:
- targets += "\n 'dependencies': ["
- targets += "\n '%s'," % "',\n '".join(dependencies)
- targets += "\n ],"
- targets += "\n 'includes': ['%s']," % path_to_compile_js
- targets += "\n },"
-
- targets = targets.strip()
-
- if targets:
- current_year = date.today().year
- print _COMPILED_RESOURCES_TEMPLATE % (current_year, created_by, targets)
-
-
-if __name__ == "__main__":
- main(path.basename(sys.argv[0]), sys.argv[1:])
diff --git a/chromium/tools/resources/optimize-png-files.sh b/chromium/tools/resources/optimize-png-files.sh
index 9c223929c13..d528c9e10c3 100755
--- a/chromium/tools/resources/optimize-png-files.sh
+++ b/chromium/tools/resources/optimize-png-files.sh
@@ -1,4 +1,4 @@
-#!/bin/bash -i
+#!/bin/bash
# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -409,9 +409,6 @@ Options:
2 Aggressively optimize the size of png files. This may produce
addtional 1%~5% reduction. Warning: this is *VERY*
slow and can take hours to process all files.
- -r<revision> If this is specified, the script processes only png files
- changed since this revision. The <dir> options will be used
- to narrow down the files under specific directories.
-c<commit> Same as -r but referencing a git commit. Only files changed
between this commit and HEAD will be processed.
-v Shows optimization process for each file.
@@ -419,11 +416,6 @@ Options:
exit 1
}
-if [ ! -e ../.gclient ]; then
- echo "$0 must be run in src directory"
- exit 1
-fi
-
if [ "$(expr substr $(uname -s) 1 6)" == "CYGWIN" ]; then
using_cygwin=true
else
@@ -445,19 +437,12 @@ fi
OPTIMIZE_LEVEL=1
# Parse options
-while getopts o:c:r:h:v opts
+while getopts o:c:h:v opts
do
case $opts in
c)
COMMIT=$OPTARG
;;
- r)
- COMMIT=$(git svn find-rev r$OPTARG | tail -1) || exit
- if [ -z "$COMMIT" ] ; then
- echo "Revision $OPTARG not found"
- show_help
- fi
- ;;
o)
if [[ "$OPTARG" != 0 && "$OPTARG" != 1 && "$OPTARG" != 2 ]] ; then
show_help
@@ -512,6 +497,12 @@ set ${DIRS:=$ALL_DIRS}
info "Optimize level=$OPTIMIZE_LEVEL"
if [ -n "$COMMIT" ] ; then
+ # To keep git logic below sane, require it be run from the top dir.
+ if [ ! -e ../.gclient ]; then
+ echo "$0 must be run in src directory"
+ exit 1
+ fi
+
ALL_FILES=$(git diff --name-only $COMMIT HEAD $DIRS | grep "png$")
ALL_FILES_LIST=( $ALL_FILES )
echo "Processing ${#ALL_FILES_LIST[*]} files"
diff --git a/chromium/tools/traffic_annotation/auditor/BUILD.gn b/chromium/tools/traffic_annotation/auditor/BUILD.gn
index 200ebb04157..4b50c8cade7 100644
--- a/chromium/tools/traffic_annotation/auditor/BUILD.gn
+++ b/chromium/tools/traffic_annotation/auditor/BUILD.gn
@@ -67,7 +67,7 @@ source_set("auditor_sources") {
public_deps = [
":traffic_annotation",
"//base",
- "//net:traffic_annotation",
+ "//net/traffic_annotation",
"//third_party/libxml",
"//third_party/protobuf:protobuf_full",
"//third_party/re2",
diff --git a/chromium/tools/traffic_annotation/auditor/README.md b/chromium/tools/traffic_annotation/auditor/README.md
index 8655c83469b..25653e44684 100644
--- a/chromium/tools/traffic_annotation/auditor/README.md
+++ b/chromium/tools/traffic_annotation/auditor/README.md
@@ -14,7 +14,7 @@ specified, only those directories of the source will be analyzed.
Run `traffic_annotation_auditor --help` for options.
Example:
- `traffic_annotation_auditor --build-dir=out/Debug`
+ `traffic_annotation_auditor --build-path=out/Debug`
The binaries of this file and the clang tool are checked out into
`tools/traffic_annotation/bin/[platform]`. This is only done for Linux and
diff --git a/chromium/tools/traffic_annotation/auditor/traffic_annotation_exporter.cc b/chromium/tools/traffic_annotation/auditor/traffic_annotation_exporter.cc
index 3ac5342e1b4..1dd41a45a16 100644
--- a/chromium/tools/traffic_annotation/auditor/traffic_annotation_exporter.cc
+++ b/chromium/tools/traffic_annotation/auditor/traffic_annotation_exporter.cc
@@ -77,9 +77,12 @@ TrafficAnnotationExporter::TrafficAnnotationExporter(
const base::FilePath& source_path)
: source_path_(source_path), modified_(false) {
all_supported_platforms_.push_back("linux");
+ all_supported_platforms_.push_back("mac");
all_supported_platforms_.push_back("windows");
#if defined(OS_LINUX)
current_platform_ = "linux";
+#elif defined(OS_MACOSX)
+ current_platform_ = "mac";
#elif defined(OS_WIN)
current_platform_ = "windows";
#else
@@ -469,4 +472,4 @@ bool TrafficAnnotationExporter::GetOtherPlatformsAnnotationIDs(
ids->push_back(item.first);
}
return true;
-} \ No newline at end of file
+}
diff --git a/chromium/tools/traffic_annotation/bin/README.md b/chromium/tools/traffic_annotation/bin/README.md
index 9f77b933495..dd619334b9c 100644
--- a/chromium/tools/traffic_annotation/bin/README.md
+++ b/chromium/tools/traffic_annotation/bin/README.md
@@ -73,5 +73,5 @@ and land the resulting CL.
The following two lines will be updated by the above script, and the modified
README should be committed along with the updated .sha1 checksums.
-CLANG_REVISION = '331747'
-LASTCHANGE=5ebfed4cb2784625cbcccb588dc7e7bd9c87c9eb-refs/heads/master@{#557822}
+CLANG_REVISION = '336424'
+LASTCHANGE=410d3d75c58860d371551c79045f35b7b277a183-refs/heads/master@{#574126}
diff --git a/chromium/tools/traffic_annotation/bin/win32/traffic_annotation_auditor.exe.sha1 b/chromium/tools/traffic_annotation/bin/win32/traffic_annotation_auditor.exe.sha1
index a73700d92f4..61f6b55753c 100644
--- a/chromium/tools/traffic_annotation/bin/win32/traffic_annotation_auditor.exe.sha1
+++ b/chromium/tools/traffic_annotation/bin/win32/traffic_annotation_auditor.exe.sha1
@@ -1 +1 @@
-f48a2ce2a1cd6bd86fcbca38fa107701a56530b4 \ No newline at end of file
+613a095e0c4c09228939da65fa9c72186af54545 \ No newline at end of file
diff --git a/chromium/tools/traffic_annotation/scripts/traffic_annotation_auditor_tests.py b/chromium/tools/traffic_annotation/scripts/traffic_annotation_auditor_tests.py
index 8b76f55d582..bac06ed72f8 100755
--- a/chromium/tools/traffic_annotation/scripts/traffic_annotation_auditor_tests.py
+++ b/chromium/tools/traffic_annotation/scripts/traffic_annotation_auditor_tests.py
@@ -18,6 +18,7 @@ from annotation_tools import NetworkTrafficAnnotationTools
# //tools/traffic_annotation/OWNERS.
TEST_IS_ENABLED = True
+MINIMUM_EXPECTED_NUMBER_OF_ANNOTATIONS = 260
class TrafficAnnotationTestsChecker():
def __init__(self, build_path=None):
@@ -28,6 +29,7 @@ class TrafficAnnotationTestsChecker():
directory.
"""
self.tools = NetworkTrafficAnnotationTools(build_path)
+ self.last_result = None
def RunAllTests(self):
@@ -50,25 +52,36 @@ class TrafficAnnotationTestsChecker():
["--test-only", "--no-filtering"] # Not using heuristic filtering.
]
- last_result = None
+ self.last_result = None
for config in configs:
result = self._RunTest(config)
if not result:
print("No output for config: %s" % config)
return False
- if last_result and last_result != result:
+ if self.last_result and self.last_result != result:
print("Unexpected different results for config: %s" % config)
return False
- last_result = result
+ self.last_result = result
return True
def CheckOutputExpectations(self):
- # TODO(https://crbug.com/690323): Add tests to check for an expected minimum
- # number of items for each type of pattern that auditor extracts. E.g., we
- # should have many annotations of each type (complete, partial, ...),
- # functions that need annotations, direct assignment to mutable annotations,
- # etc.
+ # This test can be replaced by getting results from a diagnostic mode call
+ # to traffic_annotation_auditor, and checking for an expected minimum number
+ # of items for each type of pattern that it extracts. E.g., we should have
+ # many annotations of each type (complete, partial, ...), functions that
+ # need annotations, direct assignment to mutable annotations, etc.
+
+ # |self.last_result| includes the content of the TSV file that the auditor
+ # generates. Counting the number of end of lines in the text will give the
+ # number of extracted annotations.
+ annotations_count = self.last_result.count("\n")
+ print("%i annotations found in auditor's output." % annotations_count)
+
+ if annotations_count < MINIMUM_EXPECTED_NUMBER_OF_ANNOTATIONS:
+ print("Annotations are expected to be at least %i." %
+ MINIMUM_EXPECTED_NUMBER_OF_ANNOTATIONS)
+ return False
return True
@@ -87,12 +100,18 @@ class TrafficAnnotationTestsChecker():
temp_file = tempfile.NamedTemporaryFile()
temp_filename = temp_file.name
temp_file.close()
+
_, stderr_text, return_code = self.tools.RunAuditor(
args + ["--annotations-file=%s" % temp_filename])
if os.path.exists(temp_filename):
- annotations = None if (return_code or stderr_text) \
- else open(temp_filename).read()
+ # When tests are run on all files (without filtering), there might be some
+ # compile errors in irrelevant files on Windows that can be ignored.
+ if (return_code and "--no-filtering" in args and
+ sys.platform.startswith(('win', 'cygwin'))):
+ print("Ignoring return code: %i" % return_code)
+ return_code = 0
+ annotations = None if return_code else open(temp_filename).read()
os.remove(temp_filename)
else:
annotations = None
diff --git a/chromium/tools/traffic_annotation/summary/annotations.xml b/chromium/tools/traffic_annotation/summary/annotations.xml
index 423126edbdc..9deb52812a9 100644
--- a/chromium/tools/traffic_annotation/summary/annotations.xml
+++ b/chromium/tools/traffic_annotation/summary/annotations.xml
@@ -17,7 +17,6 @@ Refer to README.md for content description and update process.
<item id="android_device_manager_socket" hash_code="37249086" type="0" content_hash_code="6436865" os_list="linux,windows" file_path="chrome/browser/devtools/device/android_device_manager.cc"/>
<item id="android_web_socket" hash_code="39356976" type="0" content_hash_code="12310113" os_list="linux,windows" file_path="chrome/browser/devtools/device/android_web_socket.cc"/>
<item id="appcache_update_job" hash_code="25790702" type="0" content_hash_code="27424887" os_list="linux,windows" file_path="content/browser/appcache/appcache_update_request_base.cc"/>
- <item id="asset_links" hash_code="89771989" type="0" content_hash_code="72216357" os_list="linux,windows" file_path="components/password_manager/core/browser/site_affiliation/asset_link_retriever.cc"/>
<item id="autofill_query" hash_code="88863520" type="0" content_hash_code="15563339" os_list="linux,windows" file_path="components/autofill/core/browser/autofill_download_manager.cc"/>
<item id="autofill_upload" hash_code="104798869" type="0" content_hash_code="110634763" os_list="linux,windows" file_path="components/autofill/core/browser/autofill_download_manager.cc"/>
<item id="backdrop_collection_images_download" hash_code="34767164" type="0" content_hash_code="103835921" os_list="linux,windows" file_path="chrome/browser/search/background/ntp_background_service.cc"/>
@@ -28,7 +27,7 @@ Refer to README.md for content description and update process.
<item id="blink_extension_resource_loader" hash_code="84165821" type="0" content_hash_code="3695143" os_list="linux,windows" file_path="content/renderer/loader/web_url_loader_impl.cc"/>
<item id="blink_resource_loader" hash_code="101845102" type="0" content_hash_code="75331172" os_list="linux,windows" file_path="content/renderer/loader/web_url_loader_impl.cc"/>
<item id="blob_read" hash_code="112303907" type="0" content_hash_code="135449692" os_list="linux,windows" file_path="storage/browser/blob/blob_url_request_job_factory.cc"/>
- <item id="blob_reader" hash_code="5154306" type="0" content_hash_code="39702178" os_list="linux,windows" file_path="extensions/browser/blob_reader.cc"/>
+ <item id="blob_reader" hash_code="5154306" type="0" deprecated="2018-06-14" content_hash_code="39702178" file_path=""/>
<item id="bluetooth_socket" hash_code="94099818" type="0" content_hash_code="30932349" os_list="linux,windows" file_path="device/bluetooth/bluetooth_socket_net.cc"/>
<item id="brandcode_config" hash_code="109679553" type="0" content_hash_code="128843792" os_list="linux,windows" file_path="chrome/browser/profile_resetter/brandcode_config_fetcher.cc"/>
<item id="captive_portal_service" hash_code="88754904" type="0" content_hash_code="70737580" os_list="linux,windows" file_path="chrome/browser/captive_portal/captive_portal_service.cc"/>
@@ -41,7 +40,6 @@ Refer to README.md for content description and update process.
<item id="certificate_verifier" hash_code="113553577" type="0" content_hash_code="62346354" os_list="linux,windows" file_path="net/cert_net/cert_net_fetcher_impl.cc"/>
<item id="chrome_apps_socket_api" hash_code="8591273" type="0" content_hash_code="70868355" os_list="linux,windows" file_path="extensions/browser/api/socket/socket.cc"/>
<item id="chrome_cleaner" hash_code="27071967" type="0" content_hash_code="111240292" os_list="windows" file_path="chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_fetcher_win.cc"/>
- <item id="chrome_expect_ct_reporter" hash_code="57276415" type="0" content_hash_code="137551346" os_list="linux,windows" file_path="chrome/browser/ssl/chrome_expect_ct_reporter.cc"/>
<item id="chrome_feedback_report_app" hash_code="134729048" type="0" content_hash_code="73916972" os_list="linux,windows" file_path="components/feedback/feedback_uploader.cc"/>
<item id="chrome_variations_service" hash_code="115188287" type="0" content_hash_code="32485683" os_list="linux,windows" file_path="components/variations/service/variations_service.cc"/>
<item id="client_download_request" hash_code="125522256" type="0" content_hash_code="23897505" os_list="linux,windows" file_path="chrome/browser/safe_browsing/download_protection/check_client_download_request.cc"/>
@@ -71,12 +69,12 @@ Refer to README.md for content description and update process.
<item id="desktop_ios_promotion" hash_code="13694792" type="0" content_hash_code="19776951" os_list="windows" file_path="chrome/browser/ui/desktop_ios_promotion/sms_service.cc"/>
<item id="device_geolocation_request" hash_code="77673751" type="0" deprecated="2017-10-20" content_hash_code="97181773" file_path=""/>
<item id="device_management_service" hash_code="117782019" type="0" content_hash_code="127535409" os_list="linux,windows" file_path="components/policy/core/common/cloud/device_management_service.cc"/>
- <item id="devtools_free_data_source" hash_code="22774132" type="0" content_hash_code="136324050" os_list="linux,windows" file_path="chrome/browser/ui/webui/devtools_ui.cc"/>
- <item id="devtools_handle_front_end_messages" hash_code="135636011" type="0" content_hash_code="18422190" os_list="linux,windows" file_path="content/shell/browser/shell_devtools_bindings.cc"/>
- <item id="devtools_hard_coded_data_source" hash_code="111565057" type="0" content_hash_code="46074423" os_list="linux,windows" file_path="chrome/browser/ui/webui/devtools_ui.cc"/>
+ <item id="devtools_free_data_source" hash_code="22774132" type="0" content_hash_code="35733000" os_list="linux,windows" file_path="chrome/browser/ui/webui/devtools_ui.cc"/>
+ <item id="devtools_handle_front_end_messages" hash_code="135636011" type="0" content_hash_code="76808593" os_list="linux,windows" file_path="content/shell/browser/shell_devtools_bindings.cc"/>
+ <item id="devtools_hard_coded_data_source" hash_code="111565057" type="0" content_hash_code="75183720" os_list="linux,windows" file_path="chrome/browser/ui/webui/devtools_ui.cc"/>
<item id="devtools_http_handler" hash_code="49160454" type="0" content_hash_code="88414393" os_list="linux,windows" file_path="content/browser/devtools/devtools_http_handler.cc"/>
- <item id="devtools_interceptor" hash_code="98123737" type="0" content_hash_code="19053470" os_list="linux,windows" file_path="content/browser/devtools/devtools_url_interceptor_request_job.cc"/>
- <item id="devtools_network_resource" hash_code="129652775" type="0" content_hash_code="24059212" os_list="linux,windows" file_path="chrome/browser/devtools/devtools_ui_bindings.cc"/>
+ <item id="devtools_interceptor" hash_code="98123737" type="0" content_hash_code="64591843" os_list="linux,windows" file_path="content/browser/devtools/devtools_url_interceptor_request_job.cc"/>
+ <item id="devtools_network_resource" hash_code="129652775" type="0" content_hash_code="32810159" os_list="linux,windows" file_path="chrome/browser/devtools/devtools_ui_bindings.cc"/>
<item id="dial_get_app_info" hash_code="15952025" type="0" deprecated="2018-02-27" content_hash_code="90542080" file_path=""/>
<item id="dial_get_device_description" hash_code="50422598" type="0" deprecated="2018-02-27" content_hash_code="129827780" file_path=""/>
<item id="dial_url_fetcher" hash_code="41424546" type="0" content_hash_code="129828432" os_list="linux,windows" file_path="chrome/browser/media/router/discovery/dial/dial_url_fetcher.cc"/>
@@ -92,6 +90,7 @@ Refer to README.md for content description and update process.
<item id="download_web_contents_frame" hash_code="56351037" type="0" content_hash_code="3657889" os_list="linux,windows" file_path="content/browser/web_contents/web_contents_impl.cc"/>
<item id="downloads_api_run_async" hash_code="121068967" type="0" content_hash_code="87443585" os_list="linux,windows" file_path="chrome/browser/extensions/api/downloads/downloads_api.cc"/>
<item id="drag_download_file" hash_code="95910019" type="0" content_hash_code="126492858" os_list="linux,windows" file_path="content/browser/download/drag_download_file.cc"/>
+ <item id="expect_ct_reporter" hash_code="57276415" type="0" deprecated="2018-06-20" content_hash_code="130492494" file_path="services/network/expect_ct_reporter.cc"/>
<item id="extension_blacklist" hash_code="59592717" type="0" content_hash_code="116742516" os_list="linux,windows" file_path="chrome/browser/extensions/blacklist_state_fetcher.cc"/>
<item id="extension_crx_fetcher" hash_code="21145003" type="0" content_hash_code="79150319" os_list="linux,windows" file_path="extensions/browser/updater/extension_downloader.cc"/>
<item id="extension_install_signer" hash_code="50464499" type="0" content_hash_code="88088656" os_list="linux,windows" file_path="chrome/browser/extensions/install_signer.cc"/>
@@ -122,8 +121,10 @@ Refer to README.md for content description and update process.
<item id="gcm_subscription" hash_code="56434025" type="0" content_hash_code="61632174" os_list="linux,windows" file_path="components/ntp_snippets/breaking_news/subscription_json_request.cc"/>
<item id="gcm_unregistration" hash_code="119542033" type="0" content_hash_code="30144127" os_list="linux,windows" file_path="google_apis/gcm/engine/unregistration_request.cc"/>
<item id="geo_language_provider" hash_code="52821843" type="1" second_id="96590038" content_hash_code="104675663" os_list="linux,windows" semantics_fields="1" policy_fields="3,4" file_path="components/language/content/browser/geo_language_provider.cc"/>
+ <item id="google_photos_album_names_download" hash_code="65075134" type="0" content_hash_code="124531309" os_list="linux,windows" file_path="chrome/browser/search/background/ntp_background_service.cc"/>
+ <item id="google_photos_metadata_download" hash_code="93441068" type="0" content_hash_code="48786223" os_list="linux,windows" file_path="chrome/browser/search/background/ntp_background_service.cc"/>
<item id="google_url_tracker" hash_code="5492492" type="0" content_hash_code="54474899" os_list="linux,windows" file_path="components/google/core/browser/google_url_tracker.cc"/>
- <item id="headless_url_request" hash_code="29865866" type="0" content_hash_code="76700151" os_list="linux,windows" file_path="headless/public/util/http_url_fetcher.cc"/>
+ <item id="headless_url_request" hash_code="29865866" type="0" deprecated="2018-07-10" content_hash_code="76700151" file_path=""/>
<item id="history_notice_utils_notice" hash_code="102595701" type="1" second_id="110307337" content_hash_code="130829410" os_list="linux,windows" semantics_fields="2,3,4" policy_fields="4" file_path="components/browsing_data/core/history_notice_utils.cc"/>
<item id="history_notice_utils_popup" hash_code="80832574" type="1" second_id="110307337" content_hash_code="30618510" os_list="linux,windows" semantics_fields="2,3,4" policy_fields="4" file_path="components/browsing_data/core/history_notice_utils.cc"/>
<item id="http_server_error_response" hash_code="32197336" type="0" content_hash_code="61082230" os_list="linux,windows" file_path="net/server/http_server.cc"/>
@@ -135,6 +136,7 @@ Refer to README.md for content description and update process.
<item id="invalidation_service" hash_code="72354423" type="0" content_hash_code="78425687" os_list="linux,windows" file_path="components/invalidation/impl/gcm_network_channel.cc"/>
<item id="lib_address_input" hash_code="50816767" type="0" content_hash_code="57977576" os_list="linux,windows" file_path="third_party/libaddressinput/chromium/chrome_metadata_source.cc"/>
<item id="logo_tracker" hash_code="36859107" type="0" content_hash_code="67588075" os_list="linux,windows" file_path="components/search_provider_logos/logo_tracker.cc"/>
+ <item id="md_downloads_dom_handler" hash_code="65603364" type="0" content_hash_code="134779147" os_list="linux,windows" file_path="chrome/browser/ui/webui/md_downloads/md_downloads_dom_handler.cc"/>
<item id="metrics_report_ukm" hash_code="727478" type="0" content_hash_code="40919254" os_list="linux,windows" file_path="components/metrics/net/net_metrics_log_uploader.cc"/>
<item id="metrics_report_uma" hash_code="727528" type="0" content_hash_code="10176197" os_list="linux,windows" file_path="components/metrics/net/net_metrics_log_uploader.cc"/>
<item id="mirroring_get_setup_info" hash_code="78447809" type="0" content_hash_code="112561099" os_list="linux,windows" file_path="components/mirroring/service/session_monitor.cc"/>
@@ -142,17 +144,18 @@ Refer to README.md for content description and update process.
<item id="mojo_context_state" hash_code="93232258" type="0" deprecated="2017-10-20" content_hash_code="124821232" file_path=""/>
<item id="navigation_url_loader" hash_code="63171670" type="0" content_hash_code="129352907" os_list="linux,windows" file_path="content/browser/loader/navigation_url_loader_impl.cc"/>
<item id="net_error_helper" hash_code="60071001" type="0" content_hash_code="68322861" os_list="linux,windows" file_path="chrome/renderer/net/net_error_helper.cc"/>
- <item id="network_location_provider" hash_code="23472048" type="1" second_id="96590038" content_hash_code="41087976" os_list="linux,windows" semantics_fields="1" policy_fields="3,4" file_path="device/geolocation/network_location_provider.cc"/>
- <item id="network_location_request" hash_code="96590038" type="2" content_hash_code="59824433" os_list="linux,windows" semantics_fields="2,3,4,5" policy_fields="-1" file_path="device/geolocation/network_location_request.cc"/>
+ <item id="network_location_provider" hash_code="23472048" type="1" second_id="96590038" content_hash_code="41087976" os_list="linux,windows" semantics_fields="1" policy_fields="3,4" file_path="services/device/geolocation/network_location_provider.cc"/>
+ <item id="network_location_request" hash_code="96590038" type="2" content_hash_code="59824433" os_list="linux,windows" semantics_fields="2,3,4,5" policy_fields="-1" file_path="services/device/geolocation/network_location_request.cc"/>
<item id="network_time_component" hash_code="46188932" type="0" content_hash_code="28051857" os_list="linux,windows" file_path="components/network_time/network_time_tracker.cc"/>
- <item id="notification_image_reporter" hash_code="70126372" type="0" content_hash_code="29754543" os_list="linux,windows" file_path="chrome/browser/safe_browsing/notification_image_reporter.cc"/>
- <item id="ntp_contextual_suggestions_fetch" hash_code="95711309" type="0" content_hash_code="71905054" os_list="linux,windows" file_path="components/ntp_snippets/contextual/contextual_suggestions_fetch.cc"/>
+ <item id="ntp_contextual_suggestions_fetch" hash_code="95711309" type="0" content_hash_code="107035434" os_list="linux,windows" file_path="components/ntp_snippets/contextual/contextual_suggestions_fetch.cc"/>
+ <item id="ntp_icon_source" hash_code="29197139" type="0" content_hash_code="16399294" os_list="linux,windows" file_path="chrome/browser/search/ntp_icon_source.cc"/>
<item id="ntp_snippets_fetch" hash_code="15418154" type="0" content_hash_code="10078959" os_list="linux,windows" file_path="components/ntp_snippets/remote/json_request.cc"/>
<item id="oauth2_access_token_fetcher" hash_code="27915688" type="0" content_hash_code="33501872" os_list="linux,windows" file_path="google_apis/gaia/oauth2_access_token_fetcher_impl.cc"/>
<item id="oauth2_api_call_flow" hash_code="29188932" type="2" content_hash_code="108831236" os_list="linux,windows" policy_fields="-1" file_path="google_apis/gaia/oauth2_api_call_flow.cc"/>
<item id="oauth2_mint_token_flow" hash_code="1112842" type="1" second_id="29188932" content_hash_code="91581432" os_list="linux,windows" semantics_fields="1,2,3,4,5" policy_fields="3,4" file_path="google_apis/gaia/oauth2_mint_token_flow.cc"/>
<item id="ocsp_start_url_request" hash_code="60921996" type="0" content_hash_code="24127780" os_list="linux" file_path="net/cert_net/nss_ocsp.cc"/>
<item id="offline_prefetch" hash_code="19185953" type="0" content_hash_code="57248156" os_list="linux,windows" file_path="components/offline_pages/core/prefetch/prefetch_request_fetcher.cc"/>
+ <item id="omnibox_documentsuggest" hash_code="6055066" type="0" content_hash_code="126973249" os_list="linux,windows" file_path="components/omnibox/browser/document_suggestions_service.cc"/>
<item id="omnibox_navigation_observer" hash_code="61684939" type="0" content_hash_code="70941231" os_list="linux,windows" file_path="chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc"/>
<item id="omnibox_prefetch_image" hash_code="109200878" type="0" content_hash_code="107906693" os_list="linux,windows" file_path="chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc"/>
<item id="omnibox_result_change" hash_code="73107389" type="0" content_hash_code="24802647" os_list="linux,windows" file_path="chrome/browser/ui/omnibox/chrome_omnibox_client.cc"/>
@@ -162,9 +165,11 @@ Refer to README.md for content description and update process.
<item id="omnibox_zerosuggest_experimental" hash_code="3813491" type="0" content_hash_code="22929259" os_list="linux,windows" file_path="components/omnibox/browser/contextual_suggestions_service.cc"/>
<item id="one_google_bar_service" hash_code="78917933" type="0" content_hash_code="46527252" os_list="linux,windows" file_path="chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc"/>
<item id="open_search" hash_code="107267424" type="0" content_hash_code="25715812" os_list="linux,windows" file_path="components/search_engines/template_url_fetcher.cc"/>
+ <item id="origin_policy_loader" hash_code="6483617" type="0" content_hash_code="20680909" os_list="linux,windows" file_path="content/browser/frame_host/origin_policy_throttle.cc"/>
<item id="p2p_invalidator" hash_code="84201371" type="0" content_hash_code="117416248" os_list="linux,windows" file_path="components/invalidation/impl/p2p_invalidator.cc"/>
<item id="parallel_download_job" hash_code="135118587" type="0" content_hash_code="105330419" os_list="linux,windows" file_path="components/download/internal/common/parallel_download_job.cc"/>
<item id="password_protection_request" hash_code="66322287" type="0" content_hash_code="25596947" os_list="linux,windows" file_path="components/safe_browsing/password_protection/password_protection_request.cc"/>
+ <item id="password_requirements_spec_fetch" hash_code="69585116" type="0" content_hash_code="5591260" os_list="linux,windows" file_path="components/autofill/core/browser/password_requirements_spec_fetcher_impl.cc"/>
<item id="payment_instrument_icon_fetcher" hash_code="73309970" type="0" deprecated="2017-09-16" content_hash_code="84709873" file_path=""/>
<item id="payment_manifest_downloader" hash_code="84045030" type="0" content_hash_code="19293316" os_list="linux,windows" file_path="components/payments/core/payment_manifest_downloader.cc"/>
<item id="payments_sync_cards" hash_code="95588446" type="0" content_hash_code="56526513" os_list="linux,windows" file_path="components/autofill/core/browser/payments/payments_client.cc"/>
@@ -207,7 +212,7 @@ Refer to README.md for content description and update process.
<item id="safe_browsing_chunk_backup_request" hash_code="79957943" type="0" content_hash_code="133850277" os_list="linux,windows" file_path="chrome/browser/safe_browsing/protocol_manager.cc"/>
<item id="safe_browsing_client_side_malware_detector" hash_code="102935425" type="0" content_hash_code="79591279" os_list="linux,windows" file_path="chrome/browser/safe_browsing/client_side_detection_service.cc"/>
<item id="safe_browsing_client_side_phishing_detector" hash_code="1313982" type="0" content_hash_code="50199143" os_list="linux,windows" file_path="chrome/browser/safe_browsing/client_side_detection_service.cc"/>
- <item id="safe_browsing_extended_reporting" hash_code="42848942" type="0" content_hash_code="50089173" os_list="linux,windows" file_path="components/safe_browsing/base_ping_manager.cc"/>
+ <item id="safe_browsing_extended_reporting" hash_code="42848942" type="0" content_hash_code="50089173" os_list="linux,windows" file_path="components/safe_browsing/ping_manager.cc"/>
<item id="safe_browsing_feedback" hash_code="44583821" type="0" content_hash_code="114076664" os_list="linux,windows" file_path="chrome/browser/safe_browsing/download_protection/download_feedback.cc"/>
<item id="safe_browsing_g4_update" hash_code="75153841" type="0" content_hash_code="112049516" os_list="linux,windows" file_path="components/safe_browsing/db/v4_update_protocol_manager.cc"/>
<item id="safe_browsing_get_full_hash" hash_code="68745894" type="0" content_hash_code="21739198" os_list="linux,windows" file_path="chrome/browser/safe_browsing/protocol_manager.cc"/>
diff --git a/chromium/tools/v8_context_snapshot/BUILD.gn b/chromium/tools/v8_context_snapshot/BUILD.gn
index b9254d95d95..b119ec095c7 100644
--- a/chromium/tools/v8_context_snapshot/BUILD.gn
+++ b/chromium/tools/v8_context_snapshot/BUILD.gn
@@ -100,7 +100,7 @@ if (use_v8_context_snapshot) {
deps = [
"//gin:gin",
- "//mojo/edk",
+ "//mojo/core/embedder",
"//services/service_manager/public/cpp",
"//third_party/blink/public:blink",
"//v8",
diff --git a/chromium/tools/v8_context_snapshot/DEPS b/chromium/tools/v8_context_snapshot/DEPS
index b62570de637..581e823289d 100644
--- a/chromium/tools/v8_context_snapshot/DEPS
+++ b/chromium/tools/v8_context_snapshot/DEPS
@@ -3,6 +3,6 @@ include_rules = [
"+v8",
"+third_party/blink/public",
"+gin/v8_initializer.h",
- "+mojo/edk/embedder",
+ "+mojo/core/embedder",
"+services/service_manager/public",
]
diff --git a/chromium/tools/v8_context_snapshot/v8_context_snapshot_generator.cc b/chromium/tools/v8_context_snapshot/v8_context_snapshot_generator.cc
index 3a8f3d9f93e..43805201445 100644
--- a/chromium/tools/v8_context_snapshot/v8_context_snapshot_generator.cc
+++ b/chromium/tools/v8_context_snapshot/v8_context_snapshot_generator.cc
@@ -10,7 +10,7 @@
#include "base/task_scheduler/task_scheduler.h"
#include "base/threading/thread_task_runner_handle.h"
#include "gin/v8_initializer.h"
-#include "mojo/edk/embedder/embedder.h"
+#include "mojo/core/embedder/embedder.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/public/web/blink.h"
@@ -55,7 +55,7 @@ int main(int argc, char** argv) {
// Set up environment to make Blink and V8 workable.
base::MessageLoop message_loop;
base::TaskScheduler::CreateAndStartWithDefaultParams("TakeSnapshot");
- mojo::edk::Init();
+ mojo::core::Init();
// Take a snapshot.
SnapshotPlatform platform;
diff --git a/chromium/tools/valgrind/asan/third_party/asan_symbolize.py b/chromium/tools/valgrind/asan/third_party/asan_symbolize.py
index 1a56e44127c..c4ed545f634 100755
--- a/chromium/tools/valgrind/asan/third_party/asan_symbolize.py
+++ b/chromium/tools/valgrind/asan/third_party/asan_symbolize.py
@@ -436,7 +436,13 @@ class SymbolizationLoop(object):
def process_logfile(self):
self.frame_no = 0
- for line in logfile:
+ # We use readline directly instead of an iterator ("for line in logfile")
+ # because the latter introduces extra buffering that is undesirable for
+ # interactive use.
+ while 1:
+ line = logfile.readline()
+ if not line:
+ break
processed = self.process_line(line)
print('\n'.join(processed))
diff --git a/chromium/tools/variations/fieldtrial_to_struct.py b/chromium/tools/variations/fieldtrial_to_struct.py
index 240160fbfd7..91a6ffa1c4a 100755
--- a/chromium/tools/variations/fieldtrial_to_struct.py
+++ b/chromium/tools/variations/fieldtrial_to_struct.py
@@ -3,7 +3,6 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import itertools
import json
import os.path
import sys
@@ -22,6 +21,23 @@ try:
finally:
sys.path.pop(0)
+_platforms = [
+ 'android',
+ 'android_webview',
+ 'chromeos',
+ 'fuchsia',
+ 'ios',
+ 'linux',
+ 'mac',
+ 'windows',
+]
+
+# Convert a platform argument to the matching Platform enum value in
+# components/variations/proto/study.proto.
+def _PlatformEnumValue(platform):
+ assert platform in _platforms
+ return 'Study::PLATFORM_' + platform.upper()
+
def _Load(filename):
"""Loads a JSON file into a Python object and return this object.
"""
@@ -29,14 +45,17 @@ def _Load(filename):
result = json.loads(json_comment_eater.Nom(handle.read()))
return result
-def _LoadFieldTrialConfig(filename, platform):
+def _LoadFieldTrialConfig(filename, platforms):
"""Loads a field trial config JSON and converts it into a format that can be
used by json_to_struct.
"""
- return _FieldTrialConfigToDescription(_Load(filename), platform)
+ return _FieldTrialConfigToDescription(_Load(filename), platforms)
-def _CreateExperiment(experiment_data):
- experiment = {'name': experiment_data['name']}
+def _CreateExperiment(experiment_data, platforms):
+ experiment = {
+ 'name': experiment_data['name'],
+ 'platforms': [_PlatformEnumValue(p) for p in platforms],
+ }
forcing_flags_data = experiment_data.get('forcing_flag')
if forcing_flags_data:
experiment['forcing_flag'] = forcing_flags_data
@@ -52,40 +71,40 @@ def _CreateExperiment(experiment_data):
experiment['disable_features'] = disable_features_data
return experiment
-def _CreateTrial(study_name, experiment_configs, platform):
- """Returns the applicable experiments for |study_name| and |platform|. This
+def _CreateTrial(study_name, experiment_configs, platforms):
+ """Returns the applicable experiments for |study_name| and |platforms|. This
iterates through all of the experiment_configs for |study_name| and picks out
the applicable experiments based off of the valid platforms.
"""
- platform_experiment_lists = [
- config['experiments'] for config in experiment_configs
- if platform in config['platforms']]
- platform_experiments = list(itertools.chain.from_iterable(
- platform_experiment_lists))
+ experiments = []
+ for config in experiment_configs:
+ platform_intersection = [p for p in platforms if p in config['platforms']]
+ if platform_intersection:
+ experiments += [_CreateExperiment(e, platform_intersection)
+ for e in config['experiments']]
return {
'name': study_name,
- 'experiments': [_CreateExperiment(experiment)
- for experiment in platform_experiments],
+ 'experiments': experiments,
}
-def _GenerateTrials(config, platform):
+def _GenerateTrials(config, platforms):
for study_name in sorted(config.keys()):
- study = _CreateTrial(study_name, config[study_name], platform)
+ study = _CreateTrial(study_name, config[study_name], platforms)
# To avoid converting studies with empty experiments (e.g. the study doesn't
- # apply to the target platform), this generator only yields studies that
+ # apply to the target platforms), this generator only yields studies that
# have non-empty experiments.
if study['experiments']:
yield study
-def ConfigToStudies(config, platform):
- """Returns the applicable studies from config for the platform."""
- return [study for study in _GenerateTrials(config, platform)]
+def ConfigToStudies(config, platforms):
+ """Returns the applicable studies from config for the platforms."""
+ return [study for study in _GenerateTrials(config, platforms)]
-def _FieldTrialConfigToDescription(config, platform):
+def _FieldTrialConfigToDescription(config, platforms):
return {
'elements': {
'kFieldTrialConfig': {
- 'studies': ConfigToStudies(config, platform)
+ 'studies': ConfigToStudies(config, platforms)
}
}
}
@@ -100,7 +119,7 @@ def main(arguments):
help='directory to output generated files, relative to destbase.')
parser.add_option('-n', '--namespace',
help='C++ namespace for generated files. e.g search_providers.')
- parser.add_option('-p', '--platform',
+ parser.add_option('-p', '--platform', action='append', choices=_platforms,
help='target platform for the field trial, mandatory.')
parser.add_option('-s', '--schema', help='path to the schema file, '
'mandatory.')
@@ -114,13 +133,7 @@ def main(arguments):
parser.error('You must specify a --schema.')
if not opts.platform:
- parser.error('You must specify a --platform.')
-
- supported_platforms = ['android', 'chromeos', 'fuchsia', 'ios', 'linux',
- 'mac', 'win']
- if opts.platform not in supported_platforms:
- parser.error('\'%s\' is an unknown platform. Supported platforms: %s' %
- (opts.platform, supported_platforms))
+ parser.error('You must specify at least 1 --platform.')
description_filename = os.path.normpath(args[0])
shortroot = opts.output
diff --git a/chromium/tools/variations/fieldtrial_to_struct_unittest.py b/chromium/tools/variations/fieldtrial_to_struct_unittest.py
index b08f0245702..897416cb177 100644
--- a/chromium/tools/variations/fieldtrial_to_struct_unittest.py
+++ b/chromium/tools/variations/fieldtrial_to_struct_unittest.py
@@ -14,7 +14,7 @@ class FieldTrialToStruct(unittest.TestCase):
config = {
'Trial1': [
{
- 'platforms': ['win'],
+ 'platforms': ['windows'],
'experiments': [
{
'name': 'Group1',
@@ -39,13 +39,13 @@ class FieldTrialToStruct(unittest.TestCase):
],
'Trial2': [
{
- 'platforms': ['win'],
+ 'platforms': ['windows'],
'experiments': [{'name': 'OtherGroup'}]
}
],
'TrialWithForcingFlag': [
{
- 'platforms': ['win'],
+ 'platforms': ['windows'],
'experiments': [
{
'name': 'ForcedGroup',
@@ -55,7 +55,8 @@ class FieldTrialToStruct(unittest.TestCase):
}
]
}
- result = fieldtrial_to_struct._FieldTrialConfigToDescription(config, 'win')
+ result = fieldtrial_to_struct._FieldTrialConfigToDescription(config,
+ ['windows'])
expected = {
'elements': {
'kFieldTrialConfig': {
@@ -65,6 +66,7 @@ class FieldTrialToStruct(unittest.TestCase):
'experiments': [
{
'name': 'Group1',
+ 'platforms': ['Study::PLATFORM_WINDOWS'],
'params': [
{'key': 'x', 'value': '1'},
{'key': 'y', 'value': '2'}
@@ -74,6 +76,7 @@ class FieldTrialToStruct(unittest.TestCase):
},
{
'name': 'Group2',
+ 'platforms': ['Study::PLATFORM_WINDOWS'],
'params': [
{'key': 'x', 'value': '3'},
{'key': 'y', 'value': '4'}
@@ -85,13 +88,19 @@ class FieldTrialToStruct(unittest.TestCase):
},
{
'name': 'Trial2',
- 'experiments': [{'name': 'OtherGroup'}]
+ 'experiments': [
+ {
+ 'name': 'OtherGroup',
+ 'platforms': ['Study::PLATFORM_WINDOWS'],
+ }
+ ]
},
{
'name': 'TrialWithForcingFlag',
'experiments': [
{
'name': 'ForcedGroup',
+ 'platforms': ['Study::PLATFORM_WINDOWS'],
'forcing_flag': "my-forcing-flag"
}
]
@@ -106,7 +115,7 @@ class FieldTrialToStruct(unittest.TestCase):
_MULTIPLE_PLATFORM_CONFIG = {
'Trial1': [
{
- 'platforms': ['win', 'ios'],
+ 'platforms': ['windows', 'ios'],
'experiments': [
{
'name': 'Group1',
@@ -139,7 +148,7 @@ class FieldTrialToStruct(unittest.TestCase):
],
'Trial2': [
{
- 'platforms': ['win', 'mac'],
+ 'platforms': ['windows', 'mac'],
'experiments': [{'name': 'OtherGroup'}]
}
]
@@ -147,7 +156,7 @@ class FieldTrialToStruct(unittest.TestCase):
def test_FieldTrialToDescriptionMultipleSinglePlatformMultipleTrial(self):
result = fieldtrial_to_struct._FieldTrialConfigToDescription(
- self._MULTIPLE_PLATFORM_CONFIG, 'ios')
+ self._MULTIPLE_PLATFORM_CONFIG, ['ios'])
expected = {
'elements': {
'kFieldTrialConfig': {
@@ -157,6 +166,7 @@ class FieldTrialToStruct(unittest.TestCase):
'experiments': [
{
'name': 'Group1',
+ 'platforms': ['Study::PLATFORM_IOS'],
'params': [
{'key': 'x', 'value': '1'},
{'key': 'y', 'value': '2'}
@@ -166,6 +176,7 @@ class FieldTrialToStruct(unittest.TestCase):
},
{
'name': 'Group2',
+ 'platforms': ['Study::PLATFORM_IOS'],
'params': [
{'key': 'x', 'value': '3'},
{'key': 'y', 'value': '4'}
@@ -174,7 +185,8 @@ class FieldTrialToStruct(unittest.TestCase):
'disable_features': ['F']
},
{
- 'name': 'IOSOnly'
+ 'name': 'IOSOnly',
+ 'platforms': ['Study::PLATFORM_IOS'],
},
],
},
@@ -187,7 +199,7 @@ class FieldTrialToStruct(unittest.TestCase):
def test_FieldTrialToDescriptionMultipleSinglePlatformSingleTrial(self):
result = fieldtrial_to_struct._FieldTrialConfigToDescription(
- self._MULTIPLE_PLATFORM_CONFIG, 'mac')
+ self._MULTIPLE_PLATFORM_CONFIG, ['mac'])
expected = {
'elements': {
'kFieldTrialConfig': {
@@ -197,6 +209,7 @@ class FieldTrialToStruct(unittest.TestCase):
'experiments': [
{
'name': 'OtherGroup',
+ 'platforms': ['Study::PLATFORM_MAC'],
},
],
},
@@ -216,7 +229,7 @@ class FieldTrialToStruct(unittest.TestCase):
fieldtrial_to_struct.main([
'--schema=' + schema,
'--output=' + test_output_filename,
- '--platform=win',
+ '--platform=windows',
'--year=2015',
unittest_data_dir + 'test_config.json'
])
diff --git a/chromium/tools/variations/fieldtrial_util.py b/chromium/tools/variations/fieldtrial_util.py
index 8fea8fb1174..689cdffbd8a 100644
--- a/chromium/tools/variations/fieldtrial_util.py
+++ b/chromium/tools/variations/fieldtrial_util.py
@@ -50,15 +50,15 @@ def _CheckForDuplicateFeatures(enable_features, disable_features):
', '.join(features_in_both))
# Generate a list of command-line switches to enable field trials for the
-# provided config_path and platform.
-def GenerateArgs(config_path, platform):
+# provided config_path and platforms.
+def GenerateArgs(config_path, platforms):
try:
with open(config_path, 'r') as config_file:
config = json.load(config_file)
except (IOError, ValueError):
return []
- platform_studies = fieldtrial_to_struct.ConfigToStudies(config, platform)
+ platform_studies = fieldtrial_to_struct.ConfigToStudies(config, platforms)
studies = []
params = []
@@ -108,13 +108,14 @@ def main():
exit(-1)
print_shell_cmd = len(sys.argv) >= 4 and sys.argv[3] == 'shell_cmd'
- supported_platforms = ['android', 'chromeos', 'ios', 'linux', 'mac', 'win']
+ supported_platforms = ['android', 'android_webview', 'chromeos', 'ios',
+ 'linux', 'mac', 'windows']
if sys.argv[2] not in supported_platforms:
print ('\'%s\' is an unknown platform. Supported platforms: %s' %
(sys.argv[2], supported_platforms))
exit(-1)
- generated_args = GenerateArgs(sys.argv[1], sys.argv[2])
+ generated_args = GenerateArgs(sys.argv[1], [sys.argv[2]])
if print_shell_cmd:
print " ".join(map((lambda arg: '"{0}"'.format(arg)), generated_args))
else:
diff --git a/chromium/tools/variations/fieldtrial_util_unittest.py b/chromium/tools/variations/fieldtrial_util_unittest.py
index 1e0db3c8aff..c0e61066242 100644
--- a/chromium/tools/variations/fieldtrial_util_unittest.py
+++ b/chromium/tools/variations/fieldtrial_util_unittest.py
@@ -17,26 +17,26 @@ class FieldTrialUtilUnittest(unittest.TestCase):
try:
base_file.write(config)
base_file.close()
- result = fieldtrial_util.GenerateArgs(base_file.name, platform)
+ result = fieldtrial_util.GenerateArgs(base_file.name, [platform])
finally:
os.unlink(base_file.name)
return result
def test_GenArgsEmptyPaths(self):
- args = fieldtrial_util.GenerateArgs('', 'linux')
+ args = fieldtrial_util.GenerateArgs('', ['linux'])
self.assertEqual([], args)
def test_GenArgsOneConfig(self):
config = '''{
"BrowserBlackList": [
{
- "platforms": ["win"],
+ "platforms": ["windows"],
"experiments": [{"name": "Enabled"}]
}
],
"SimpleParams": [
{
- "platforms": ["win"],
+ "platforms": ["windows"],
"experiments": [
{
"name": "Default",
@@ -48,7 +48,7 @@ class FieldTrialUtilUnittest(unittest.TestCase):
],
"c": [
{
- "platforms": ["win"],
+ "platforms": ["windows"],
"experiments": [
{
"name": "d.",
@@ -60,7 +60,7 @@ class FieldTrialUtilUnittest(unittest.TestCase):
}
]
}'''
- result = self.runGenerateArgs(config, 'win')
+ result = self.runGenerateArgs(config, 'windows')
self.assertEqual(['--force-fieldtrials='
'BrowserBlackList/Enabled/SimpleParams/Default/c/d.',
'--force-fieldtrial-params='
@@ -73,7 +73,7 @@ class FieldTrialUtilUnittest(unittest.TestCase):
config = '''{
"X": [
{
- "platforms": ["win"],
+ "platforms": ["windows"],
"experiments": [
{
"name": "x",
@@ -84,7 +84,7 @@ class FieldTrialUtilUnittest(unittest.TestCase):
],
"Y": [
{
- "platforms": ["win"],
+ "platforms": ["windows"],
"experiments": [
{
"name": "Default",
@@ -95,7 +95,7 @@ class FieldTrialUtilUnittest(unittest.TestCase):
]
}'''
with self.assertRaises(Exception) as raised:
- self.runGenerateArgs(config, 'win')
+ self.runGenerateArgs(config, 'windows')
self.assertEqual('Duplicate feature(s) in enable_features: x',
str(raised.exception))
@@ -103,7 +103,7 @@ class FieldTrialUtilUnittest(unittest.TestCase):
config = '''{
"X": [
{
- "platforms": ["win"],
+ "platforms": ["windows"],
"experiments": [
{
"name": "x",
@@ -114,7 +114,7 @@ class FieldTrialUtilUnittest(unittest.TestCase):
],
"Y": [
{
- "platforms": ["win"],
+ "platforms": ["windows"],
"experiments": [
{
"name": "Default",
@@ -125,7 +125,7 @@ class FieldTrialUtilUnittest(unittest.TestCase):
]
}'''
with self.assertRaises(Exception) as raised:
- self.runGenerateArgs(config, 'win')
+ self.runGenerateArgs(config, 'windows')
self.assertEqual('Duplicate feature(s) in enable_features: y, z',
str(raised.exception))
@@ -134,7 +134,7 @@ class FieldTrialUtilUnittest(unittest.TestCase):
config = '''{
"X": [
{
- "platforms": ["win"],
+ "platforms": ["windows"],
"experiments": [
{
"name": "x",
@@ -145,7 +145,7 @@ class FieldTrialUtilUnittest(unittest.TestCase):
],
"Y": [
{
- "platforms": ["win"],
+ "platforms": ["windows"],
"experiments": [
{
"name": "Default",
@@ -156,7 +156,7 @@ class FieldTrialUtilUnittest(unittest.TestCase):
]
}'''
with self.assertRaises(Exception) as raised:
- self.runGenerateArgs(config, 'win')
+ self.runGenerateArgs(config, 'windows')
self.assertEqual('Conflicting features set as both enabled and disabled: x',
str(raised.exception))
diff --git a/chromium/tools/variations/unittest_data/DEPS b/chromium/tools/variations/unittest_data/DEPS
new file mode 100644
index 00000000000..e6d615ab083
--- /dev/null
+++ b/chromium/tools/variations/unittest_data/DEPS
@@ -0,0 +1,3 @@
+specific_include_rules = {
+ "expected_output.h": ["+components/variations/proto/study.pb.h"]
+}
diff --git a/chromium/tools/variations/unittest_data/expected_output.cc b/chromium/tools/variations/unittest_data/expected_output.cc
index 6feaabac15f..f7cbab76e38 100644
--- a/chromium/tools/variations/unittest_data/expected_output.cc
+++ b/chromium/tools/variations/unittest_data/expected_output.cc
@@ -10,9 +10,14 @@
#include "test_output.h"
+const Study::Platform array_kFieldTrialConfig_platforms_3[] = {
+ Study::PLATFORM_WINDOWS,
+};
const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_2[] = {
{
"ForcedGroup",
+ array_kFieldTrialConfig_platforms_3,
+ 1,
NULL,
0,
NULL,
@@ -25,9 +30,14 @@ const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_2[] = {
const char* const array_kFieldTrialConfig_enable_features_1[] = {
"X",
};
+const Study::Platform array_kFieldTrialConfig_platforms_2[] = {
+ Study::PLATFORM_WINDOWS,
+};
const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_1[] = {
{
"TestGroup3",
+ array_kFieldTrialConfig_platforms_2,
+ 1,
NULL,
0,
array_kFieldTrialConfig_enable_features_1,
@@ -54,6 +64,9 @@ const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params_0[] = {
"4",
},
};
+const Study::Platform array_kFieldTrialConfig_platforms_1[] = {
+ Study::PLATFORM_WINDOWS,
+};
const char* const array_kFieldTrialConfig_disable_features[] = {
"C",
};
@@ -71,9 +84,14 @@ const FieldTrialTestingExperimentParams array_kFieldTrialConfig_params[] = {
"2",
},
};
+const Study::Platform array_kFieldTrialConfig_platforms_0[] = {
+ Study::PLATFORM_WINDOWS,
+};
const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = {
{
"TestGroup2",
+ array_kFieldTrialConfig_platforms_0,
+ 1,
array_kFieldTrialConfig_params,
2,
array_kFieldTrialConfig_enable_features,
@@ -84,6 +102,8 @@ const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = {
},
{
"TestGroup2-2",
+ array_kFieldTrialConfig_platforms_1,
+ 1,
array_kFieldTrialConfig_params_0,
2,
array_kFieldTrialConfig_enable_features_0,
@@ -93,9 +113,14 @@ const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments_0[] = {
NULL,
},
};
+const Study::Platform array_kFieldTrialConfig_platforms[] = {
+ Study::PLATFORM_WINDOWS,
+};
const FieldTrialTestingExperiment array_kFieldTrialConfig_experiments[] = {
{
"TestGroup1",
+ array_kFieldTrialConfig_platforms,
+ 1,
NULL,
0,
NULL,
diff --git a/chromium/tools/variations/unittest_data/expected_output.h b/chromium/tools/variations/unittest_data/expected_output.h
index 2d78e7087c5..641ff31dded 100644
--- a/chromium/tools/variations/unittest_data/expected_output.h
+++ b/chromium/tools/variations/unittest_data/expected_output.h
@@ -12,6 +12,7 @@
#include <cstddef>
+#include "components/variations/proto/study.pb.h"
struct FieldTrialTestingExperimentParams {
const char* const key;
@@ -20,6 +21,8 @@ struct FieldTrialTestingExperimentParams {
struct FieldTrialTestingExperiment {
const char* const name;
+ const Study::Platform * platforms;
+ const size_t platforms_size;
const FieldTrialTestingExperimentParams * params;
const size_t params_size;
const char* const * enable_features;
diff --git a/chromium/tools/variations/unittest_data/test_config.json b/chromium/tools/variations/unittest_data/test_config.json
index 4a7b94ca385..63662d02fb8 100644
--- a/chromium/tools/variations/unittest_data/test_config.json
+++ b/chromium/tools/variations/unittest_data/test_config.json
@@ -1,13 +1,13 @@
{
"TestTrial1": [
{
- "platforms": ["win"],
+ "platforms": ["windows"],
"experiments": [{"name": "TestGroup1"}]
}
],
"TestTrial2": [
{
- "platforms": ["win"],
+ "platforms": ["windows"],
"experiments": [
{
"name": "TestGroup2",
@@ -32,13 +32,13 @@
],
"TestTrial3": [
{
- "platforms": ["win"],
+ "platforms": ["windows"],
"experiments": [{"name": "TestGroup3", "enable_features": ["X"]}]
}
],
"TrialWithForcingFlag": [
{
- "platforms": ["win"],
+ "platforms": ["windows"],
"experiments": [
{
"name": "ForcedGroup",
diff --git a/chromium/tools/win/ShowGlobals/ShowGlobals.cc b/chromium/tools/win/ShowGlobals/ShowGlobals.cc
index 3dcea86c0c1..82f78e2a3e1 100644
--- a/chromium/tools/win/ShowGlobals/ShowGlobals.cc
+++ b/chromium/tools/win/ShowGlobals/ShowGlobals.cc
@@ -105,6 +105,17 @@ bool DumpInterestingGlobals(IDiaSymbol* global, const wchar_t* filename) {
for (ULONG celt = 0;
SUCCEEDED(enum_symbols->Next(1, &symbol, &celt)) && (celt == 1);
symbol.Release()) {
+ DWORD location_type = 0;
+ // If we can't get the location type then we assume the variable is not of
+ // interest.
+ if (FAILED(symbol->get_locationType(&location_type))) {
+ continue;
+ }
+ // Ignore location types that don't actually correspond to statics and
+ // globals.
+ if (location_type != LocIsStatic)
+ continue;
+
// If we call get_length on symbol it works for functions but not for
// data. For some reason for data we have to call get_type() to get
// another IDiaSymbol object which we can query for length.
diff --git a/chromium/tools/win/ShowGlobals/ShowGlobals.vcxproj b/chromium/tools/win/ShowGlobals/ShowGlobals.vcxproj
index 177b9230486..dc373b7df45 100644
--- a/chromium/tools/win/ShowGlobals/ShowGlobals.vcxproj
+++ b/chromium/tools/win/ShowGlobals/ShowGlobals.vcxproj
@@ -22,32 +22,32 @@
<ProjectGuid>{6D21CDE5-0037-4065-8833-6F11E6094884}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>ShowGlobals</RootNamespace>
- <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ <WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
+ <PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
+ <PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
+ <PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
+ <PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
diff --git a/chromium/tools/win/static_initializers/static_initializers.cc b/chromium/tools/win/static_initializers/static_initializers.cc
index 2800ac385aa..df76775b42b 100644
--- a/chromium/tools/win/static_initializers/static_initializers.cc
+++ b/chromium/tools/win/static_initializers/static_initializers.cc
@@ -37,11 +37,23 @@ static bool LoadDataFromPdb(const wchar_t* filename,
wchar_t ext[MAX_PATH];
_wsplitpath_s(filename, NULL, 0, NULL, 0, NULL, 0, ext, MAX_PATH);
- // Open and prepare the debug data associated with the executable.
- hr = (*source)->loadDataForExe(filename, search_path, NULL);
- if (FAILED(hr)) {
- printf("loadDataForExe failed - HRESULT = %08lX\n", hr);
- return false;
+ if (wcsicmp(ext, L".pdb") == 0) {
+ // Open and prepare the debug data specified.
+ hr = (*source)->loadDataFromPdb(filename);
+ if (FAILED(hr)) {
+ printf("loadDataFromPdb failed - HRESULT = %08lX\n", hr);
+ return false;
+ }
+ } else {
+ // Open and prepare the debug data associated with the executable.
+ hr = (*source)->loadDataForExe(filename, search_path, NULL);
+ if (FAILED(hr)) {
+ printf("loadDataForExe failed - HRESULT = %08lX\n", hr);
+ printf(
+ "Try copying the .pdb beside the PE file or passing the .pdb path "
+ "to this tool directly.");
+ return false;
+ }
}
// Open a session for querying symbols.
diff --git a/chromium/tools/xdisplaycheck/BUILD.gn b/chromium/tools/xdisplaycheck/BUILD.gn
index 064305aa04e..717c31a5183 100644
--- a/chromium/tools/xdisplaycheck/BUILD.gn
+++ b/chromium/tools/xdisplaycheck/BUILD.gn
@@ -8,8 +8,4 @@ executable("xdisplaycheck") {
]
configs += [ "//build/config/linux:x11" ]
-
- deps = [
- "//build/config:exe_and_shlib_deps",
- ]
}